summaryrefslogtreecommitdiffstats
path: root/src/cmd/compile/internal/ssa
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/ssa')
-rw-r--r--src/cmd/compile/internal/ssa/README.md209
-rw-r--r--src/cmd/compile/internal/ssa/TODO24
-rw-r--r--src/cmd/compile/internal/ssa/addressingmodes.go460
-rw-r--r--src/cmd/compile/internal/ssa/biasedsparsemap.go112
-rw-r--r--src/cmd/compile/internal/ssa/block.go371
-rw-r--r--src/cmd/compile/internal/ssa/branchelim.go449
-rw-r--r--src/cmd/compile/internal/ssa/branchelim_test.go172
-rw-r--r--src/cmd/compile/internal/ssa/cache.go81
-rw-r--r--src/cmd/compile/internal/ssa/check.go597
-rw-r--r--src/cmd/compile/internal/ssa/checkbce.go35
-rw-r--r--src/cmd/compile/internal/ssa/compile.go573
-rw-r--r--src/cmd/compile/internal/ssa/config.go390
-rw-r--r--src/cmd/compile/internal/ssa/copyelim.go84
-rw-r--r--src/cmd/compile/internal/ssa/copyelim_test.go41
-rw-r--r--src/cmd/compile/internal/ssa/critical.go116
-rw-r--r--src/cmd/compile/internal/ssa/cse.go373
-rw-r--r--src/cmd/compile/internal/ssa/cse_test.go129
-rw-r--r--src/cmd/compile/internal/ssa/deadcode.go393
-rw-r--r--src/cmd/compile/internal/ssa/deadcode_test.go161
-rw-r--r--src/cmd/compile/internal/ssa/deadstore.go348
-rw-r--r--src/cmd/compile/internal/ssa/deadstore_test.go129
-rw-r--r--src/cmd/compile/internal/ssa/debug.go1187
-rw-r--r--src/cmd/compile/internal/ssa/debug_test.go1020
-rw-r--r--src/cmd/compile/internal/ssa/decompose.go449
-rw-r--r--src/cmd/compile/internal/ssa/dom.go302
-rw-r--r--src/cmd/compile/internal/ssa/dom_test.go608
-rw-r--r--src/cmd/compile/internal/ssa/expand_calls.go975
-rw-r--r--src/cmd/compile/internal/ssa/export_test.go209
-rw-r--r--src/cmd/compile/internal/ssa/flagalloc.go269
-rw-r--r--src/cmd/compile/internal/ssa/flags_amd64_test.s31
-rw-r--r--src/cmd/compile/internal/ssa/flags_arm64_test.s32
-rw-r--r--src/cmd/compile/internal/ssa/flags_test.go108
-rw-r--r--src/cmd/compile/internal/ssa/func.go799
-rw-r--r--src/cmd/compile/internal/ssa/func_test.go484
-rw-r--r--src/cmd/compile/internal/ssa/fuse.go243
-rw-r--r--src/cmd/compile/internal/ssa/fuse_comparisons.go157
-rw-r--r--src/cmd/compile/internal/ssa/fuse_test.go203
-rw-r--r--src/cmd/compile/internal/ssa/gen/386.rules1111
-rw-r--r--src/cmd/compile/internal/ssa/gen/386Ops.go585
-rw-r--r--src/cmd/compile/internal/ssa/gen/386splitload.rules11
-rw-r--r--src/cmd/compile/internal/ssa/gen/AMD64.rules2216
-rw-r--r--src/cmd/compile/internal/ssa/gen/AMD64Ops.go946
-rw-r--r--src/cmd/compile/internal/ssa/gen/AMD64splitload.rules45
-rw-r--r--src/cmd/compile/internal/ssa/gen/ARM.rules1475
-rw-r--r--src/cmd/compile/internal/ssa/gen/ARM64.rules2789
-rw-r--r--src/cmd/compile/internal/ssa/gen/ARM64Ops.go762
-rw-r--r--src/cmd/compile/internal/ssa/gen/ARMOps.go600
-rw-r--r--src/cmd/compile/internal/ssa/gen/MIPS.rules697
-rw-r--r--src/cmd/compile/internal/ssa/gen/MIPS64.rules678
-rw-r--r--src/cmd/compile/internal/ssa/gen/MIPS64Ops.go482
-rw-r--r--src/cmd/compile/internal/ssa/gen/MIPSOps.go439
-rw-r--r--src/cmd/compile/internal/ssa/gen/PPC64.rules1461
-rw-r--r--src/cmd/compile/internal/ssa/gen/PPC64Ops.go717
-rw-r--r--src/cmd/compile/internal/ssa/gen/README7
-rw-r--r--src/cmd/compile/internal/ssa/gen/RISCV64.rules737
-rw-r--r--src/cmd/compile/internal/ssa/gen/RISCV64Ops.go464
-rw-r--r--src/cmd/compile/internal/ssa/gen/S390X.rules1695
-rw-r--r--src/cmd/compile/internal/ssa/gen/S390XOps.go816
-rw-r--r--src/cmd/compile/internal/ssa/gen/Wasm.rules408
-rw-r--r--src/cmd/compile/internal/ssa/gen/WasmOps.go278
-rwxr-xr-xsrc/cmd/compile/internal/ssa/gen/cover.bash26
-rw-r--r--src/cmd/compile/internal/ssa/gen/dec.rules92
-rw-r--r--src/cmd/compile/internal/ssa/gen/dec64.rules396
-rw-r--r--src/cmd/compile/internal/ssa/gen/dec64Ops.go20
-rw-r--r--src/cmd/compile/internal/ssa/gen/decArgs.rules58
-rw-r--r--src/cmd/compile/internal/ssa/gen/decArgsOps.go20
-rw-r--r--src/cmd/compile/internal/ssa/gen/decOps.go20
-rw-r--r--src/cmd/compile/internal/ssa/gen/generic.rules2535
-rw-r--r--src/cmd/compile/internal/ssa/gen/genericOps.go620
-rw-r--r--src/cmd/compile/internal/ssa/gen/main.go541
-rw-r--r--src/cmd/compile/internal/ssa/gen/rulegen.go1856
-rw-r--r--src/cmd/compile/internal/ssa/html.go1319
-rw-r--r--src/cmd/compile/internal/ssa/id.go28
-rw-r--r--src/cmd/compile/internal/ssa/layout.go180
-rw-r--r--src/cmd/compile/internal/ssa/lca.go123
-rw-r--r--src/cmd/compile/internal/ssa/lca_test.go88
-rw-r--r--src/cmd/compile/internal/ssa/likelyadjust.go575
-rw-r--r--src/cmd/compile/internal/ssa/location.go88
-rw-r--r--src/cmd/compile/internal/ssa/loopbce.go346
-rw-r--r--src/cmd/compile/internal/ssa/loopreschedchecks.go499
-rw-r--r--src/cmd/compile/internal/ssa/looprotate.go106
-rw-r--r--src/cmd/compile/internal/ssa/lower.go39
-rw-r--r--src/cmd/compile/internal/ssa/magic.go424
-rw-r--r--src/cmd/compile/internal/ssa/magic_test.go410
-rw-r--r--src/cmd/compile/internal/ssa/nilcheck.go336
-rw-r--r--src/cmd/compile/internal/ssa/nilcheck_test.go434
-rw-r--r--src/cmd/compile/internal/ssa/numberlines.go271
-rw-r--r--src/cmd/compile/internal/ssa/op.go405
-rw-r--r--src/cmd/compile/internal/ssa/opGen.go36677
-rw-r--r--src/cmd/compile/internal/ssa/opt.go10
-rw-r--r--src/cmd/compile/internal/ssa/passbm_test.go101
-rw-r--r--src/cmd/compile/internal/ssa/phielim.go69
-rw-r--r--src/cmd/compile/internal/ssa/phiopt.go176
-rw-r--r--src/cmd/compile/internal/ssa/poset.go1359
-rw-r--r--src/cmd/compile/internal/ssa/poset_test.go800
-rw-r--r--src/cmd/compile/internal/ssa/print.go159
-rw-r--r--src/cmd/compile/internal/ssa/prove.go1426
-rw-r--r--src/cmd/compile/internal/ssa/redblack32.go429
-rw-r--r--src/cmd/compile/internal/ssa/redblack32_test.go274
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go2696
-rw-r--r--src/cmd/compile/internal/ssa/regalloc_test.go230
-rw-r--r--src/cmd/compile/internal/ssa/rewrite.go1892
-rw-r--r--src/cmd/compile/internal/ssa/rewrite386.go12575
-rw-r--r--src/cmd/compile/internal/ssa/rewrite386splitload.go162
-rw-r--r--src/cmd/compile/internal/ssa/rewriteAMD64.go35989
-rw-r--r--src/cmd/compile/internal/ssa/rewriteAMD64splitload.go853
-rw-r--r--src/cmd/compile/internal/ssa/rewriteARM.go22017
-rw-r--r--src/cmd/compile/internal/ssa/rewriteARM64.go28662
-rw-r--r--src/cmd/compile/internal/ssa/rewriteCond_test.go597
-rw-r--r--src/cmd/compile/internal/ssa/rewriteMIPS.go7535
-rw-r--r--src/cmd/compile/internal/ssa/rewriteMIPS64.go8040
-rw-r--r--src/cmd/compile/internal/ssa/rewritePPC64.go18258
-rw-r--r--src/cmd/compile/internal/ssa/rewriteRISCV64.go6604
-rw-r--r--src/cmd/compile/internal/ssa/rewriteS390X.go17859
-rw-r--r--src/cmd/compile/internal/ssa/rewriteWasm.go4905
-rw-r--r--src/cmd/compile/internal/ssa/rewrite_test.go220
-rw-r--r--src/cmd/compile/internal/ssa/rewritedec.go415
-rw-r--r--src/cmd/compile/internal/ssa/rewritedec64.go2464
-rw-r--r--src/cmd/compile/internal/ssa/rewritedecArgs.go247
-rw-r--r--src/cmd/compile/internal/ssa/rewritegeneric.go25091
-rw-r--r--src/cmd/compile/internal/ssa/schedule.go503
-rw-r--r--src/cmd/compile/internal/ssa/schedule_test.go101
-rw-r--r--src/cmd/compile/internal/ssa/shift_test.go107
-rw-r--r--src/cmd/compile/internal/ssa/shortcircuit.go510
-rw-r--r--src/cmd/compile/internal/ssa/shortcircuit_test.go53
-rw-r--r--src/cmd/compile/internal/ssa/sizeof_test.go39
-rw-r--r--src/cmd/compile/internal/ssa/softfloat.go79
-rw-r--r--src/cmd/compile/internal/ssa/sparsemap.go93
-rw-r--r--src/cmd/compile/internal/ssa/sparseset.go79
-rw-r--r--src/cmd/compile/internal/ssa/sparsetree.go235
-rw-r--r--src/cmd/compile/internal/ssa/sparsetreemap.go189
-rw-r--r--src/cmd/compile/internal/ssa/stackalloc.go420
-rw-r--r--src/cmd/compile/internal/ssa/stackframe.go10
-rw-r--r--src/cmd/compile/internal/ssa/stmtlines_test.go132
-rw-r--r--src/cmd/compile/internal/ssa/testdata/hist.dlv-dbg.nexts99
-rw-r--r--src/cmd/compile/internal/ssa/testdata/hist.dlv-opt.nexts94
-rw-r--r--src/cmd/compile/internal/ssa/testdata/hist.gdb-dbg.nexts123
-rw-r--r--src/cmd/compile/internal/ssa/testdata/hist.gdb-opt.nexts143
-rw-r--r--src/cmd/compile/internal/ssa/testdata/hist.go106
-rw-r--r--src/cmd/compile/internal/ssa/testdata/i22558.dlv-dbg.nexts11
-rw-r--r--src/cmd/compile/internal/ssa/testdata/i22558.gdb-dbg.nexts11
-rw-r--r--src/cmd/compile/internal/ssa/testdata/i22558.go51
-rw-r--r--src/cmd/compile/internal/ssa/testdata/i22600.dlv-dbg-race.nexts7
-rw-r--r--src/cmd/compile/internal/ssa/testdata/i22600.gdb-dbg-race.nexts7
-rw-r--r--src/cmd/compile/internal/ssa/testdata/i22600.go27
-rw-r--r--src/cmd/compile/internal/ssa/testdata/infloop.dlv-opt.nexts12
-rw-r--r--src/cmd/compile/internal/ssa/testdata/infloop.gdb-opt.nexts4
-rw-r--r--src/cmd/compile/internal/ssa/testdata/infloop.go16
-rw-r--r--src/cmd/compile/internal/ssa/testdata/scopes.dlv-dbg.nexts56
-rw-r--r--src/cmd/compile/internal/ssa/testdata/scopes.dlv-opt.nexts46
-rw-r--r--src/cmd/compile/internal/ssa/testdata/scopes.gdb-dbg.nexts64
-rw-r--r--src/cmd/compile/internal/ssa/testdata/scopes.gdb-opt.nexts55
-rw-r--r--src/cmd/compile/internal/ssa/testdata/scopes.go107
-rw-r--r--src/cmd/compile/internal/ssa/tighten.go164
-rw-r--r--src/cmd/compile/internal/ssa/trim.go172
-rw-r--r--src/cmd/compile/internal/ssa/tuple.go59
-rw-r--r--src/cmd/compile/internal/ssa/value.go494
-rw-r--r--src/cmd/compile/internal/ssa/writebarrier.go616
-rw-r--r--src/cmd/compile/internal/ssa/writebarrier_test.go56
-rw-r--r--src/cmd/compile/internal/ssa/xposmap.go116
-rw-r--r--src/cmd/compile/internal/ssa/zcse.go79
-rw-r--r--src/cmd/compile/internal/ssa/zeroextension_test.go34
162 files changed, 287767 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/README.md b/src/cmd/compile/internal/ssa/README.md
new file mode 100644
index 0000000..4483c2c
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/README.md
@@ -0,0 +1,209 @@
+<!---
+// Copyright 2018 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.
+-->
+
+## Introduction to the Go compiler's SSA backend
+
+This package contains the compiler's Static Single Assignment form component. If
+you're not familiar with SSA, its [Wikipedia
+article](https://en.wikipedia.org/wiki/Static_single_assignment_form) is a good
+starting point.
+
+It is recommended that you first read [cmd/compile/README.md](../../README.md)
+if you are not familiar with the Go compiler already. That document gives an
+overview of the compiler, and explains what is SSA's part and purpose in it.
+
+### Key concepts
+
+The names described below may be loosely related to their Go counterparts, but
+note that they are not equivalent. For example, a Go block statement has a
+variable scope, yet SSA has no notion of variables nor variable scopes.
+
+It may also be surprising that values and blocks are named after their unique
+sequential IDs. They rarely correspond to named entities in the original code,
+such as variables or function parameters. The sequential IDs also allow the
+compiler to avoid maps, and it is always possible to track back the values to Go
+code using debug and position information.
+
+#### Values
+
+Values are the basic building blocks of SSA. Per SSA's very definition, a
+value is defined exactly once, but it may be used any number of times. A value
+mainly consists of a unique identifier, an operator, a type, and some arguments.
+
+An operator or `Op` describes the operation that computes the value. The
+semantics of each operator can be found in `gen/*Ops.go`. For example, `OpAdd8`
+takes two value arguments holding 8-bit integers and results in their addition.
+Here is a possible SSA representation of the addition of two `uint8` values:
+
+ // var c uint8 = a + b
+ v4 = Add8 <uint8> v2 v3
+
+A value's type will usually be a Go type. For example, the value in the example
+above has a `uint8` type, and a constant boolean value will have a `bool` type.
+However, certain types don't come from Go and are special; below we will cover
+`memory`, the most common of them.
+
+See [value.go](value.go) for more information.
+
+#### Memory types
+
+`memory` represents the global memory state. An `Op` that takes a memory
+argument depends on that memory state, and an `Op` which has the memory type
+impacts the state of memory. This ensures that memory operations are kept in the
+right order. For example:
+
+ // *a = 3
+ // *b = *a
+ v10 = Store <mem> {int} v6 v8 v1
+ v14 = Store <mem> {int} v7 v8 v10
+
+Here, `Store` stores its second argument (of type `int`) into the first argument
+(of type `*int`). The last argument is the memory state; since the second store
+depends on the memory value defined by the first store, the two stores cannot be
+reordered.
+
+See [cmd/compile/internal/types/type.go](../types/type.go) for more information.
+
+#### Blocks
+
+A block represents a basic block in the control flow graph of a function. It is,
+essentially, a list of values that define the operation of this block. Besides
+the list of values, blocks mainly consist of a unique identifier, a kind, and a
+list of successor blocks.
+
+The simplest kind is a `plain` block; it simply hands the control flow to
+another block, thus its successors list contains one block.
+
+Another common block kind is the `exit` block. These have a final value, called
+control value, which must return a memory state. This is necessary for functions
+to return some values, for example - the caller needs some memory state to
+depend on, to ensure that it receives those return values correctly.
+
+The last important block kind we will mention is the `if` block. It has a single
+control value that must be a boolean value, and it has exactly two successor
+blocks. The control flow is handed to the first successor if the bool is true,
+and to the second otherwise.
+
+Here is a sample if-else control flow represented with basic blocks:
+
+ // func(b bool) int {
+ // if b {
+ // return 2
+ // }
+ // return 3
+ // }
+ b1:
+ v1 = InitMem <mem>
+ v2 = SP <uintptr>
+ v5 = Addr <*int> {~r1} v2
+ v6 = Arg <bool> {b}
+ v8 = Const64 <int> [2]
+ v12 = Const64 <int> [3]
+ If v6 -> b2 b3
+ b2: <- b1
+ v10 = VarDef <mem> {~r1} v1
+ v11 = Store <mem> {int} v5 v8 v10
+ Ret v11
+ b3: <- b1
+ v14 = VarDef <mem> {~r1} v1
+ v15 = Store <mem> {int} v5 v12 v14
+ Ret v15
+
+<!---
+TODO: can we come up with a shorter example that still shows the control flow?
+-->
+
+See [block.go](block.go) for more information.
+
+#### Functions
+
+A function represents a function declaration along with its body. It mainly
+consists of a name, a type (its signature), a list of blocks that form its body,
+and the entry block within said list.
+
+When a function is called, the control flow is handed to its entry block. If the
+function terminates, the control flow will eventually reach an exit block, thus
+ending the function call.
+
+Note that a function may have zero or multiple exit blocks, just like a Go
+function can have any number of return points, but it must have exactly one
+entry point block.
+
+Also note that some SSA functions are autogenerated, such as the hash functions
+for each type used as a map key.
+
+For example, this is what an empty function can look like in SSA, with a single
+exit block that returns an uninteresting memory state:
+
+ foo func()
+ b1:
+ v1 = InitMem <mem>
+ Ret v1
+
+See [func.go](func.go) for more information.
+
+### Compiler passes
+
+Having a program in SSA form is not very useful on its own. Its advantage lies
+in how easy it is to write optimizations that modify the program to make it
+better. The way the Go compiler accomplishes this is via a list of passes.
+
+Each pass transforms a SSA function in some way. For example, a dead code
+elimination pass will remove blocks and values that it can prove will never be
+executed, and a nil check elimination pass will remove nil checks which it can
+prove to be redundant.
+
+Compiler passes work on one function at a time, and by default run sequentially
+and exactly once.
+
+The `lower` pass is special; it converts the SSA representation from being
+machine-independent to being machine-dependent. That is, some abstract operators
+are replaced with their non-generic counterparts, potentially reducing or
+increasing the final number of values.
+
+<!---
+TODO: Probably explain here why the ordering of the passes matters, and why some
+passes like deadstore have multiple variants at different stages.
+-->
+
+See the `passes` list defined in [compile.go](compile.go) for more information.
+
+### Playing with SSA
+
+A good way to see and get used to the compiler's SSA in action is via
+`GOSSAFUNC`. For example, to see func `Foo`'s initial SSA form and final
+generated assembly, one can run:
+
+ GOSSAFUNC=Foo go build
+
+The generated `ssa.html` file will also contain the SSA func at each of the
+compile passes, making it easy to see what each pass does to a particular
+program. You can also click on values and blocks to highlight them, to help
+follow the control flow and values.
+
+<!---
+TODO: need more ideas for this section
+-->
+
+### Hacking on SSA
+
+While most compiler passes are implemented directly in Go code, some others are
+code generated. This is currently done via rewrite rules, which have their own
+syntax and are maintained in `gen/*.rules`. Simpler optimizations can be written
+easily and quickly this way, but rewrite rules are not suitable for more complex
+optimizations.
+
+To read more on rewrite rules, have a look at the top comments in
+[gen/generic.rules](gen/generic.rules) and [gen/rulegen.go](gen/rulegen.go).
+
+Similarly, the code to manage operators is also code generated from
+`gen/*Ops.go`, as it is easier to maintain a few tables than a lot of code.
+After changing the rules or operators, see [gen/README](gen/README) for
+instructions on how to generate the Go code again.
+
+<!---
+TODO: more tips and info could likely go here
+-->
diff --git a/src/cmd/compile/internal/ssa/TODO b/src/cmd/compile/internal/ssa/TODO
new file mode 100644
index 0000000..f4e4382
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/TODO
@@ -0,0 +1,24 @@
+This is a list of possible improvements to the SSA pass of the compiler.
+
+Optimizations (better compiled code)
+------------------------------------
+- Reduce register pressure in scheduler
+- Make dead store pass inter-block
+- If there are a lot of MOVQ $0, ..., then load
+ 0 into a register and use the register as the source instead.
+- Allow large structs to be SSAable (issue 24416)
+- Allow arrays of length >1 to be SSAable
+- If strings are being passed around without being interpreted (ptr
+ and len fields being accessed) pass them in xmm registers?
+ Same for interfaces?
+- any pointer generated by unsafe arithmetic must be non-nil?
+ (Of course that may not be true in general, but it is for all uses
+ in the runtime, and we can play games with unsafe.)
+
+Optimizations (better compiler)
+-------------------------------
+- Handle signed division overflow and sign extension earlier
+
+Regalloc
+--------
+- Make liveness analysis non-quadratic
diff --git a/src/cmd/compile/internal/ssa/addressingmodes.go b/src/cmd/compile/internal/ssa/addressingmodes.go
new file mode 100644
index 0000000..1baf143
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/addressingmodes.go
@@ -0,0 +1,460 @@
+// Copyright 2020 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
+
+// addressingModes combines address calculations into memory operations
+// that can perform complicated addressing modes.
+func addressingModes(f *Func) {
+ isInImmediateRange := is32Bit
+ switch f.Config.arch {
+ default:
+ // Most architectures can't do this.
+ return
+ case "amd64", "386":
+ case "s390x":
+ isInImmediateRange = is20Bit
+ }
+
+ var tmp []*Value
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if !combineFirst[v.Op] {
+ continue
+ }
+ // All matched operations have the pointer in arg[0].
+ // All results have the pointer in arg[0] and the index in arg[1].
+ // *Except* for operations which update a register,
+ // which are marked with resultInArg0. Those have
+ // the pointer in arg[1], and the corresponding result op
+ // has the pointer in arg[1] and the index in arg[2].
+ ptrIndex := 0
+ if opcodeTable[v.Op].resultInArg0 {
+ ptrIndex = 1
+ }
+ p := v.Args[ptrIndex]
+ c, ok := combine[[2]Op{v.Op, p.Op}]
+ if !ok {
+ continue
+ }
+ // See if we can combine the Aux/AuxInt values.
+ switch [2]auxType{opcodeTable[v.Op].auxType, opcodeTable[p.Op].auxType} {
+ case [2]auxType{auxSymOff, auxInt32}:
+ // TODO: introduce auxSymOff32
+ if !isInImmediateRange(v.AuxInt + p.AuxInt) {
+ continue
+ }
+ v.AuxInt += p.AuxInt
+ case [2]auxType{auxSymOff, auxSymOff}:
+ if v.Aux != nil && p.Aux != nil {
+ continue
+ }
+ if !isInImmediateRange(v.AuxInt + p.AuxInt) {
+ continue
+ }
+ if p.Aux != nil {
+ v.Aux = p.Aux
+ }
+ v.AuxInt += p.AuxInt
+ case [2]auxType{auxSymValAndOff, auxInt32}:
+ vo := ValAndOff(v.AuxInt)
+ if !vo.canAdd64(p.AuxInt) {
+ continue
+ }
+ v.AuxInt = int64(vo.addOffset64(p.AuxInt))
+ case [2]auxType{auxSymValAndOff, auxSymOff}:
+ vo := ValAndOff(v.AuxInt)
+ if v.Aux != nil && p.Aux != nil {
+ continue
+ }
+ if !vo.canAdd64(p.AuxInt) {
+ continue
+ }
+ if p.Aux != nil {
+ v.Aux = p.Aux
+ }
+ v.AuxInt = int64(vo.addOffset64(p.AuxInt))
+ case [2]auxType{auxSymOff, auxNone}:
+ // nothing to do
+ case [2]auxType{auxSymValAndOff, auxNone}:
+ // nothing to do
+ default:
+ f.Fatalf("unknown aux combining for %s and %s\n", v.Op, p.Op)
+ }
+ // Combine the operations.
+ tmp = append(tmp[:0], v.Args[:ptrIndex]...)
+ tmp = append(tmp, p.Args...)
+ tmp = append(tmp, v.Args[ptrIndex+1:]...)
+ v.resetArgs()
+ v.Op = c
+ v.AddArgs(tmp...)
+ if needSplit[c] {
+ // It turns out that some of the combined instructions have faster two-instruction equivalents,
+ // but not the two instructions that led to them being combined here. For example
+ // (CMPBconstload c (ADDQ x y)) -> (CMPBconstloadidx1 c x y) -> (CMPB c (MOVBloadidx1 x y))
+ // The final pair of instructions turns out to be notably faster, at least in some benchmarks.
+ f.Config.splitLoad(v)
+ }
+ }
+ }
+}
+
+// combineFirst contains ops which appear in combine as the
+// first part of the key.
+var combineFirst = map[Op]bool{}
+
+func init() {
+ for k := range combine {
+ combineFirst[k[0]] = true
+ }
+}
+
+// needSplit contains instructions that should be postprocessed by splitLoad
+// into a more-efficient two-instruction form.
+var needSplit = map[Op]bool{
+ OpAMD64CMPBloadidx1: true,
+ OpAMD64CMPWloadidx1: true,
+ OpAMD64CMPLloadidx1: true,
+ OpAMD64CMPQloadidx1: true,
+ OpAMD64CMPWloadidx2: true,
+ OpAMD64CMPLloadidx4: true,
+ OpAMD64CMPQloadidx8: true,
+
+ OpAMD64CMPBconstloadidx1: true,
+ OpAMD64CMPWconstloadidx1: true,
+ OpAMD64CMPLconstloadidx1: true,
+ OpAMD64CMPQconstloadidx1: true,
+ OpAMD64CMPWconstloadidx2: true,
+ OpAMD64CMPLconstloadidx4: true,
+ OpAMD64CMPQconstloadidx8: true,
+}
+
+// For each entry k, v in this map, if we have a value x with:
+// x.Op == k[0]
+// x.Args[0].Op == k[1]
+// then we can set x.Op to v and set x.Args like this:
+// x.Args[0].Args + x.Args[1:]
+// Additionally, the Aux/AuxInt from x.Args[0] is merged into x.
+var combine = map[[2]Op]Op{
+ // amd64
+ [2]Op{OpAMD64MOVBload, OpAMD64ADDQ}: OpAMD64MOVBloadidx1,
+ [2]Op{OpAMD64MOVWload, OpAMD64ADDQ}: OpAMD64MOVWloadidx1,
+ [2]Op{OpAMD64MOVLload, OpAMD64ADDQ}: OpAMD64MOVLloadidx1,
+ [2]Op{OpAMD64MOVQload, OpAMD64ADDQ}: OpAMD64MOVQloadidx1,
+ [2]Op{OpAMD64MOVSSload, OpAMD64ADDQ}: OpAMD64MOVSSloadidx1,
+ [2]Op{OpAMD64MOVSDload, OpAMD64ADDQ}: OpAMD64MOVSDloadidx1,
+
+ [2]Op{OpAMD64MOVBstore, OpAMD64ADDQ}: OpAMD64MOVBstoreidx1,
+ [2]Op{OpAMD64MOVWstore, OpAMD64ADDQ}: OpAMD64MOVWstoreidx1,
+ [2]Op{OpAMD64MOVLstore, OpAMD64ADDQ}: OpAMD64MOVLstoreidx1,
+ [2]Op{OpAMD64MOVQstore, OpAMD64ADDQ}: OpAMD64MOVQstoreidx1,
+ [2]Op{OpAMD64MOVSSstore, OpAMD64ADDQ}: OpAMD64MOVSSstoreidx1,
+ [2]Op{OpAMD64MOVSDstore, OpAMD64ADDQ}: OpAMD64MOVSDstoreidx1,
+
+ [2]Op{OpAMD64MOVBstoreconst, OpAMD64ADDQ}: OpAMD64MOVBstoreconstidx1,
+ [2]Op{OpAMD64MOVWstoreconst, OpAMD64ADDQ}: OpAMD64MOVWstoreconstidx1,
+ [2]Op{OpAMD64MOVLstoreconst, OpAMD64ADDQ}: OpAMD64MOVLstoreconstidx1,
+ [2]Op{OpAMD64MOVQstoreconst, OpAMD64ADDQ}: OpAMD64MOVQstoreconstidx1,
+
+ [2]Op{OpAMD64MOVBload, OpAMD64LEAQ1}: OpAMD64MOVBloadidx1,
+ [2]Op{OpAMD64MOVWload, OpAMD64LEAQ1}: OpAMD64MOVWloadidx1,
+ [2]Op{OpAMD64MOVWload, OpAMD64LEAQ2}: OpAMD64MOVWloadidx2,
+ [2]Op{OpAMD64MOVLload, OpAMD64LEAQ1}: OpAMD64MOVLloadidx1,
+ [2]Op{OpAMD64MOVLload, OpAMD64LEAQ4}: OpAMD64MOVLloadidx4,
+ [2]Op{OpAMD64MOVLload, OpAMD64LEAQ8}: OpAMD64MOVLloadidx8,
+ [2]Op{OpAMD64MOVQload, OpAMD64LEAQ1}: OpAMD64MOVQloadidx1,
+ [2]Op{OpAMD64MOVQload, OpAMD64LEAQ8}: OpAMD64MOVQloadidx8,
+ [2]Op{OpAMD64MOVSSload, OpAMD64LEAQ1}: OpAMD64MOVSSloadidx1,
+ [2]Op{OpAMD64MOVSSload, OpAMD64LEAQ4}: OpAMD64MOVSSloadidx4,
+ [2]Op{OpAMD64MOVSDload, OpAMD64LEAQ1}: OpAMD64MOVSDloadidx1,
+ [2]Op{OpAMD64MOVSDload, OpAMD64LEAQ8}: OpAMD64MOVSDloadidx8,
+
+ [2]Op{OpAMD64MOVBstore, OpAMD64LEAQ1}: OpAMD64MOVBstoreidx1,
+ [2]Op{OpAMD64MOVWstore, OpAMD64LEAQ1}: OpAMD64MOVWstoreidx1,
+ [2]Op{OpAMD64MOVWstore, OpAMD64LEAQ2}: OpAMD64MOVWstoreidx2,
+ [2]Op{OpAMD64MOVLstore, OpAMD64LEAQ1}: OpAMD64MOVLstoreidx1,
+ [2]Op{OpAMD64MOVLstore, OpAMD64LEAQ4}: OpAMD64MOVLstoreidx4,
+ [2]Op{OpAMD64MOVLstore, OpAMD64LEAQ8}: OpAMD64MOVLstoreidx8,
+ [2]Op{OpAMD64MOVQstore, OpAMD64LEAQ1}: OpAMD64MOVQstoreidx1,
+ [2]Op{OpAMD64MOVQstore, OpAMD64LEAQ8}: OpAMD64MOVQstoreidx8,
+ [2]Op{OpAMD64MOVSSstore, OpAMD64LEAQ1}: OpAMD64MOVSSstoreidx1,
+ [2]Op{OpAMD64MOVSSstore, OpAMD64LEAQ4}: OpAMD64MOVSSstoreidx4,
+ [2]Op{OpAMD64MOVSDstore, OpAMD64LEAQ1}: OpAMD64MOVSDstoreidx1,
+ [2]Op{OpAMD64MOVSDstore, OpAMD64LEAQ8}: OpAMD64MOVSDstoreidx8,
+
+ [2]Op{OpAMD64MOVBstoreconst, OpAMD64LEAQ1}: OpAMD64MOVBstoreconstidx1,
+ [2]Op{OpAMD64MOVWstoreconst, OpAMD64LEAQ1}: OpAMD64MOVWstoreconstidx1,
+ [2]Op{OpAMD64MOVWstoreconst, OpAMD64LEAQ2}: OpAMD64MOVWstoreconstidx2,
+ [2]Op{OpAMD64MOVLstoreconst, OpAMD64LEAQ1}: OpAMD64MOVLstoreconstidx1,
+ [2]Op{OpAMD64MOVLstoreconst, OpAMD64LEAQ4}: OpAMD64MOVLstoreconstidx4,
+ [2]Op{OpAMD64MOVQstoreconst, OpAMD64LEAQ1}: OpAMD64MOVQstoreconstidx1,
+ [2]Op{OpAMD64MOVQstoreconst, OpAMD64LEAQ8}: OpAMD64MOVQstoreconstidx8,
+
+ // These instructions are re-split differently for performance, see needSplit above.
+ // TODO if 386 versions are created, also update needSplit and gen/386splitload.rules
+ [2]Op{OpAMD64CMPBload, OpAMD64ADDQ}: OpAMD64CMPBloadidx1,
+ [2]Op{OpAMD64CMPWload, OpAMD64ADDQ}: OpAMD64CMPWloadidx1,
+ [2]Op{OpAMD64CMPLload, OpAMD64ADDQ}: OpAMD64CMPLloadidx1,
+ [2]Op{OpAMD64CMPQload, OpAMD64ADDQ}: OpAMD64CMPQloadidx1,
+
+ [2]Op{OpAMD64CMPBload, OpAMD64LEAQ1}: OpAMD64CMPBloadidx1,
+ [2]Op{OpAMD64CMPWload, OpAMD64LEAQ1}: OpAMD64CMPWloadidx1,
+ [2]Op{OpAMD64CMPWload, OpAMD64LEAQ2}: OpAMD64CMPWloadidx2,
+ [2]Op{OpAMD64CMPLload, OpAMD64LEAQ1}: OpAMD64CMPLloadidx1,
+ [2]Op{OpAMD64CMPLload, OpAMD64LEAQ4}: OpAMD64CMPLloadidx4,
+ [2]Op{OpAMD64CMPQload, OpAMD64LEAQ1}: OpAMD64CMPQloadidx1,
+ [2]Op{OpAMD64CMPQload, OpAMD64LEAQ8}: OpAMD64CMPQloadidx8,
+
+ [2]Op{OpAMD64CMPBconstload, OpAMD64ADDQ}: OpAMD64CMPBconstloadidx1,
+ [2]Op{OpAMD64CMPWconstload, OpAMD64ADDQ}: OpAMD64CMPWconstloadidx1,
+ [2]Op{OpAMD64CMPLconstload, OpAMD64ADDQ}: OpAMD64CMPLconstloadidx1,
+ [2]Op{OpAMD64CMPQconstload, OpAMD64ADDQ}: OpAMD64CMPQconstloadidx1,
+
+ [2]Op{OpAMD64CMPBconstload, OpAMD64LEAQ1}: OpAMD64CMPBconstloadidx1,
+ [2]Op{OpAMD64CMPWconstload, OpAMD64LEAQ1}: OpAMD64CMPWconstloadidx1,
+ [2]Op{OpAMD64CMPWconstload, OpAMD64LEAQ2}: OpAMD64CMPWconstloadidx2,
+ [2]Op{OpAMD64CMPLconstload, OpAMD64LEAQ1}: OpAMD64CMPLconstloadidx1,
+ [2]Op{OpAMD64CMPLconstload, OpAMD64LEAQ4}: OpAMD64CMPLconstloadidx4,
+ [2]Op{OpAMD64CMPQconstload, OpAMD64LEAQ1}: OpAMD64CMPQconstloadidx1,
+ [2]Op{OpAMD64CMPQconstload, OpAMD64LEAQ8}: OpAMD64CMPQconstloadidx8,
+
+ [2]Op{OpAMD64ADDLload, OpAMD64ADDQ}: OpAMD64ADDLloadidx1,
+ [2]Op{OpAMD64ADDQload, OpAMD64ADDQ}: OpAMD64ADDQloadidx1,
+ [2]Op{OpAMD64SUBLload, OpAMD64ADDQ}: OpAMD64SUBLloadidx1,
+ [2]Op{OpAMD64SUBQload, OpAMD64ADDQ}: OpAMD64SUBQloadidx1,
+ [2]Op{OpAMD64ANDLload, OpAMD64ADDQ}: OpAMD64ANDLloadidx1,
+ [2]Op{OpAMD64ANDQload, OpAMD64ADDQ}: OpAMD64ANDQloadidx1,
+ [2]Op{OpAMD64ORLload, OpAMD64ADDQ}: OpAMD64ORLloadidx1,
+ [2]Op{OpAMD64ORQload, OpAMD64ADDQ}: OpAMD64ORQloadidx1,
+ [2]Op{OpAMD64XORLload, OpAMD64ADDQ}: OpAMD64XORLloadidx1,
+ [2]Op{OpAMD64XORQload, OpAMD64ADDQ}: OpAMD64XORQloadidx1,
+
+ [2]Op{OpAMD64ADDLload, OpAMD64LEAQ1}: OpAMD64ADDLloadidx1,
+ [2]Op{OpAMD64ADDLload, OpAMD64LEAQ4}: OpAMD64ADDLloadidx4,
+ [2]Op{OpAMD64ADDLload, OpAMD64LEAQ8}: OpAMD64ADDLloadidx8,
+ [2]Op{OpAMD64ADDQload, OpAMD64LEAQ1}: OpAMD64ADDQloadidx1,
+ [2]Op{OpAMD64ADDQload, OpAMD64LEAQ8}: OpAMD64ADDQloadidx8,
+ [2]Op{OpAMD64SUBLload, OpAMD64LEAQ1}: OpAMD64SUBLloadidx1,
+ [2]Op{OpAMD64SUBLload, OpAMD64LEAQ4}: OpAMD64SUBLloadidx4,
+ [2]Op{OpAMD64SUBLload, OpAMD64LEAQ8}: OpAMD64SUBLloadidx8,
+ [2]Op{OpAMD64SUBQload, OpAMD64LEAQ1}: OpAMD64SUBQloadidx1,
+ [2]Op{OpAMD64SUBQload, OpAMD64LEAQ8}: OpAMD64SUBQloadidx8,
+ [2]Op{OpAMD64ANDLload, OpAMD64LEAQ1}: OpAMD64ANDLloadidx1,
+ [2]Op{OpAMD64ANDLload, OpAMD64LEAQ4}: OpAMD64ANDLloadidx4,
+ [2]Op{OpAMD64ANDLload, OpAMD64LEAQ8}: OpAMD64ANDLloadidx8,
+ [2]Op{OpAMD64ANDQload, OpAMD64LEAQ1}: OpAMD64ANDQloadidx1,
+ [2]Op{OpAMD64ANDQload, OpAMD64LEAQ8}: OpAMD64ANDQloadidx8,
+ [2]Op{OpAMD64ORLload, OpAMD64LEAQ1}: OpAMD64ORLloadidx1,
+ [2]Op{OpAMD64ORLload, OpAMD64LEAQ4}: OpAMD64ORLloadidx4,
+ [2]Op{OpAMD64ORLload, OpAMD64LEAQ8}: OpAMD64ORLloadidx8,
+ [2]Op{OpAMD64ORQload, OpAMD64LEAQ1}: OpAMD64ORQloadidx1,
+ [2]Op{OpAMD64ORQload, OpAMD64LEAQ8}: OpAMD64ORQloadidx8,
+ [2]Op{OpAMD64XORLload, OpAMD64LEAQ1}: OpAMD64XORLloadidx1,
+ [2]Op{OpAMD64XORLload, OpAMD64LEAQ4}: OpAMD64XORLloadidx4,
+ [2]Op{OpAMD64XORLload, OpAMD64LEAQ8}: OpAMD64XORLloadidx8,
+ [2]Op{OpAMD64XORQload, OpAMD64LEAQ1}: OpAMD64XORQloadidx1,
+ [2]Op{OpAMD64XORQload, OpAMD64LEAQ8}: OpAMD64XORQloadidx8,
+
+ [2]Op{OpAMD64ADDLmodify, OpAMD64ADDQ}: OpAMD64ADDLmodifyidx1,
+ [2]Op{OpAMD64ADDQmodify, OpAMD64ADDQ}: OpAMD64ADDQmodifyidx1,
+ [2]Op{OpAMD64SUBLmodify, OpAMD64ADDQ}: OpAMD64SUBLmodifyidx1,
+ [2]Op{OpAMD64SUBQmodify, OpAMD64ADDQ}: OpAMD64SUBQmodifyidx1,
+ [2]Op{OpAMD64ANDLmodify, OpAMD64ADDQ}: OpAMD64ANDLmodifyidx1,
+ [2]Op{OpAMD64ANDQmodify, OpAMD64ADDQ}: OpAMD64ANDQmodifyidx1,
+ [2]Op{OpAMD64ORLmodify, OpAMD64ADDQ}: OpAMD64ORLmodifyidx1,
+ [2]Op{OpAMD64ORQmodify, OpAMD64ADDQ}: OpAMD64ORQmodifyidx1,
+ [2]Op{OpAMD64XORLmodify, OpAMD64ADDQ}: OpAMD64XORLmodifyidx1,
+ [2]Op{OpAMD64XORQmodify, OpAMD64ADDQ}: OpAMD64XORQmodifyidx1,
+
+ [2]Op{OpAMD64ADDLmodify, OpAMD64LEAQ1}: OpAMD64ADDLmodifyidx1,
+ [2]Op{OpAMD64ADDLmodify, OpAMD64LEAQ4}: OpAMD64ADDLmodifyidx4,
+ [2]Op{OpAMD64ADDLmodify, OpAMD64LEAQ8}: OpAMD64ADDLmodifyidx8,
+ [2]Op{OpAMD64ADDQmodify, OpAMD64LEAQ1}: OpAMD64ADDQmodifyidx1,
+ [2]Op{OpAMD64ADDQmodify, OpAMD64LEAQ8}: OpAMD64ADDQmodifyidx8,
+ [2]Op{OpAMD64SUBLmodify, OpAMD64LEAQ1}: OpAMD64SUBLmodifyidx1,
+ [2]Op{OpAMD64SUBLmodify, OpAMD64LEAQ4}: OpAMD64SUBLmodifyidx4,
+ [2]Op{OpAMD64SUBLmodify, OpAMD64LEAQ8}: OpAMD64SUBLmodifyidx8,
+ [2]Op{OpAMD64SUBQmodify, OpAMD64LEAQ1}: OpAMD64SUBQmodifyidx1,
+ [2]Op{OpAMD64SUBQmodify, OpAMD64LEAQ8}: OpAMD64SUBQmodifyidx8,
+ [2]Op{OpAMD64ANDLmodify, OpAMD64LEAQ1}: OpAMD64ANDLmodifyidx1,
+ [2]Op{OpAMD64ANDLmodify, OpAMD64LEAQ4}: OpAMD64ANDLmodifyidx4,
+ [2]Op{OpAMD64ANDLmodify, OpAMD64LEAQ8}: OpAMD64ANDLmodifyidx8,
+ [2]Op{OpAMD64ANDQmodify, OpAMD64LEAQ1}: OpAMD64ANDQmodifyidx1,
+ [2]Op{OpAMD64ANDQmodify, OpAMD64LEAQ8}: OpAMD64ANDQmodifyidx8,
+ [2]Op{OpAMD64ORLmodify, OpAMD64LEAQ1}: OpAMD64ORLmodifyidx1,
+ [2]Op{OpAMD64ORLmodify, OpAMD64LEAQ4}: OpAMD64ORLmodifyidx4,
+ [2]Op{OpAMD64ORLmodify, OpAMD64LEAQ8}: OpAMD64ORLmodifyidx8,
+ [2]Op{OpAMD64ORQmodify, OpAMD64LEAQ1}: OpAMD64ORQmodifyidx1,
+ [2]Op{OpAMD64ORQmodify, OpAMD64LEAQ8}: OpAMD64ORQmodifyidx8,
+ [2]Op{OpAMD64XORLmodify, OpAMD64LEAQ1}: OpAMD64XORLmodifyidx1,
+ [2]Op{OpAMD64XORLmodify, OpAMD64LEAQ4}: OpAMD64XORLmodifyidx4,
+ [2]Op{OpAMD64XORLmodify, OpAMD64LEAQ8}: OpAMD64XORLmodifyidx8,
+ [2]Op{OpAMD64XORQmodify, OpAMD64LEAQ1}: OpAMD64XORQmodifyidx1,
+ [2]Op{OpAMD64XORQmodify, OpAMD64LEAQ8}: OpAMD64XORQmodifyidx8,
+
+ [2]Op{OpAMD64ADDLconstmodify, OpAMD64ADDQ}: OpAMD64ADDLconstmodifyidx1,
+ [2]Op{OpAMD64ADDQconstmodify, OpAMD64ADDQ}: OpAMD64ADDQconstmodifyidx1,
+ [2]Op{OpAMD64ANDLconstmodify, OpAMD64ADDQ}: OpAMD64ANDLconstmodifyidx1,
+ [2]Op{OpAMD64ANDQconstmodify, OpAMD64ADDQ}: OpAMD64ANDQconstmodifyidx1,
+ [2]Op{OpAMD64ORLconstmodify, OpAMD64ADDQ}: OpAMD64ORLconstmodifyidx1,
+ [2]Op{OpAMD64ORQconstmodify, OpAMD64ADDQ}: OpAMD64ORQconstmodifyidx1,
+ [2]Op{OpAMD64XORLconstmodify, OpAMD64ADDQ}: OpAMD64XORLconstmodifyidx1,
+ [2]Op{OpAMD64XORQconstmodify, OpAMD64ADDQ}: OpAMD64XORQconstmodifyidx1,
+
+ [2]Op{OpAMD64ADDLconstmodify, OpAMD64LEAQ1}: OpAMD64ADDLconstmodifyidx1,
+ [2]Op{OpAMD64ADDLconstmodify, OpAMD64LEAQ4}: OpAMD64ADDLconstmodifyidx4,
+ [2]Op{OpAMD64ADDLconstmodify, OpAMD64LEAQ8}: OpAMD64ADDLconstmodifyidx8,
+ [2]Op{OpAMD64ADDQconstmodify, OpAMD64LEAQ1}: OpAMD64ADDQconstmodifyidx1,
+ [2]Op{OpAMD64ADDQconstmodify, OpAMD64LEAQ8}: OpAMD64ADDQconstmodifyidx8,
+ [2]Op{OpAMD64ANDLconstmodify, OpAMD64LEAQ1}: OpAMD64ANDLconstmodifyidx1,
+ [2]Op{OpAMD64ANDLconstmodify, OpAMD64LEAQ4}: OpAMD64ANDLconstmodifyidx4,
+ [2]Op{OpAMD64ANDLconstmodify, OpAMD64LEAQ8}: OpAMD64ANDLconstmodifyidx8,
+ [2]Op{OpAMD64ANDQconstmodify, OpAMD64LEAQ1}: OpAMD64ANDQconstmodifyidx1,
+ [2]Op{OpAMD64ANDQconstmodify, OpAMD64LEAQ8}: OpAMD64ANDQconstmodifyidx8,
+ [2]Op{OpAMD64ORLconstmodify, OpAMD64LEAQ1}: OpAMD64ORLconstmodifyidx1,
+ [2]Op{OpAMD64ORLconstmodify, OpAMD64LEAQ4}: OpAMD64ORLconstmodifyidx4,
+ [2]Op{OpAMD64ORLconstmodify, OpAMD64LEAQ8}: OpAMD64ORLconstmodifyidx8,
+ [2]Op{OpAMD64ORQconstmodify, OpAMD64LEAQ1}: OpAMD64ORQconstmodifyidx1,
+ [2]Op{OpAMD64ORQconstmodify, OpAMD64LEAQ8}: OpAMD64ORQconstmodifyidx8,
+ [2]Op{OpAMD64XORLconstmodify, OpAMD64LEAQ1}: OpAMD64XORLconstmodifyidx1,
+ [2]Op{OpAMD64XORLconstmodify, OpAMD64LEAQ4}: OpAMD64XORLconstmodifyidx4,
+ [2]Op{OpAMD64XORLconstmodify, OpAMD64LEAQ8}: OpAMD64XORLconstmodifyidx8,
+ [2]Op{OpAMD64XORQconstmodify, OpAMD64LEAQ1}: OpAMD64XORQconstmodifyidx1,
+ [2]Op{OpAMD64XORQconstmodify, OpAMD64LEAQ8}: OpAMD64XORQconstmodifyidx8,
+
+ [2]Op{OpAMD64ADDSSload, OpAMD64LEAQ1}: OpAMD64ADDSSloadidx1,
+ [2]Op{OpAMD64ADDSSload, OpAMD64LEAQ4}: OpAMD64ADDSSloadidx4,
+ [2]Op{OpAMD64ADDSDload, OpAMD64LEAQ1}: OpAMD64ADDSDloadidx1,
+ [2]Op{OpAMD64ADDSDload, OpAMD64LEAQ8}: OpAMD64ADDSDloadidx8,
+ [2]Op{OpAMD64SUBSSload, OpAMD64LEAQ1}: OpAMD64SUBSSloadidx1,
+ [2]Op{OpAMD64SUBSSload, OpAMD64LEAQ4}: OpAMD64SUBSSloadidx4,
+ [2]Op{OpAMD64SUBSDload, OpAMD64LEAQ1}: OpAMD64SUBSDloadidx1,
+ [2]Op{OpAMD64SUBSDload, OpAMD64LEAQ8}: OpAMD64SUBSDloadidx8,
+ [2]Op{OpAMD64MULSSload, OpAMD64LEAQ1}: OpAMD64MULSSloadidx1,
+ [2]Op{OpAMD64MULSSload, OpAMD64LEAQ4}: OpAMD64MULSSloadidx4,
+ [2]Op{OpAMD64MULSDload, OpAMD64LEAQ1}: OpAMD64MULSDloadidx1,
+ [2]Op{OpAMD64MULSDload, OpAMD64LEAQ8}: OpAMD64MULSDloadidx8,
+ [2]Op{OpAMD64DIVSSload, OpAMD64LEAQ1}: OpAMD64DIVSSloadidx1,
+ [2]Op{OpAMD64DIVSSload, OpAMD64LEAQ4}: OpAMD64DIVSSloadidx4,
+ [2]Op{OpAMD64DIVSDload, OpAMD64LEAQ1}: OpAMD64DIVSDloadidx1,
+ [2]Op{OpAMD64DIVSDload, OpAMD64LEAQ8}: OpAMD64DIVSDloadidx8,
+
+ // 386
+ [2]Op{Op386MOVBload, Op386ADDL}: Op386MOVBloadidx1,
+ [2]Op{Op386MOVWload, Op386ADDL}: Op386MOVWloadidx1,
+ [2]Op{Op386MOVLload, Op386ADDL}: Op386MOVLloadidx1,
+ [2]Op{Op386MOVSSload, Op386ADDL}: Op386MOVSSloadidx1,
+ [2]Op{Op386MOVSDload, Op386ADDL}: Op386MOVSDloadidx1,
+
+ [2]Op{Op386MOVBstore, Op386ADDL}: Op386MOVBstoreidx1,
+ [2]Op{Op386MOVWstore, Op386ADDL}: Op386MOVWstoreidx1,
+ [2]Op{Op386MOVLstore, Op386ADDL}: Op386MOVLstoreidx1,
+ [2]Op{Op386MOVSSstore, Op386ADDL}: Op386MOVSSstoreidx1,
+ [2]Op{Op386MOVSDstore, Op386ADDL}: Op386MOVSDstoreidx1,
+
+ [2]Op{Op386MOVBstoreconst, Op386ADDL}: Op386MOVBstoreconstidx1,
+ [2]Op{Op386MOVWstoreconst, Op386ADDL}: Op386MOVWstoreconstidx1,
+ [2]Op{Op386MOVLstoreconst, Op386ADDL}: Op386MOVLstoreconstidx1,
+
+ [2]Op{Op386MOVBload, Op386LEAL1}: Op386MOVBloadidx1,
+ [2]Op{Op386MOVWload, Op386LEAL1}: Op386MOVWloadidx1,
+ [2]Op{Op386MOVWload, Op386LEAL2}: Op386MOVWloadidx2,
+ [2]Op{Op386MOVLload, Op386LEAL1}: Op386MOVLloadidx1,
+ [2]Op{Op386MOVLload, Op386LEAL4}: Op386MOVLloadidx4,
+ [2]Op{Op386MOVSSload, Op386LEAL1}: Op386MOVSSloadidx1,
+ [2]Op{Op386MOVSSload, Op386LEAL4}: Op386MOVSSloadidx4,
+ [2]Op{Op386MOVSDload, Op386LEAL1}: Op386MOVSDloadidx1,
+ [2]Op{Op386MOVSDload, Op386LEAL8}: Op386MOVSDloadidx8,
+
+ [2]Op{Op386MOVBstore, Op386LEAL1}: Op386MOVBstoreidx1,
+ [2]Op{Op386MOVWstore, Op386LEAL1}: Op386MOVWstoreidx1,
+ [2]Op{Op386MOVWstore, Op386LEAL2}: Op386MOVWstoreidx2,
+ [2]Op{Op386MOVLstore, Op386LEAL1}: Op386MOVLstoreidx1,
+ [2]Op{Op386MOVLstore, Op386LEAL4}: Op386MOVLstoreidx4,
+ [2]Op{Op386MOVSSstore, Op386LEAL1}: Op386MOVSSstoreidx1,
+ [2]Op{Op386MOVSSstore, Op386LEAL4}: Op386MOVSSstoreidx4,
+ [2]Op{Op386MOVSDstore, Op386LEAL1}: Op386MOVSDstoreidx1,
+ [2]Op{Op386MOVSDstore, Op386LEAL8}: Op386MOVSDstoreidx8,
+
+ [2]Op{Op386MOVBstoreconst, Op386LEAL1}: Op386MOVBstoreconstidx1,
+ [2]Op{Op386MOVWstoreconst, Op386LEAL1}: Op386MOVWstoreconstidx1,
+ [2]Op{Op386MOVWstoreconst, Op386LEAL2}: Op386MOVWstoreconstidx2,
+ [2]Op{Op386MOVLstoreconst, Op386LEAL1}: Op386MOVLstoreconstidx1,
+ [2]Op{Op386MOVLstoreconst, Op386LEAL4}: Op386MOVLstoreconstidx4,
+
+ [2]Op{Op386ADDLload, Op386LEAL4}: Op386ADDLloadidx4,
+ [2]Op{Op386SUBLload, Op386LEAL4}: Op386SUBLloadidx4,
+ [2]Op{Op386MULLload, Op386LEAL4}: Op386MULLloadidx4,
+ [2]Op{Op386ANDLload, Op386LEAL4}: Op386ANDLloadidx4,
+ [2]Op{Op386ORLload, Op386LEAL4}: Op386ORLloadidx4,
+ [2]Op{Op386XORLload, Op386LEAL4}: Op386XORLloadidx4,
+
+ [2]Op{Op386ADDLmodify, Op386LEAL4}: Op386ADDLmodifyidx4,
+ [2]Op{Op386SUBLmodify, Op386LEAL4}: Op386SUBLmodifyidx4,
+ [2]Op{Op386ANDLmodify, Op386LEAL4}: Op386ANDLmodifyidx4,
+ [2]Op{Op386ORLmodify, Op386LEAL4}: Op386ORLmodifyidx4,
+ [2]Op{Op386XORLmodify, Op386LEAL4}: Op386XORLmodifyidx4,
+
+ [2]Op{Op386ADDLconstmodify, Op386LEAL4}: Op386ADDLconstmodifyidx4,
+ [2]Op{Op386ANDLconstmodify, Op386LEAL4}: Op386ANDLconstmodifyidx4,
+ [2]Op{Op386ORLconstmodify, Op386LEAL4}: Op386ORLconstmodifyidx4,
+ [2]Op{Op386XORLconstmodify, Op386LEAL4}: Op386XORLconstmodifyidx4,
+
+ // s390x
+ [2]Op{OpS390XMOVDload, OpS390XADD}: OpS390XMOVDloadidx,
+ [2]Op{OpS390XMOVWload, OpS390XADD}: OpS390XMOVWloadidx,
+ [2]Op{OpS390XMOVHload, OpS390XADD}: OpS390XMOVHloadidx,
+ [2]Op{OpS390XMOVBload, OpS390XADD}: OpS390XMOVBloadidx,
+
+ [2]Op{OpS390XMOVWZload, OpS390XADD}: OpS390XMOVWZloadidx,
+ [2]Op{OpS390XMOVHZload, OpS390XADD}: OpS390XMOVHZloadidx,
+ [2]Op{OpS390XMOVBZload, OpS390XADD}: OpS390XMOVBZloadidx,
+
+ [2]Op{OpS390XMOVDBRload, OpS390XADD}: OpS390XMOVDBRloadidx,
+ [2]Op{OpS390XMOVWBRload, OpS390XADD}: OpS390XMOVWBRloadidx,
+ [2]Op{OpS390XMOVHBRload, OpS390XADD}: OpS390XMOVHBRloadidx,
+
+ [2]Op{OpS390XFMOVDload, OpS390XADD}: OpS390XFMOVDloadidx,
+ [2]Op{OpS390XFMOVSload, OpS390XADD}: OpS390XFMOVSloadidx,
+
+ [2]Op{OpS390XMOVDstore, OpS390XADD}: OpS390XMOVDstoreidx,
+ [2]Op{OpS390XMOVWstore, OpS390XADD}: OpS390XMOVWstoreidx,
+ [2]Op{OpS390XMOVHstore, OpS390XADD}: OpS390XMOVHstoreidx,
+ [2]Op{OpS390XMOVBstore, OpS390XADD}: OpS390XMOVBstoreidx,
+
+ [2]Op{OpS390XMOVDBRstore, OpS390XADD}: OpS390XMOVDBRstoreidx,
+ [2]Op{OpS390XMOVWBRstore, OpS390XADD}: OpS390XMOVWBRstoreidx,
+ [2]Op{OpS390XMOVHBRstore, OpS390XADD}: OpS390XMOVHBRstoreidx,
+
+ [2]Op{OpS390XFMOVDstore, OpS390XADD}: OpS390XFMOVDstoreidx,
+ [2]Op{OpS390XFMOVSstore, OpS390XADD}: OpS390XFMOVSstoreidx,
+
+ [2]Op{OpS390XMOVDload, OpS390XMOVDaddridx}: OpS390XMOVDloadidx,
+ [2]Op{OpS390XMOVWload, OpS390XMOVDaddridx}: OpS390XMOVWloadidx,
+ [2]Op{OpS390XMOVHload, OpS390XMOVDaddridx}: OpS390XMOVHloadidx,
+ [2]Op{OpS390XMOVBload, OpS390XMOVDaddridx}: OpS390XMOVBloadidx,
+
+ [2]Op{OpS390XMOVWZload, OpS390XMOVDaddridx}: OpS390XMOVWZloadidx,
+ [2]Op{OpS390XMOVHZload, OpS390XMOVDaddridx}: OpS390XMOVHZloadidx,
+ [2]Op{OpS390XMOVBZload, OpS390XMOVDaddridx}: OpS390XMOVBZloadidx,
+
+ [2]Op{OpS390XMOVDBRload, OpS390XMOVDaddridx}: OpS390XMOVDBRloadidx,
+ [2]Op{OpS390XMOVWBRload, OpS390XMOVDaddridx}: OpS390XMOVWBRloadidx,
+ [2]Op{OpS390XMOVHBRload, OpS390XMOVDaddridx}: OpS390XMOVHBRloadidx,
+
+ [2]Op{OpS390XFMOVDload, OpS390XMOVDaddridx}: OpS390XFMOVDloadidx,
+ [2]Op{OpS390XFMOVSload, OpS390XMOVDaddridx}: OpS390XFMOVSloadidx,
+
+ [2]Op{OpS390XMOVDstore, OpS390XMOVDaddridx}: OpS390XMOVDstoreidx,
+ [2]Op{OpS390XMOVWstore, OpS390XMOVDaddridx}: OpS390XMOVWstoreidx,
+ [2]Op{OpS390XMOVHstore, OpS390XMOVDaddridx}: OpS390XMOVHstoreidx,
+ [2]Op{OpS390XMOVBstore, OpS390XMOVDaddridx}: OpS390XMOVBstoreidx,
+
+ [2]Op{OpS390XMOVDBRstore, OpS390XMOVDaddridx}: OpS390XMOVDBRstoreidx,
+ [2]Op{OpS390XMOVWBRstore, OpS390XMOVDaddridx}: OpS390XMOVWBRstoreidx,
+ [2]Op{OpS390XMOVHBRstore, OpS390XMOVDaddridx}: OpS390XMOVHBRstoreidx,
+
+ [2]Op{OpS390XFMOVDstore, OpS390XMOVDaddridx}: OpS390XFMOVDstoreidx,
+ [2]Op{OpS390XFMOVSstore, OpS390XMOVDaddridx}: OpS390XFMOVSstoreidx,
+}
diff --git a/src/cmd/compile/internal/ssa/biasedsparsemap.go b/src/cmd/compile/internal/ssa/biasedsparsemap.go
new file mode 100644
index 0000000..0d35154
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/biasedsparsemap.go
@@ -0,0 +1,112 @@
+// Copyright 2018 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 (
+ "cmd/internal/src"
+ "math"
+)
+
+// A biasedSparseMap is a sparseMap for integers between J and K inclusive,
+// where J might be somewhat larger than zero (and K-J is probably much smaller than J).
+// (The motivating use case is the line numbers of statements for a single function.)
+// Not all features of a SparseMap are exported, and it is also easy to treat a
+// biasedSparseMap like a SparseSet.
+type biasedSparseMap struct {
+ s *sparseMap
+ first int
+}
+
+// newBiasedSparseMap returns a new biasedSparseMap for values between first and last, inclusive.
+func newBiasedSparseMap(first, last int) *biasedSparseMap {
+ if first > last {
+ return &biasedSparseMap{first: math.MaxInt32, s: nil}
+ }
+ return &biasedSparseMap{first: first, s: newSparseMap(1 + last - first)}
+}
+
+// cap returns one more than the largest key valid for s
+func (s *biasedSparseMap) cap() int {
+ if s == nil || s.s == nil {
+ return 0
+ }
+ return s.s.cap() + int(s.first)
+}
+
+// size returns the number of entries stored in s
+func (s *biasedSparseMap) size() int {
+ if s == nil || s.s == nil {
+ return 0
+ }
+ return s.s.size()
+}
+
+// contains reports whether x is a key in s
+func (s *biasedSparseMap) contains(x uint) bool {
+ if s == nil || s.s == nil {
+ return false
+ }
+ if int(x) < s.first {
+ return false
+ }
+ if int(x) >= s.cap() {
+ return false
+ }
+ return s.s.contains(ID(int(x) - s.first))
+}
+
+// get returns the value s maps for key x, or -1 if
+// x is not mapped or is out of range for s.
+func (s *biasedSparseMap) get(x uint) int32 {
+ if s == nil || s.s == nil {
+ return -1
+ }
+ if int(x) < s.first {
+ return -1
+ }
+ if int(x) >= s.cap() {
+ return -1
+ }
+ return s.s.get(ID(int(x) - s.first))
+}
+
+// getEntry returns the i'th key and value stored in s,
+// where 0 <= i < s.size()
+func (s *biasedSparseMap) getEntry(i int) (x uint, v int32) {
+ e := s.s.contents()[i]
+ x = uint(int(e.key) + s.first)
+ v = e.val
+ return
+}
+
+// add inserts x->0 into s, provided that x is in the range of keys stored in s.
+func (s *biasedSparseMap) add(x uint) {
+ if int(x) < s.first || int(x) >= s.cap() {
+ return
+ }
+ s.s.set(ID(int(x)-s.first), 0, src.NoXPos)
+}
+
+// add inserts x->v into s, provided that x is in the range of keys stored in s.
+func (s *biasedSparseMap) set(x uint, v int32) {
+ if int(x) < s.first || int(x) >= s.cap() {
+ return
+ }
+ s.s.set(ID(int(x)-s.first), v, src.NoXPos)
+}
+
+// remove removes key x from s.
+func (s *biasedSparseMap) remove(x uint) {
+ if int(x) < s.first || int(x) >= s.cap() {
+ return
+ }
+ s.s.remove(ID(int(x) - s.first))
+}
+
+func (s *biasedSparseMap) clear() {
+ if s.s != nil {
+ s.s.clear()
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/block.go b/src/cmd/compile/internal/ssa/block.go
new file mode 100644
index 0000000..519ac21
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/block.go
@@ -0,0 +1,371 @@
+// 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 (
+ "cmd/internal/src"
+ "fmt"
+)
+
+// Block represents a basic block in the control flow graph of a function.
+type Block struct {
+ // A unique identifier for the block. The system will attempt to allocate
+ // these IDs densely, but no guarantees.
+ ID ID
+
+ // Source position for block's control operation
+ Pos src.XPos
+
+ // The kind of block this is.
+ Kind BlockKind
+
+ // Likely direction for branches.
+ // If BranchLikely, Succs[0] is the most likely branch taken.
+ // If BranchUnlikely, Succs[1] is the most likely branch taken.
+ // Ignored if len(Succs) < 2.
+ // Fatal if not BranchUnknown and len(Succs) > 2.
+ Likely BranchPrediction
+
+ // After flagalloc, records whether flags are live at the end of the block.
+ FlagsLiveAtEnd bool
+
+ // Subsequent blocks, if any. The number and order depend on the block kind.
+ Succs []Edge
+
+ // Inverse of successors.
+ // The order is significant to Phi nodes in the block.
+ // TODO: predecessors is a pain to maintain. Can we somehow order phi
+ // arguments by block id and have this field computed explicitly when needed?
+ Preds []Edge
+
+ // A list of values that determine how the block is exited. The number
+ // and type of control values depends on the Kind of the block. For
+ // instance, a BlockIf has a single boolean control value and BlockExit
+ // has a single memory control value.
+ //
+ // The ControlValues() method may be used to get a slice with the non-nil
+ // control values that can be ranged over.
+ //
+ // Controls[1] must be nil if Controls[0] is nil.
+ Controls [2]*Value
+
+ // Auxiliary info for the block. Its value depends on the Kind.
+ Aux interface{}
+ AuxInt int64
+
+ // The unordered set of Values that define the operation of this block.
+ // After the scheduling pass, this list is ordered.
+ Values []*Value
+
+ // The containing function
+ Func *Func
+
+ // Storage for Succs, Preds and Values.
+ succstorage [2]Edge
+ predstorage [4]Edge
+ valstorage [9]*Value
+}
+
+// Edge represents a CFG edge.
+// Example edges for b branching to either c or d.
+// (c and d have other predecessors.)
+// b.Succs = [{c,3}, {d,1}]
+// c.Preds = [?, ?, ?, {b,0}]
+// d.Preds = [?, {b,1}, ?]
+// These indexes allow us to edit the CFG in constant time.
+// In addition, it informs phi ops in degenerate cases like:
+// b:
+// if k then c else c
+// c:
+// v = Phi(x, y)
+// Then the indexes tell you whether x is chosen from
+// the if or else branch from b.
+// b.Succs = [{c,0},{c,1}]
+// c.Preds = [{b,0},{b,1}]
+// means x is chosen if k is true.
+type Edge struct {
+ // block edge goes to (in a Succs list) or from (in a Preds list)
+ b *Block
+ // index of reverse edge. Invariant:
+ // e := x.Succs[idx]
+ // e.b.Preds[e.i] = Edge{x,idx}
+ // and similarly for predecessors.
+ i int
+}
+
+func (e Edge) Block() *Block {
+ return e.b
+}
+func (e Edge) Index() int {
+ return e.i
+}
+func (e Edge) String() string {
+ return fmt.Sprintf("{%v,%d}", e.b, e.i)
+}
+
+// kind controls successors
+// ------------------------------------------
+// Exit [return mem] []
+// Plain [] [next]
+// If [boolean Value] [then, else]
+// Defer [mem] [nopanic, panic] (control opcode should be OpStaticCall to runtime.deferproc)
+type BlockKind int8
+
+// short form print
+func (b *Block) String() string {
+ return fmt.Sprintf("b%d", b.ID)
+}
+
+// long form print
+func (b *Block) LongString() string {
+ s := b.Kind.String()
+ if b.Aux != nil {
+ s += fmt.Sprintf(" {%s}", b.Aux)
+ }
+ if t := b.AuxIntString(); t != "" {
+ s += fmt.Sprintf(" [%s]", t)
+ }
+ for _, c := range b.ControlValues() {
+ s += fmt.Sprintf(" %s", c)
+ }
+ if len(b.Succs) > 0 {
+ s += " ->"
+ for _, c := range b.Succs {
+ s += " " + c.b.String()
+ }
+ }
+ switch b.Likely {
+ case BranchUnlikely:
+ s += " (unlikely)"
+ case BranchLikely:
+ s += " (likely)"
+ }
+ return s
+}
+
+// NumControls returns the number of non-nil control values the
+// block has.
+func (b *Block) NumControls() int {
+ if b.Controls[0] == nil {
+ return 0
+ }
+ if b.Controls[1] == nil {
+ return 1
+ }
+ return 2
+}
+
+// ControlValues returns a slice containing the non-nil control
+// values of the block. The index of each control value will be
+// the same as it is in the Controls property and can be used
+// in ReplaceControl calls.
+func (b *Block) ControlValues() []*Value {
+ if b.Controls[0] == nil {
+ return b.Controls[:0]
+ }
+ if b.Controls[1] == nil {
+ return b.Controls[:1]
+ }
+ return b.Controls[:2]
+}
+
+// SetControl removes all existing control values and then adds
+// the control value provided. The number of control values after
+// a call to SetControl will always be 1.
+func (b *Block) SetControl(v *Value) {
+ b.ResetControls()
+ b.Controls[0] = v
+ v.Uses++
+}
+
+// ResetControls sets the number of controls for the block to 0.
+func (b *Block) ResetControls() {
+ if b.Controls[0] != nil {
+ b.Controls[0].Uses--
+ }
+ if b.Controls[1] != nil {
+ b.Controls[1].Uses--
+ }
+ b.Controls = [2]*Value{} // reset both controls to nil
+}
+
+// AddControl appends a control value to the existing list of control values.
+func (b *Block) AddControl(v *Value) {
+ i := b.NumControls()
+ b.Controls[i] = v // panics if array is full
+ v.Uses++
+}
+
+// ReplaceControl exchanges the existing control value at the index provided
+// for the new value. The index must refer to a valid control value.
+func (b *Block) ReplaceControl(i int, v *Value) {
+ b.Controls[i].Uses--
+ b.Controls[i] = v
+ v.Uses++
+}
+
+// CopyControls replaces the controls for this block with those from the
+// provided block. The provided block is not modified.
+func (b *Block) CopyControls(from *Block) {
+ if b == from {
+ return
+ }
+ b.ResetControls()
+ for _, c := range from.ControlValues() {
+ b.AddControl(c)
+ }
+}
+
+// Reset sets the block to the provided kind and clears all the blocks control
+// and auxiliary values. Other properties of the block, such as its successors,
+// predecessors and values are left unmodified.
+func (b *Block) Reset(kind BlockKind) {
+ b.Kind = kind
+ b.ResetControls()
+ b.Aux = nil
+ b.AuxInt = 0
+}
+
+// resetWithControl resets b and adds control v.
+// It is equivalent to b.Reset(kind); b.AddControl(v),
+// except that it is one call instead of two and avoids a bounds check.
+// It is intended for use by rewrite rules, where this matters.
+func (b *Block) resetWithControl(kind BlockKind, v *Value) {
+ b.Kind = kind
+ b.ResetControls()
+ b.Aux = nil
+ b.AuxInt = 0
+ b.Controls[0] = v
+ v.Uses++
+}
+
+// resetWithControl2 resets b and adds controls v and w.
+// It is equivalent to b.Reset(kind); b.AddControl(v); b.AddControl(w),
+// except that it is one call instead of three and avoids two bounds checks.
+// It is intended for use by rewrite rules, where this matters.
+func (b *Block) resetWithControl2(kind BlockKind, v, w *Value) {
+ b.Kind = kind
+ b.ResetControls()
+ b.Aux = nil
+ b.AuxInt = 0
+ b.Controls[0] = v
+ b.Controls[1] = w
+ v.Uses++
+ w.Uses++
+}
+
+// truncateValues truncates b.Values at the ith element, zeroing subsequent elements.
+// The values in b.Values after i must already have had their args reset,
+// to maintain correct value uses counts.
+func (b *Block) truncateValues(i int) {
+ tail := b.Values[i:]
+ for j := range tail {
+ tail[j] = nil
+ }
+ b.Values = b.Values[:i]
+}
+
+// AddEdgeTo adds an edge from block b to block c. Used during building of the
+// SSA graph; do not use on an already-completed SSA graph.
+func (b *Block) AddEdgeTo(c *Block) {
+ i := len(b.Succs)
+ j := len(c.Preds)
+ b.Succs = append(b.Succs, Edge{c, j})
+ c.Preds = append(c.Preds, Edge{b, i})
+ b.Func.invalidateCFG()
+}
+
+// removePred removes the ith input edge from b.
+// It is the responsibility of the caller to remove
+// the corresponding successor edge.
+func (b *Block) removePred(i int) {
+ n := len(b.Preds) - 1
+ if i != n {
+ e := b.Preds[n]
+ b.Preds[i] = e
+ // Update the other end of the edge we moved.
+ e.b.Succs[e.i].i = i
+ }
+ b.Preds[n] = Edge{}
+ b.Preds = b.Preds[:n]
+ b.Func.invalidateCFG()
+}
+
+// removeSucc removes the ith output edge from b.
+// It is the responsibility of the caller to remove
+// the corresponding predecessor edge.
+func (b *Block) removeSucc(i int) {
+ n := len(b.Succs) - 1
+ if i != n {
+ e := b.Succs[n]
+ b.Succs[i] = e
+ // Update the other end of the edge we moved.
+ e.b.Preds[e.i].i = i
+ }
+ b.Succs[n] = Edge{}
+ b.Succs = b.Succs[:n]
+ b.Func.invalidateCFG()
+}
+
+func (b *Block) swapSuccessors() {
+ if len(b.Succs) != 2 {
+ b.Fatalf("swapSuccessors with len(Succs)=%d", len(b.Succs))
+ }
+ e0 := b.Succs[0]
+ e1 := b.Succs[1]
+ b.Succs[0] = e1
+ b.Succs[1] = e0
+ e0.b.Preds[e0.i].i = 1
+ e1.b.Preds[e1.i].i = 0
+ b.Likely *= -1
+}
+
+// LackingPos indicates whether b is a block whose position should be inherited
+// from its successors. This is true if all the values within it have unreliable positions
+// and if it is "plain", meaning that there is no control flow that is also very likely
+// to correspond to a well-understood source position.
+func (b *Block) LackingPos() bool {
+ // Non-plain predecessors are If or Defer, which both (1) have two successors,
+ // which might have different line numbers and (2) correspond to statements
+ // in the source code that have positions, so this case ought not occur anyway.
+ if b.Kind != BlockPlain {
+ return false
+ }
+ if b.Pos != src.NoXPos {
+ return false
+ }
+ for _, v := range b.Values {
+ if v.LackingPos() {
+ continue
+ }
+ return false
+ }
+ return true
+}
+
+func (b *Block) AuxIntString() string {
+ switch b.Kind.AuxIntType() {
+ case "int8":
+ return fmt.Sprintf("%v", int8(b.AuxInt))
+ case "uint8":
+ return fmt.Sprintf("%v", uint8(b.AuxInt))
+ default: // type specified but not implemented - print as int64
+ return fmt.Sprintf("%v", b.AuxInt)
+ case "": // no aux int type
+ return ""
+ }
+}
+
+func (b *Block) Logf(msg string, args ...interface{}) { b.Func.Logf(msg, args...) }
+func (b *Block) Log() bool { return b.Func.Log() }
+func (b *Block) Fatalf(msg string, args ...interface{}) { b.Func.Fatalf(msg, args...) }
+
+type BranchPrediction int8
+
+const (
+ BranchUnlikely = BranchPrediction(-1)
+ BranchUnknown = BranchPrediction(0)
+ BranchLikely = BranchPrediction(+1)
+)
diff --git a/src/cmd/compile/internal/ssa/branchelim.go b/src/cmd/compile/internal/ssa/branchelim.go
new file mode 100644
index 0000000..1d34f81
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/branchelim.go
@@ -0,0 +1,449 @@
+// Copyright 2017 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 "cmd/internal/src"
+
+// branchelim tries to eliminate branches by
+// generating CondSelect instructions.
+//
+// Search for basic blocks that look like
+//
+// bb0 bb0
+// | \ / \
+// | bb1 or bb1 bb2 <- trivial if/else blocks
+// | / \ /
+// bb2 bb3
+//
+// where the intermediate blocks are mostly empty (with no side-effects);
+// rewrite Phis in the postdominator as CondSelects.
+func branchelim(f *Func) {
+ // FIXME: add support for lowering CondSelects on more architectures
+ switch f.Config.arch {
+ case "arm64", "amd64", "wasm":
+ // implemented
+ default:
+ return
+ }
+
+ // Find all the values used in computing the address of any load.
+ // Typically these values have operations like AddPtr, Lsh64x64, etc.
+ loadAddr := f.newSparseSet(f.NumValues())
+ defer f.retSparseSet(loadAddr)
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ switch v.Op {
+ case OpLoad, OpAtomicLoad8, OpAtomicLoad32, OpAtomicLoad64, OpAtomicLoadPtr, OpAtomicLoadAcq32, OpAtomicLoadAcq64:
+ loadAddr.add(v.Args[0].ID)
+ case OpMove:
+ loadAddr.add(v.Args[1].ID)
+ }
+ }
+ }
+ po := f.postorder()
+ for {
+ n := loadAddr.size()
+ for _, b := range po {
+ for i := len(b.Values) - 1; i >= 0; i-- {
+ v := b.Values[i]
+ if !loadAddr.contains(v.ID) {
+ continue
+ }
+ for _, a := range v.Args {
+ if a.Type.IsInteger() || a.Type.IsPtr() || a.Type.IsUnsafePtr() {
+ loadAddr.add(a.ID)
+ }
+ }
+ }
+ }
+ if loadAddr.size() == n {
+ break
+ }
+ }
+
+ change := true
+ for change {
+ change = false
+ for _, b := range f.Blocks {
+ change = elimIf(f, loadAddr, b) || elimIfElse(f, loadAddr, b) || change
+ }
+ }
+}
+
+func canCondSelect(v *Value, arch string, loadAddr *sparseSet) bool {
+ if loadAddr.contains(v.ID) {
+ // The result of the soon-to-be conditional move is used to compute a load address.
+ // We want to avoid generating a conditional move in this case
+ // because the load address would now be data-dependent on the condition.
+ // Previously it would only be control-dependent on the condition, which is faster
+ // if the branch predicts well (or possibly even if it doesn't, if the load will
+ // be an expensive cache miss).
+ // See issue #26306.
+ return false
+ }
+ // For now, stick to simple scalars that fit in registers
+ switch {
+ case v.Type.Size() > v.Block.Func.Config.RegSize:
+ return false
+ case v.Type.IsPtrShaped():
+ return true
+ case v.Type.IsInteger():
+ if arch == "amd64" && v.Type.Size() < 2 {
+ // amd64 doesn't support CMOV with byte registers
+ return false
+ }
+ return true
+ default:
+ return false
+ }
+}
+
+// elimIf converts the one-way branch starting at dom in f to a conditional move if possible.
+// loadAddr is a set of values which are used to compute the address of a load.
+// Those values are exempt from CMOV generation.
+func elimIf(f *Func, loadAddr *sparseSet, dom *Block) bool {
+ // See if dom is an If with one arm that
+ // is trivial and succeeded by the other
+ // successor of dom.
+ if dom.Kind != BlockIf || dom.Likely != BranchUnknown {
+ return false
+ }
+ var simple, post *Block
+ for i := range dom.Succs {
+ bb, other := dom.Succs[i].Block(), dom.Succs[i^1].Block()
+ if isLeafPlain(bb) && bb.Succs[0].Block() == other {
+ simple = bb
+ post = other
+ break
+ }
+ }
+ if simple == nil || len(post.Preds) != 2 || post == dom {
+ return false
+ }
+
+ // We've found our diamond CFG of blocks.
+ // Now decide if fusing 'simple' into dom+post
+ // looks profitable.
+
+ // Check that there are Phis, and that all of them
+ // can be safely rewritten to CondSelect.
+ hasphis := false
+ for _, v := range post.Values {
+ if v.Op == OpPhi {
+ hasphis = true
+ if !canCondSelect(v, f.Config.arch, loadAddr) {
+ return false
+ }
+ }
+ }
+ if !hasphis {
+ return false
+ }
+
+ // Pick some upper bound for the number of instructions
+ // we'd be willing to execute just to generate a dead
+ // argument to CondSelect. In the worst case, this is
+ // the number of useless instructions executed.
+ const maxfuseinsts = 2
+
+ if len(simple.Values) > maxfuseinsts || !canSpeculativelyExecute(simple) {
+ return false
+ }
+
+ // Replace Phi instructions in b with CondSelect instructions
+ swap := (post.Preds[0].Block() == dom) != (dom.Succs[0].Block() == post)
+ for _, v := range post.Values {
+ if v.Op != OpPhi {
+ continue
+ }
+ v.Op = OpCondSelect
+ if swap {
+ v.Args[0], v.Args[1] = v.Args[1], v.Args[0]
+ }
+ v.AddArg(dom.Controls[0])
+ }
+
+ // Put all of the instructions into 'dom'
+ // and update the CFG appropriately.
+ dom.Kind = post.Kind
+ dom.CopyControls(post)
+ dom.Aux = post.Aux
+ dom.Succs = append(dom.Succs[:0], post.Succs...)
+ for i := range dom.Succs {
+ e := dom.Succs[i]
+ e.b.Preds[e.i].b = dom
+ }
+
+ // Try really hard to preserve statement marks attached to blocks.
+ simplePos := simple.Pos
+ postPos := post.Pos
+ simpleStmt := simplePos.IsStmt() == src.PosIsStmt
+ postStmt := postPos.IsStmt() == src.PosIsStmt
+
+ for _, v := range simple.Values {
+ v.Block = dom
+ }
+ for _, v := range post.Values {
+ v.Block = dom
+ }
+
+ // findBlockPos determines if b contains a stmt-marked value
+ // that has the same line number as the Pos for b itself.
+ // (i.e. is the position on b actually redundant?)
+ findBlockPos := func(b *Block) bool {
+ pos := b.Pos
+ for _, v := range b.Values {
+ // See if there is a stmt-marked value already that matches simple.Pos (and perhaps post.Pos)
+ if pos.SameFileAndLine(v.Pos) && v.Pos.IsStmt() == src.PosIsStmt {
+ return true
+ }
+ }
+ return false
+ }
+ if simpleStmt {
+ simpleStmt = !findBlockPos(simple)
+ if !simpleStmt && simplePos.SameFileAndLine(postPos) {
+ postStmt = false
+ }
+
+ }
+ if postStmt {
+ postStmt = !findBlockPos(post)
+ }
+
+ // If simpleStmt and/or postStmt are still true, then try harder
+ // to find the corresponding statement marks new homes.
+
+ // setBlockPos determines if b contains a can-be-statement value
+ // that has the same line number as the Pos for b itself, and
+ // puts a statement mark on it, and returns whether it succeeded
+ // in this operation.
+ setBlockPos := func(b *Block) bool {
+ pos := b.Pos
+ for _, v := range b.Values {
+ if pos.SameFileAndLine(v.Pos) && !isPoorStatementOp(v.Op) {
+ v.Pos = v.Pos.WithIsStmt()
+ return true
+ }
+ }
+ return false
+ }
+ // If necessary and possible, add a mark to a value in simple
+ if simpleStmt {
+ if setBlockPos(simple) && simplePos.SameFileAndLine(postPos) {
+ postStmt = false
+ }
+ }
+ // If necessary and possible, add a mark to a value in post
+ if postStmt {
+ postStmt = !setBlockPos(post)
+ }
+
+ // Before giving up (this was added because it helps), try the end of "dom", and if that is not available,
+ // try the values in the successor block if it is uncomplicated.
+ if postStmt {
+ if dom.Pos.IsStmt() != src.PosIsStmt {
+ dom.Pos = postPos
+ } else {
+ // Try the successor block
+ if len(dom.Succs) == 1 && len(dom.Succs[0].Block().Preds) == 1 {
+ succ := dom.Succs[0].Block()
+ for _, v := range succ.Values {
+ if isPoorStatementOp(v.Op) {
+ continue
+ }
+ if postPos.SameFileAndLine(v.Pos) {
+ v.Pos = v.Pos.WithIsStmt()
+ }
+ postStmt = false
+ break
+ }
+ // If postStmt still true, tag the block itself if possible
+ if postStmt && succ.Pos.IsStmt() != src.PosIsStmt {
+ succ.Pos = postPos
+ }
+ }
+ }
+ }
+
+ dom.Values = append(dom.Values, simple.Values...)
+ dom.Values = append(dom.Values, post.Values...)
+
+ // Trash 'post' and 'simple'
+ clobberBlock(post)
+ clobberBlock(simple)
+
+ f.invalidateCFG()
+ return true
+}
+
+// is this a BlockPlain with one predecessor?
+func isLeafPlain(b *Block) bool {
+ return b.Kind == BlockPlain && len(b.Preds) == 1
+}
+
+func clobberBlock(b *Block) {
+ b.Values = nil
+ b.Preds = nil
+ b.Succs = nil
+ b.Aux = nil
+ b.ResetControls()
+ b.Likely = BranchUnknown
+ b.Kind = BlockInvalid
+}
+
+// elimIfElse converts the two-way branch starting at dom in f to a conditional move if possible.
+// loadAddr is a set of values which are used to compute the address of a load.
+// Those values are exempt from CMOV generation.
+func elimIfElse(f *Func, loadAddr *sparseSet, b *Block) bool {
+ // See if 'b' ends in an if/else: it should
+ // have two successors, both of which are BlockPlain
+ // and succeeded by the same block.
+ if b.Kind != BlockIf || b.Likely != BranchUnknown {
+ return false
+ }
+ yes, no := b.Succs[0].Block(), b.Succs[1].Block()
+ if !isLeafPlain(yes) || len(yes.Values) > 1 || !canSpeculativelyExecute(yes) {
+ return false
+ }
+ if !isLeafPlain(no) || len(no.Values) > 1 || !canSpeculativelyExecute(no) {
+ return false
+ }
+ if b.Succs[0].Block().Succs[0].Block() != b.Succs[1].Block().Succs[0].Block() {
+ return false
+ }
+ // block that postdominates the if/else
+ post := b.Succs[0].Block().Succs[0].Block()
+ if len(post.Preds) != 2 || post == b {
+ return false
+ }
+ hasphis := false
+ for _, v := range post.Values {
+ if v.Op == OpPhi {
+ hasphis = true
+ if !canCondSelect(v, f.Config.arch, loadAddr) {
+ return false
+ }
+ }
+ }
+ if !hasphis {
+ return false
+ }
+
+ // Don't generate CondSelects if branch is cheaper.
+ if !shouldElimIfElse(no, yes, post, f.Config.arch) {
+ return false
+ }
+
+ // now we're committed: rewrite each Phi as a CondSelect
+ swap := post.Preds[0].Block() != b.Succs[0].Block()
+ for _, v := range post.Values {
+ if v.Op != OpPhi {
+ continue
+ }
+ v.Op = OpCondSelect
+ if swap {
+ v.Args[0], v.Args[1] = v.Args[1], v.Args[0]
+ }
+ v.AddArg(b.Controls[0])
+ }
+
+ // Move the contents of all of these
+ // blocks into 'b' and update CFG edges accordingly
+ b.Kind = post.Kind
+ b.CopyControls(post)
+ b.Aux = post.Aux
+ b.Succs = append(b.Succs[:0], post.Succs...)
+ for i := range b.Succs {
+ e := b.Succs[i]
+ e.b.Preds[e.i].b = b
+ }
+ for i := range post.Values {
+ post.Values[i].Block = b
+ }
+ for i := range yes.Values {
+ yes.Values[i].Block = b
+ }
+ for i := range no.Values {
+ no.Values[i].Block = b
+ }
+ b.Values = append(b.Values, yes.Values...)
+ b.Values = append(b.Values, no.Values...)
+ b.Values = append(b.Values, post.Values...)
+
+ // trash post, yes, and no
+ clobberBlock(yes)
+ clobberBlock(no)
+ clobberBlock(post)
+
+ f.invalidateCFG()
+ return true
+}
+
+// shouldElimIfElse reports whether estimated cost of eliminating branch
+// is lower than threshold.
+func shouldElimIfElse(no, yes, post *Block, arch string) bool {
+ switch arch {
+ default:
+ return true
+ case "amd64":
+ const maxcost = 2
+ phi := 0
+ other := 0
+ for _, v := range post.Values {
+ if v.Op == OpPhi {
+ // Each phi results in CondSelect, which lowers into CMOV,
+ // CMOV has latency >1 on most CPUs.
+ phi++
+ }
+ for _, x := range v.Args {
+ if x.Block == no || x.Block == yes {
+ other++
+ }
+ }
+ }
+ cost := phi * 1
+ if phi > 1 {
+ // If we have more than 1 phi and some values in post have args
+ // in yes or no blocks, we may have to recalculate condition, because
+ // those args may clobber flags. For now assume that all operations clobber flags.
+ cost += other * 1
+ }
+ return cost < maxcost
+ }
+}
+
+// canSpeculativelyExecute reports whether every value in the block can
+// be evaluated without causing any observable side effects (memory
+// accesses, panics and so on) except for execution time changes. It
+// also ensures that the block does not contain any phis which we can't
+// speculatively execute.
+// Warning: this function cannot currently detect values that represent
+// instructions the execution of which need to be guarded with CPU
+// hardware feature checks. See issue #34950.
+func canSpeculativelyExecute(b *Block) bool {
+ // don't fuse memory ops, Phi ops, divides (can panic),
+ // or anything else with side-effects
+ for _, v := range b.Values {
+ if v.Op == OpPhi || isDivMod(v.Op) || v.Type.IsMemory() ||
+ v.MemoryArg() != nil || opcodeTable[v.Op].hasSideEffects {
+ return false
+ }
+ }
+ return true
+}
+
+func isDivMod(op Op) bool {
+ switch op {
+ case OpDiv8, OpDiv8u, OpDiv16, OpDiv16u,
+ OpDiv32, OpDiv32u, OpDiv64, OpDiv64u, OpDiv128u,
+ OpDiv32F, OpDiv64F,
+ OpMod8, OpMod8u, OpMod16, OpMod16u,
+ OpMod32, OpMod32u, OpMod64, OpMod64u:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/branchelim_test.go b/src/cmd/compile/internal/ssa/branchelim_test.go
new file mode 100644
index 0000000..20fa84d
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/branchelim_test.go
@@ -0,0 +1,172 @@
+// Copyright 2017 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 (
+ "cmd/compile/internal/types"
+ "testing"
+)
+
+// Test that a trivial 'if' is eliminated
+func TestBranchElimIf(t *testing.T) {
+ var testData = []struct {
+ arch string
+ intType string
+ ok bool
+ }{
+ {"arm64", "int32", true},
+ {"amd64", "int32", true},
+ {"amd64", "int8", false},
+ }
+
+ for _, data := range testData {
+ t.Run(data.arch+"/"+data.intType, func(t *testing.T) {
+ c := testConfigArch(t, data.arch)
+ boolType := c.config.Types.Bool
+ var intType *types.Type
+ switch data.intType {
+ case "int32":
+ intType = c.config.Types.Int32
+ case "int8":
+ intType = c.config.Types.Int8
+ default:
+ t.Fatal("invalid integer type:", data.intType)
+ }
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("const1", OpConst32, intType, 1, nil),
+ Valu("const2", OpConst32, intType, 2, nil),
+ Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
+ Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
+ If("cond", "b2", "b3")),
+ Bloc("b2",
+ Goto("b3")),
+ Bloc("b3",
+ Valu("phi", OpPhi, intType, 0, nil, "const1", "const2"),
+ Valu("retstore", OpStore, types.TypeMem, 0, nil, "phi", "sb", "start"),
+ Exit("retstore")))
+
+ CheckFunc(fun.f)
+ branchelim(fun.f)
+ CheckFunc(fun.f)
+ Deadcode(fun.f)
+ CheckFunc(fun.f)
+
+ if data.ok {
+
+ if len(fun.f.Blocks) != 1 {
+ t.Fatalf("expected 1 block after branchelim and deadcode; found %d", len(fun.f.Blocks))
+ }
+ if fun.values["phi"].Op != OpCondSelect {
+ t.Fatalf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
+ }
+ if fun.values["phi"].Args[2] != fun.values["cond"] {
+ t.Errorf("expected CondSelect condition to be %s; found %s", fun.values["cond"], fun.values["phi"].Args[2])
+ }
+ if fun.blocks["entry"].Kind != BlockExit {
+ t.Errorf("expected entry to be BlockExit; found kind %s", fun.blocks["entry"].Kind.String())
+ }
+ } else {
+ if len(fun.f.Blocks) != 3 {
+ t.Fatalf("expected 3 block after branchelim and deadcode; found %d", len(fun.f.Blocks))
+ }
+ }
+ })
+ }
+}
+
+// Test that a trivial if/else is eliminated
+func TestBranchElimIfElse(t *testing.T) {
+ for _, arch := range []string{"arm64", "amd64"} {
+ t.Run(arch, func(t *testing.T) {
+ c := testConfigArch(t, arch)
+ boolType := c.config.Types.Bool
+ intType := c.config.Types.Int32
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("const1", OpConst32, intType, 1, nil),
+ Valu("const2", OpConst32, intType, 2, nil),
+ Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
+ Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
+ If("cond", "b2", "b3")),
+ Bloc("b2",
+ Goto("b4")),
+ Bloc("b3",
+ Goto("b4")),
+ Bloc("b4",
+ Valu("phi", OpPhi, intType, 0, nil, "const1", "const2"),
+ Valu("retstore", OpStore, types.TypeMem, 0, nil, "phi", "sb", "start"),
+ Exit("retstore")))
+
+ CheckFunc(fun.f)
+ branchelim(fun.f)
+ CheckFunc(fun.f)
+ Deadcode(fun.f)
+ CheckFunc(fun.f)
+
+ if len(fun.f.Blocks) != 1 {
+ t.Fatalf("expected 1 block after branchelim; found %d", len(fun.f.Blocks))
+ }
+ if fun.values["phi"].Op != OpCondSelect {
+ t.Fatalf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
+ }
+ if fun.values["phi"].Args[2] != fun.values["cond"] {
+ t.Errorf("expected CondSelect condition to be %s; found %s", fun.values["cond"], fun.values["phi"].Args[2])
+ }
+ if fun.blocks["entry"].Kind != BlockExit {
+ t.Errorf("expected entry to be BlockExit; found kind %s", fun.blocks["entry"].Kind.String())
+ }
+ })
+ }
+}
+
+// Test that an if/else CFG that loops back
+// into itself does *not* get eliminated.
+func TestNoBranchElimLoop(t *testing.T) {
+ for _, arch := range []string{"arm64", "amd64"} {
+ t.Run(arch, func(t *testing.T) {
+ c := testConfigArch(t, arch)
+ boolType := c.config.Types.Bool
+ intType := c.config.Types.Int32
+
+ // The control flow here is totally bogus,
+ // but a dead cycle seems like the only plausible
+ // way to arrive at a diamond CFG that is also a loop.
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("const2", OpConst32, intType, 2, nil),
+ Valu("const3", OpConst32, intType, 3, nil),
+ Goto("b5")),
+ Bloc("b2",
+ Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
+ Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
+ Valu("phi", OpPhi, intType, 0, nil, "const2", "const3"),
+ If("cond", "b3", "b4")),
+ Bloc("b3",
+ Goto("b2")),
+ Bloc("b4",
+ Goto("b2")),
+ Bloc("b5",
+ Exit("start")))
+
+ CheckFunc(fun.f)
+ branchelim(fun.f)
+ CheckFunc(fun.f)
+
+ if len(fun.f.Blocks) != 5 {
+ t.Errorf("expected 5 block after branchelim; found %d", len(fun.f.Blocks))
+ }
+ if fun.values["phi"].Op != OpPhi {
+ t.Errorf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
+ }
+ })
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/cache.go b/src/cmd/compile/internal/ssa/cache.go
new file mode 100644
index 0000000..dbec2e1
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/cache.go
@@ -0,0 +1,81 @@
+// Copyright 2017 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 (
+ "cmd/internal/obj"
+ "sort"
+)
+
+// A Cache holds reusable compiler state.
+// It is intended to be re-used for multiple Func compilations.
+type Cache struct {
+ // Storage for low-numbered values and blocks.
+ values [2000]Value
+ blocks [200]Block
+ locs [2000]Location
+
+ // Reusable stackAllocState.
+ // See stackalloc.go's {new,put}StackAllocState.
+ stackAllocState *stackAllocState
+
+ domblockstore []ID // scratch space for computing dominators
+ scrSparseSet []*sparseSet // scratch sparse sets to be re-used.
+ scrSparseMap []*sparseMap // scratch sparse maps to be re-used.
+ scrPoset []*poset // scratch poset to be reused
+ // deadcode contains reusable slices specifically for the deadcode pass.
+ // It gets special treatment because of the frequency with which it is run.
+ deadcode struct {
+ liveOrderStmts []*Value
+ live []bool
+ q []*Value
+ }
+ // Reusable regalloc state.
+ regallocValues []valState
+
+ ValueToProgAfter []*obj.Prog
+ debugState debugState
+
+ Liveness interface{} // *gc.livenessFuncCache
+}
+
+func (c *Cache) Reset() {
+ nv := sort.Search(len(c.values), func(i int) bool { return c.values[i].ID == 0 })
+ xv := c.values[:nv]
+ for i := range xv {
+ xv[i] = Value{}
+ }
+ nb := sort.Search(len(c.blocks), func(i int) bool { return c.blocks[i].ID == 0 })
+ xb := c.blocks[:nb]
+ for i := range xb {
+ xb[i] = Block{}
+ }
+ nl := sort.Search(len(c.locs), func(i int) bool { return c.locs[i] == nil })
+ xl := c.locs[:nl]
+ for i := range xl {
+ xl[i] = nil
+ }
+
+ // regalloc sets the length of c.regallocValues to whatever it may use,
+ // so clear according to length.
+ for i := range c.regallocValues {
+ c.regallocValues[i] = valState{}
+ }
+
+ // liveOrderStmts gets used multiple times during compilation of a function.
+ // We don't know where the high water mark was, so reslice to cap and search.
+ c.deadcode.liveOrderStmts = c.deadcode.liveOrderStmts[:cap(c.deadcode.liveOrderStmts)]
+ no := sort.Search(len(c.deadcode.liveOrderStmts), func(i int) bool { return c.deadcode.liveOrderStmts[i] == nil })
+ xo := c.deadcode.liveOrderStmts[:no]
+ for i := range xo {
+ xo[i] = nil
+ }
+ c.deadcode.q = c.deadcode.q[:cap(c.deadcode.q)]
+ nq := sort.Search(len(c.deadcode.q), func(i int) bool { return c.deadcode.q[i] == nil })
+ xq := c.deadcode.q[:nq]
+ for i := range xq {
+ xq[i] = nil
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go
new file mode 100644
index 0000000..2dade7a
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/check.go
@@ -0,0 +1,597 @@
+// 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 (
+ "cmd/internal/obj/s390x"
+ "math"
+ "math/bits"
+)
+
+// checkFunc checks invariants of f.
+func checkFunc(f *Func) {
+ blockMark := make([]bool, f.NumBlocks())
+ valueMark := make([]bool, f.NumValues())
+
+ for _, b := range f.Blocks {
+ if blockMark[b.ID] {
+ f.Fatalf("block %s appears twice in %s!", b, f.Name)
+ }
+ blockMark[b.ID] = true
+ if b.Func != f {
+ f.Fatalf("%s.Func=%s, want %s", b, b.Func.Name, f.Name)
+ }
+
+ for i, e := range b.Preds {
+ if se := e.b.Succs[e.i]; se.b != b || se.i != i {
+ f.Fatalf("block pred/succ not crosslinked correctly %d:%s %d:%s", i, b, se.i, se.b)
+ }
+ }
+ for i, e := range b.Succs {
+ if pe := e.b.Preds[e.i]; pe.b != b || pe.i != i {
+ f.Fatalf("block succ/pred not crosslinked correctly %d:%s %d:%s", i, b, pe.i, pe.b)
+ }
+ }
+
+ switch b.Kind {
+ case BlockExit:
+ if len(b.Succs) != 0 {
+ f.Fatalf("exit block %s has successors", b)
+ }
+ if b.NumControls() != 1 {
+ f.Fatalf("exit block %s has no control value", b)
+ }
+ if !b.Controls[0].Type.IsMemory() {
+ f.Fatalf("exit block %s has non-memory control value %s", b, b.Controls[0].LongString())
+ }
+ case BlockRet:
+ if len(b.Succs) != 0 {
+ f.Fatalf("ret block %s has successors", b)
+ }
+ if b.NumControls() != 1 {
+ f.Fatalf("ret block %s has nil control", b)
+ }
+ if !b.Controls[0].Type.IsMemory() {
+ f.Fatalf("ret block %s has non-memory control value %s", b, b.Controls[0].LongString())
+ }
+ case BlockRetJmp:
+ if len(b.Succs) != 0 {
+ f.Fatalf("retjmp block %s len(Succs)==%d, want 0", b, len(b.Succs))
+ }
+ if b.NumControls() != 1 {
+ f.Fatalf("retjmp block %s has nil control", b)
+ }
+ if !b.Controls[0].Type.IsMemory() {
+ f.Fatalf("retjmp block %s has non-memory control value %s", b, b.Controls[0].LongString())
+ }
+ if b.Aux == nil {
+ f.Fatalf("retjmp block %s has nil Aux field", b)
+ }
+ case BlockPlain:
+ if len(b.Succs) != 1 {
+ f.Fatalf("plain block %s len(Succs)==%d, want 1", b, len(b.Succs))
+ }
+ if b.NumControls() != 0 {
+ f.Fatalf("plain block %s has non-nil control %s", b, b.Controls[0].LongString())
+ }
+ case BlockIf:
+ if len(b.Succs) != 2 {
+ f.Fatalf("if block %s len(Succs)==%d, want 2", b, len(b.Succs))
+ }
+ if b.NumControls() != 1 {
+ f.Fatalf("if block %s has no control value", b)
+ }
+ if !b.Controls[0].Type.IsBoolean() {
+ f.Fatalf("if block %s has non-bool control value %s", b, b.Controls[0].LongString())
+ }
+ case BlockDefer:
+ if len(b.Succs) != 2 {
+ f.Fatalf("defer block %s len(Succs)==%d, want 2", b, len(b.Succs))
+ }
+ if b.NumControls() != 1 {
+ f.Fatalf("defer block %s has no control value", b)
+ }
+ if !b.Controls[0].Type.IsMemory() {
+ f.Fatalf("defer block %s has non-memory control value %s", b, b.Controls[0].LongString())
+ }
+ case BlockFirst:
+ if len(b.Succs) != 2 {
+ f.Fatalf("plain/dead block %s len(Succs)==%d, want 2", b, len(b.Succs))
+ }
+ if b.NumControls() != 0 {
+ f.Fatalf("plain/dead block %s has a control value", b)
+ }
+ }
+ if len(b.Succs) != 2 && b.Likely != BranchUnknown {
+ f.Fatalf("likeliness prediction %d for block %s with %d successors", b.Likely, b, len(b.Succs))
+ }
+
+ for _, v := range b.Values {
+ // Check to make sure argument count makes sense (argLen of -1 indicates
+ // variable length args)
+ nArgs := opcodeTable[v.Op].argLen
+ if nArgs != -1 && int32(len(v.Args)) != nArgs {
+ f.Fatalf("value %s has %d args, expected %d", v.LongString(),
+ len(v.Args), nArgs)
+ }
+
+ // Check to make sure aux values make sense.
+ canHaveAux := false
+ canHaveAuxInt := false
+ // TODO: enforce types of Aux in this switch (like auxString does below)
+ switch opcodeTable[v.Op].auxType {
+ case auxNone:
+ case auxBool:
+ if v.AuxInt < 0 || v.AuxInt > 1 {
+ f.Fatalf("bad bool AuxInt value for %v", v)
+ }
+ canHaveAuxInt = true
+ case auxInt8:
+ if v.AuxInt != int64(int8(v.AuxInt)) {
+ f.Fatalf("bad int8 AuxInt value for %v", v)
+ }
+ canHaveAuxInt = true
+ case auxInt16:
+ if v.AuxInt != int64(int16(v.AuxInt)) {
+ f.Fatalf("bad int16 AuxInt value for %v", v)
+ }
+ canHaveAuxInt = true
+ case auxInt32:
+ if v.AuxInt != int64(int32(v.AuxInt)) {
+ f.Fatalf("bad int32 AuxInt value for %v", v)
+ }
+ canHaveAuxInt = true
+ case auxInt64, auxARM64BitField:
+ canHaveAuxInt = true
+ case auxInt128:
+ // AuxInt must be zero, so leave canHaveAuxInt set to false.
+ case auxUInt8:
+ if v.AuxInt != int64(uint8(v.AuxInt)) {
+ f.Fatalf("bad uint8 AuxInt value for %v", v)
+ }
+ canHaveAuxInt = true
+ case auxFloat32:
+ canHaveAuxInt = true
+ if math.IsNaN(v.AuxFloat()) {
+ f.Fatalf("value %v has an AuxInt that encodes a NaN", v)
+ }
+ if !isExactFloat32(v.AuxFloat()) {
+ f.Fatalf("value %v has an AuxInt value that is not an exact float32", v)
+ }
+ case auxFloat64:
+ canHaveAuxInt = true
+ if math.IsNaN(v.AuxFloat()) {
+ f.Fatalf("value %v has an AuxInt that encodes a NaN", v)
+ }
+ case auxString:
+ if _, ok := v.Aux.(string); !ok {
+ f.Fatalf("value %v has Aux type %T, want string", v, v.Aux)
+ }
+ canHaveAux = true
+ case auxCallOff:
+ canHaveAuxInt = true
+ fallthrough
+ case auxCall:
+ if ac, ok := v.Aux.(*AuxCall); ok {
+ if v.Op == OpStaticCall && ac.Fn == nil {
+ f.Fatalf("value %v has *AuxCall with nil Fn", v)
+ }
+ } else {
+ f.Fatalf("value %v has Aux type %T, want *AuxCall", v, v.Aux)
+ }
+ canHaveAux = true
+ case auxSym, auxTyp:
+ canHaveAux = true
+ case auxSymOff, auxSymValAndOff, auxTypSize:
+ canHaveAuxInt = true
+ canHaveAux = true
+ case auxCCop:
+ if opcodeTable[Op(v.AuxInt)].name == "OpInvalid" {
+ f.Fatalf("value %v has an AuxInt value that is a valid opcode", v)
+ }
+ canHaveAuxInt = true
+ case auxS390XCCMask:
+ if _, ok := v.Aux.(s390x.CCMask); !ok {
+ f.Fatalf("bad type %T for S390XCCMask in %v", v.Aux, v)
+ }
+ canHaveAux = true
+ case auxS390XRotateParams:
+ if _, ok := v.Aux.(s390x.RotateParams); !ok {
+ f.Fatalf("bad type %T for S390XRotateParams in %v", v.Aux, v)
+ }
+ canHaveAux = true
+ case auxFlagConstant:
+ if v.AuxInt < 0 || v.AuxInt > 15 {
+ f.Fatalf("bad FlagConstant AuxInt value for %v", v)
+ }
+ canHaveAuxInt = true
+ default:
+ f.Fatalf("unknown aux type for %s", v.Op)
+ }
+ if !canHaveAux && v.Aux != nil {
+ f.Fatalf("value %s has an Aux value %v but shouldn't", v.LongString(), v.Aux)
+ }
+ if !canHaveAuxInt && v.AuxInt != 0 {
+ f.Fatalf("value %s has an AuxInt value %d but shouldn't", v.LongString(), v.AuxInt)
+ }
+
+ for i, arg := range v.Args {
+ if arg == nil {
+ f.Fatalf("value %s has nil arg", v.LongString())
+ }
+ if v.Op != OpPhi {
+ // For non-Phi ops, memory args must be last, if present
+ if arg.Type.IsMemory() && i != len(v.Args)-1 {
+ f.Fatalf("value %s has non-final memory arg (%d < %d)", v.LongString(), i, len(v.Args)-1)
+ }
+ }
+ }
+
+ if valueMark[v.ID] {
+ f.Fatalf("value %s appears twice!", v.LongString())
+ }
+ valueMark[v.ID] = true
+
+ if v.Block != b {
+ f.Fatalf("%s.block != %s", v, b)
+ }
+ if v.Op == OpPhi && len(v.Args) != len(b.Preds) {
+ f.Fatalf("phi length %s does not match pred length %d for block %s", v.LongString(), len(b.Preds), b)
+ }
+
+ if v.Op == OpAddr {
+ if len(v.Args) == 0 {
+ f.Fatalf("no args for OpAddr %s", v.LongString())
+ }
+ if v.Args[0].Op != OpSB {
+ f.Fatalf("bad arg to OpAddr %v", v)
+ }
+ }
+
+ if v.Op == OpLocalAddr {
+ if len(v.Args) != 2 {
+ f.Fatalf("wrong # of args for OpLocalAddr %s", v.LongString())
+ }
+ if v.Args[0].Op != OpSP {
+ f.Fatalf("bad arg 0 to OpLocalAddr %v", v)
+ }
+ if !v.Args[1].Type.IsMemory() {
+ f.Fatalf("bad arg 1 to OpLocalAddr %v", v)
+ }
+ }
+
+ if f.RegAlloc != nil && f.Config.SoftFloat && v.Type.IsFloat() {
+ f.Fatalf("unexpected floating-point type %v", v.LongString())
+ }
+
+ // Check types.
+ // TODO: more type checks?
+ switch c := f.Config; v.Op {
+ case OpSP, OpSB:
+ if v.Type != c.Types.Uintptr {
+ f.Fatalf("bad %s type: want uintptr, have %s",
+ v.Op, v.Type.String())
+ }
+ case OpStringLen:
+ if v.Type != c.Types.Int {
+ f.Fatalf("bad %s type: want int, have %s",
+ v.Op, v.Type.String())
+ }
+ case OpLoad:
+ if !v.Args[1].Type.IsMemory() {
+ f.Fatalf("bad arg 1 type to %s: want mem, have %s",
+ v.Op, v.Args[1].Type.String())
+ }
+ case OpStore:
+ if !v.Type.IsMemory() {
+ f.Fatalf("bad %s type: want mem, have %s",
+ v.Op, v.Type.String())
+ }
+ if !v.Args[2].Type.IsMemory() {
+ f.Fatalf("bad arg 2 type to %s: want mem, have %s",
+ v.Op, v.Args[2].Type.String())
+ }
+ case OpCondSelect:
+ if !v.Args[2].Type.IsBoolean() {
+ f.Fatalf("bad arg 2 type to %s: want boolean, have %s",
+ v.Op, v.Args[2].Type.String())
+ }
+ case OpAddPtr:
+ if !v.Args[0].Type.IsPtrShaped() && v.Args[0].Type != c.Types.Uintptr {
+ f.Fatalf("bad arg 0 type to %s: want ptr, have %s", v.Op, v.Args[0].LongString())
+ }
+ if !v.Args[1].Type.IsInteger() {
+ f.Fatalf("bad arg 1 type to %s: want integer, have %s", v.Op, v.Args[1].LongString())
+ }
+
+ }
+
+ // TODO: check for cycles in values
+ }
+ }
+
+ // Check to make sure all Blocks referenced are in the function.
+ if !blockMark[f.Entry.ID] {
+ f.Fatalf("entry block %v is missing", f.Entry)
+ }
+ for _, b := range f.Blocks {
+ for _, c := range b.Preds {
+ if !blockMark[c.b.ID] {
+ f.Fatalf("predecessor block %v for %v is missing", c, b)
+ }
+ }
+ for _, c := range b.Succs {
+ if !blockMark[c.b.ID] {
+ f.Fatalf("successor block %v for %v is missing", c, b)
+ }
+ }
+ }
+
+ if len(f.Entry.Preds) > 0 {
+ f.Fatalf("entry block %s of %s has predecessor(s) %v", f.Entry, f.Name, f.Entry.Preds)
+ }
+
+ // Check to make sure all Values referenced are in the function.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ for i, a := range v.Args {
+ if !valueMark[a.ID] {
+ f.Fatalf("%v, arg %d of %s, is missing", a, i, v.LongString())
+ }
+ }
+ }
+ for _, c := range b.ControlValues() {
+ if !valueMark[c.ID] {
+ f.Fatalf("control value for %s is missing: %v", b, c)
+ }
+ }
+ }
+ for b := f.freeBlocks; b != nil; b = b.succstorage[0].b {
+ if blockMark[b.ID] {
+ f.Fatalf("used block b%d in free list", b.ID)
+ }
+ }
+ for v := f.freeValues; v != nil; v = v.argstorage[0] {
+ if valueMark[v.ID] {
+ f.Fatalf("used value v%d in free list", v.ID)
+ }
+ }
+
+ // Check to make sure all args dominate uses.
+ if f.RegAlloc == nil {
+ // Note: regalloc introduces non-dominating args.
+ // See TODO in regalloc.go.
+ sdom := f.Sdom()
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ for i, arg := range v.Args {
+ x := arg.Block
+ y := b
+ if v.Op == OpPhi {
+ y = b.Preds[i].b
+ }
+ if !domCheck(f, sdom, x, y) {
+ f.Fatalf("arg %d of value %s does not dominate, arg=%s", i, v.LongString(), arg.LongString())
+ }
+ }
+ }
+ for _, c := range b.ControlValues() {
+ if !domCheck(f, sdom, c.Block, b) {
+ f.Fatalf("control value %s for %s doesn't dominate", c, b)
+ }
+ }
+ }
+ }
+
+ // Check loop construction
+ if f.RegAlloc == nil && f.pass != nil { // non-nil pass allows better-targeted debug printing
+ ln := f.loopnest()
+ if !ln.hasIrreducible {
+ po := f.postorder() // use po to avoid unreachable blocks.
+ for _, b := range po {
+ for _, s := range b.Succs {
+ bb := s.Block()
+ if ln.b2l[b.ID] == nil && ln.b2l[bb.ID] != nil && bb != ln.b2l[bb.ID].header {
+ f.Fatalf("block %s not in loop branches to non-header block %s in loop", b.String(), bb.String())
+ }
+ if ln.b2l[b.ID] != nil && ln.b2l[bb.ID] != nil && bb != ln.b2l[bb.ID].header && !ln.b2l[b.ID].isWithinOrEq(ln.b2l[bb.ID]) {
+ f.Fatalf("block %s in loop branches to non-header block %s in non-containing loop", b.String(), bb.String())
+ }
+ }
+ }
+ }
+ }
+
+ // Check use counts
+ uses := make([]int32, f.NumValues())
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ for _, a := range v.Args {
+ uses[a.ID]++
+ }
+ }
+ for _, c := range b.ControlValues() {
+ uses[c.ID]++
+ }
+ }
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Uses != uses[v.ID] {
+ f.Fatalf("%s has %d uses, but has Uses=%d", v, uses[v.ID], v.Uses)
+ }
+ }
+ }
+
+ memCheck(f)
+}
+
+func memCheck(f *Func) {
+ // Check that if a tuple has a memory type, it is second.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Type.IsTuple() && v.Type.FieldType(0).IsMemory() {
+ f.Fatalf("memory is first in a tuple: %s\n", v.LongString())
+ }
+ }
+ }
+
+ // Single live memory checks.
+ // These checks only work if there are no memory copies.
+ // (Memory copies introduce ambiguity about which mem value is really live.
+ // probably fixable, but it's easier to avoid the problem.)
+ // For the same reason, disable this check if some memory ops are unused.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if (v.Op == OpCopy || v.Uses == 0) && v.Type.IsMemory() {
+ return
+ }
+ }
+ if b != f.Entry && len(b.Preds) == 0 {
+ return
+ }
+ }
+
+ // Compute live memory at the end of each block.
+ lastmem := make([]*Value, f.NumBlocks())
+ ss := newSparseSet(f.NumValues())
+ for _, b := range f.Blocks {
+ // Mark overwritten memory values. Those are args of other
+ // ops that generate memory values.
+ ss.clear()
+ for _, v := range b.Values {
+ if v.Op == OpPhi || !v.Type.IsMemory() {
+ continue
+ }
+ if m := v.MemoryArg(); m != nil {
+ ss.add(m.ID)
+ }
+ }
+ // There should be at most one remaining unoverwritten memory value.
+ for _, v := range b.Values {
+ if !v.Type.IsMemory() {
+ continue
+ }
+ if ss.contains(v.ID) {
+ continue
+ }
+ if lastmem[b.ID] != nil {
+ f.Fatalf("two live memory values in %s: %s and %s", b, lastmem[b.ID], v)
+ }
+ lastmem[b.ID] = v
+ }
+ // If there is no remaining memory value, that means there was no memory update.
+ // Take any memory arg.
+ if lastmem[b.ID] == nil {
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ continue
+ }
+ m := v.MemoryArg()
+ if m == nil {
+ continue
+ }
+ if lastmem[b.ID] != nil && lastmem[b.ID] != m {
+ f.Fatalf("two live memory values in %s: %s and %s", b, lastmem[b.ID], m)
+ }
+ lastmem[b.ID] = m
+ }
+ }
+ }
+ // Propagate last live memory through storeless blocks.
+ for {
+ changed := false
+ for _, b := range f.Blocks {
+ if lastmem[b.ID] != nil {
+ continue
+ }
+ for _, e := range b.Preds {
+ p := e.b
+ if lastmem[p.ID] != nil {
+ lastmem[b.ID] = lastmem[p.ID]
+ changed = true
+ break
+ }
+ }
+ }
+ if !changed {
+ break
+ }
+ }
+ // Check merge points.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op == OpPhi && v.Type.IsMemory() {
+ for i, a := range v.Args {
+ if a != lastmem[b.Preds[i].b.ID] {
+ f.Fatalf("inconsistent memory phi %s %d %s %s", v.LongString(), i, a, lastmem[b.Preds[i].b.ID])
+ }
+ }
+ }
+ }
+ }
+
+ // Check that only one memory is live at any point.
+ if f.scheduled {
+ for _, b := range f.Blocks {
+ var mem *Value // the current live memory in the block
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ if v.Type.IsMemory() {
+ mem = v
+ }
+ continue
+ }
+ if mem == nil && len(b.Preds) > 0 {
+ // If no mem phi, take mem of any predecessor.
+ mem = lastmem[b.Preds[0].b.ID]
+ }
+ for _, a := range v.Args {
+ if a.Type.IsMemory() && a != mem {
+ f.Fatalf("two live mems @ %s: %s and %s", v, mem, a)
+ }
+ }
+ if v.Type.IsMemory() {
+ mem = v
+ }
+ }
+ }
+ }
+
+ // Check that after scheduling, phis are always first in the block.
+ if f.scheduled {
+ for _, b := range f.Blocks {
+ seenNonPhi := false
+ for _, v := range b.Values {
+ switch v.Op {
+ case OpPhi:
+ if seenNonPhi {
+ f.Fatalf("phi after non-phi @ %s: %s", b, v)
+ }
+ default:
+ seenNonPhi = true
+ }
+ }
+ }
+ }
+}
+
+// domCheck reports whether x dominates y (including x==y).
+func domCheck(f *Func, sdom SparseTree, x, y *Block) bool {
+ if !sdom.IsAncestorEq(f.Entry, y) {
+ // unreachable - ignore
+ return true
+ }
+ return sdom.IsAncestorEq(x, y)
+}
+
+// isExactFloat32 reports whether x can be exactly represented as a float32.
+func isExactFloat32(x float64) bool {
+ // Check the mantissa is in range.
+ if bits.TrailingZeros64(math.Float64bits(x)) < 52-23 {
+ return false
+ }
+ // Check the exponent is in range. The mantissa check above is sufficient for NaN values.
+ return math.IsNaN(x) || x == float64(float32(x))
+}
diff --git a/src/cmd/compile/internal/ssa/checkbce.go b/src/cmd/compile/internal/ssa/checkbce.go
new file mode 100644
index 0000000..6a9ce2b
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/checkbce.go
@@ -0,0 +1,35 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import "cmd/compile/internal/logopt"
+
+// checkbce prints all bounds checks that are present in the function.
+// Useful to find regressions. checkbce is only activated when with
+// corresponding debug options, so it's off by default.
+// See test/checkbce.go
+func checkbce(f *Func) {
+ if f.pass.debug <= 0 && !logopt.Enabled() {
+ return
+ }
+
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op == OpIsInBounds || v.Op == OpIsSliceInBounds {
+ if f.pass.debug > 0 {
+ f.Warnl(v.Pos, "Found %v", v.Op)
+ }
+ if logopt.Enabled() {
+ if v.Op == OpIsInBounds {
+ logopt.LogOpt(v.Pos, "isInBounds", "checkbce", f.Name)
+ }
+ if v.Op == OpIsSliceInBounds {
+ logopt.LogOpt(v.Pos, "isSliceInBounds", "checkbce", f.Name)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go
new file mode 100644
index 0000000..63994d1
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/compile.go
@@ -0,0 +1,573 @@
+// 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 (
+ "bytes"
+ "cmd/internal/objabi"
+ "cmd/internal/src"
+ "fmt"
+ "hash/crc32"
+ "log"
+ "math/rand"
+ "os"
+ "regexp"
+ "runtime"
+ "sort"
+ "strings"
+ "time"
+)
+
+// Compile is the main entry point for this package.
+// Compile modifies f so that on return:
+// · all Values in f map to 0 or 1 assembly instructions of the target architecture
+// · the order of f.Blocks is the order to emit the Blocks
+// · the order of b.Values is the order to emit the Values in each Block
+// · f has a non-nil regAlloc field
+func Compile(f *Func) {
+ // TODO: debugging - set flags to control verbosity of compiler,
+ // which phases to dump IR before/after, etc.
+ if f.Log() {
+ f.Logf("compiling %s\n", f.Name)
+ }
+
+ var rnd *rand.Rand
+ if checkEnabled {
+ seed := int64(crc32.ChecksumIEEE(([]byte)(f.Name))) ^ int64(checkRandSeed)
+ rnd = rand.New(rand.NewSource(seed))
+ }
+
+ // hook to print function & phase if panic happens
+ phaseName := "init"
+ defer func() {
+ if phaseName != "" {
+ err := recover()
+ stack := make([]byte, 16384)
+ n := runtime.Stack(stack, false)
+ stack = stack[:n]
+ if f.HTMLWriter != nil {
+ f.HTMLWriter.flushPhases()
+ }
+ f.Fatalf("panic during %s while compiling %s:\n\n%v\n\n%s\n", phaseName, f.Name, err, stack)
+ }
+ }()
+
+ // Run all the passes
+ if f.Log() {
+ printFunc(f)
+ }
+ f.HTMLWriter.WritePhase("start", "start")
+ if BuildDump != "" && BuildDump == f.Name {
+ f.dumpFile("build")
+ }
+ if checkEnabled {
+ checkFunc(f)
+ }
+ const logMemStats = false
+ for _, p := range passes {
+ if !f.Config.optimize && !p.required || p.disabled {
+ continue
+ }
+ f.pass = &p
+ phaseName = p.name
+ if f.Log() {
+ f.Logf(" pass %s begin\n", p.name)
+ }
+ // TODO: capture logging during this pass, add it to the HTML
+ var mStart runtime.MemStats
+ if logMemStats || p.mem {
+ runtime.ReadMemStats(&mStart)
+ }
+
+ if checkEnabled && !f.scheduled {
+ // Test that we don't depend on the value order, by randomizing
+ // the order of values in each block. See issue 18169.
+ for _, b := range f.Blocks {
+ for i := 0; i < len(b.Values)-1; i++ {
+ j := i + rnd.Intn(len(b.Values)-i)
+ b.Values[i], b.Values[j] = b.Values[j], b.Values[i]
+ }
+ }
+ }
+
+ tStart := time.Now()
+ p.fn(f)
+ tEnd := time.Now()
+
+ // Need something less crude than "Log the whole intermediate result".
+ if f.Log() || f.HTMLWriter != nil {
+ time := tEnd.Sub(tStart).Nanoseconds()
+ var stats string
+ if logMemStats {
+ var mEnd runtime.MemStats
+ runtime.ReadMemStats(&mEnd)
+ nBytes := mEnd.TotalAlloc - mStart.TotalAlloc
+ nAllocs := mEnd.Mallocs - mStart.Mallocs
+ stats = fmt.Sprintf("[%d ns %d allocs %d bytes]", time, nAllocs, nBytes)
+ } else {
+ stats = fmt.Sprintf("[%d ns]", time)
+ }
+
+ if f.Log() {
+ f.Logf(" pass %s end %s\n", p.name, stats)
+ printFunc(f)
+ }
+ f.HTMLWriter.WritePhase(phaseName, fmt.Sprintf("%s <span class=\"stats\">%s</span>", phaseName, stats))
+ }
+ if p.time || p.mem {
+ // Surround timing information w/ enough context to allow comparisons.
+ time := tEnd.Sub(tStart).Nanoseconds()
+ if p.time {
+ f.LogStat("TIME(ns)", time)
+ }
+ if p.mem {
+ var mEnd runtime.MemStats
+ runtime.ReadMemStats(&mEnd)
+ nBytes := mEnd.TotalAlloc - mStart.TotalAlloc
+ nAllocs := mEnd.Mallocs - mStart.Mallocs
+ f.LogStat("TIME(ns):BYTES:ALLOCS", time, nBytes, nAllocs)
+ }
+ }
+ if p.dump != nil && p.dump[f.Name] {
+ // Dump function to appropriately named file
+ f.dumpFile(phaseName)
+ }
+ if checkEnabled {
+ checkFunc(f)
+ }
+ }
+
+ if f.HTMLWriter != nil {
+ // Ensure we write any pending phases to the html
+ f.HTMLWriter.flushPhases()
+ }
+
+ if f.ruleMatches != nil {
+ var keys []string
+ for key := range f.ruleMatches {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+ buf := new(bytes.Buffer)
+ fmt.Fprintf(buf, "%s: ", f.Name)
+ for _, key := range keys {
+ fmt.Fprintf(buf, "%s=%d ", key, f.ruleMatches[key])
+ }
+ fmt.Fprint(buf, "\n")
+ fmt.Print(buf.String())
+ }
+
+ // Squash error printing defer
+ phaseName = ""
+}
+
+// dumpFile creates a file from the phase name and function name
+// Dumping is done to files to avoid buffering huge strings before
+// output.
+func (f *Func) dumpFile(phaseName string) {
+ f.dumpFileSeq++
+ fname := fmt.Sprintf("%s_%02d__%s.dump", f.Name, int(f.dumpFileSeq), phaseName)
+ fname = strings.Replace(fname, " ", "_", -1)
+ fname = strings.Replace(fname, "/", "_", -1)
+ fname = strings.Replace(fname, ":", "_", -1)
+
+ fi, err := os.Create(fname)
+ if err != nil {
+ f.Warnl(src.NoXPos, "Unable to create after-phase dump file %s", fname)
+ return
+ }
+
+ p := stringFuncPrinter{w: fi}
+ fprintFunc(p, f)
+ fi.Close()
+}
+
+type pass struct {
+ name string
+ fn func(*Func)
+ required bool
+ disabled bool
+ time bool // report time to run pass
+ mem bool // report mem stats to run pass
+ stats int // pass reports own "stats" (e.g., branches removed)
+ debug int // pass performs some debugging. =1 should be in error-testing-friendly Warnl format.
+ test int // pass-specific ad-hoc option, perhaps useful in development
+ dump map[string]bool // dump if function name matches
+}
+
+func (p *pass) addDump(s string) {
+ if p.dump == nil {
+ p.dump = make(map[string]bool)
+ }
+ p.dump[s] = true
+}
+
+func (p *pass) String() string {
+ if p == nil {
+ return "nil pass"
+ }
+ return p.name
+}
+
+// Run consistency checker between each phase
+var (
+ checkEnabled = false
+ checkRandSeed = 0
+)
+
+// Debug output
+var IntrinsicsDebug int
+var IntrinsicsDisable bool
+
+var BuildDebug int
+var BuildTest int
+var BuildStats int
+var BuildDump string // name of function to dump after initial build of ssa
+
+// PhaseOption sets the specified flag in the specified ssa phase,
+// returning empty string if this was successful or a string explaining
+// the error if it was not.
+// A version of the phase name with "_" replaced by " " is also checked for a match.
+// If the phase name begins a '~' then the rest of the underscores-replaced-with-blanks
+// version is used as a regular expression to match the phase name(s).
+//
+// Special cases that have turned out to be useful:
+// ssa/check/on enables checking after each phase
+// ssa/all/time enables time reporting for all phases
+//
+// See gc/lex.go for dissection of the option string.
+// Example uses:
+//
+// GO_GCFLAGS=-d=ssa/generic_cse/time,ssa/generic_cse/stats,ssa/generic_cse/debug=3 ./make.bash
+//
+// BOOT_GO_GCFLAGS=-d='ssa/~^.*scc$/off' GO_GCFLAGS='-d=ssa/~^.*scc$/off' ./make.bash
+//
+func PhaseOption(phase, flag string, val int, valString string) string {
+ switch phase {
+ case "", "help":
+ lastcr := 0
+ phasenames := " check, all, build, intrinsics"
+ for _, p := range passes {
+ pn := strings.Replace(p.name, " ", "_", -1)
+ if len(pn)+len(phasenames)-lastcr > 70 {
+ phasenames += "\n "
+ lastcr = len(phasenames)
+ phasenames += pn
+ } else {
+ phasenames += ", " + pn
+ }
+ }
+ return `PhaseOptions usage:
+
+ go tool compile -d=ssa/<phase>/<flag>[=<value>|<function_name>]
+
+where:
+
+- <phase> is one of:
+` + phasenames + `
+
+- <flag> is one of:
+ on, off, debug, mem, time, test, stats, dump, seed
+
+- <value> defaults to 1
+
+- <function_name> is required for the "dump" flag, and specifies the
+ name of function to dump after <phase>
+
+Phase "all" supports flags "time", "mem", and "dump".
+Phase "intrinsics" supports flags "on", "off", and "debug".
+
+If the "dump" flag is specified, the output is written on a file named
+<phase>__<function_name>_<seq>.dump; otherwise it is directed to stdout.
+
+Examples:
+
+ -d=ssa/check/on
+enables checking after each phase
+
+ -d=ssa/check/seed=1234
+enables checking after each phase, using 1234 to seed the PRNG
+used for value order randomization
+
+ -d=ssa/all/time
+enables time reporting for all phases
+
+ -d=ssa/prove/debug=2
+sets debugging level to 2 in the prove pass
+
+Multiple flags can be passed at once, by separating them with
+commas. For example:
+
+ -d=ssa/check/on,ssa/all/time
+`
+ }
+
+ if phase == "check" {
+ switch flag {
+ case "on":
+ checkEnabled = val != 0
+ debugPoset = checkEnabled // also turn on advanced self-checking in prove's datastructure
+ return ""
+ case "off":
+ checkEnabled = val == 0
+ debugPoset = checkEnabled
+ return ""
+ case "seed":
+ checkEnabled = true
+ checkRandSeed = val
+ debugPoset = checkEnabled
+ return ""
+ }
+ }
+
+ alltime := false
+ allmem := false
+ alldump := false
+ if phase == "all" {
+ switch flag {
+ case "time":
+ alltime = val != 0
+ case "mem":
+ allmem = val != 0
+ case "dump":
+ alldump = val != 0
+ if alldump {
+ BuildDump = valString
+ }
+ default:
+ return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option", flag, phase)
+ }
+ }
+
+ if phase == "intrinsics" {
+ switch flag {
+ case "on":
+ IntrinsicsDisable = val == 0
+ case "off":
+ IntrinsicsDisable = val != 0
+ case "debug":
+ IntrinsicsDebug = val
+ default:
+ return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option", flag, phase)
+ }
+ return ""
+ }
+ if phase == "build" {
+ switch flag {
+ case "debug":
+ BuildDebug = val
+ case "test":
+ BuildTest = val
+ case "stats":
+ BuildStats = val
+ case "dump":
+ BuildDump = valString
+ default:
+ return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option", flag, phase)
+ }
+ return ""
+ }
+
+ underphase := strings.Replace(phase, "_", " ", -1)
+ var re *regexp.Regexp
+ if phase[0] == '~' {
+ r, ok := regexp.Compile(underphase[1:])
+ if ok != nil {
+ return fmt.Sprintf("Error %s in regexp for phase %s, flag %s", ok.Error(), phase, flag)
+ }
+ re = r
+ }
+ matchedOne := false
+ for i, p := range passes {
+ if phase == "all" {
+ p.time = alltime
+ p.mem = allmem
+ if alldump {
+ p.addDump(valString)
+ }
+ passes[i] = p
+ matchedOne = true
+ } else if p.name == phase || p.name == underphase || re != nil && re.MatchString(p.name) {
+ switch flag {
+ case "on":
+ p.disabled = val == 0
+ case "off":
+ p.disabled = val != 0
+ case "time":
+ p.time = val != 0
+ case "mem":
+ p.mem = val != 0
+ case "debug":
+ p.debug = val
+ case "stats":
+ p.stats = val
+ case "test":
+ p.test = val
+ case "dump":
+ p.addDump(valString)
+ default:
+ return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option", flag, phase)
+ }
+ if p.disabled && p.required {
+ return fmt.Sprintf("Cannot disable required SSA phase %s using -d=ssa/%s debug option", phase, phase)
+ }
+ passes[i] = p
+ matchedOne = true
+ }
+ }
+ if matchedOne {
+ return ""
+ }
+ return fmt.Sprintf("Did not find a phase matching %s in -d=ssa/... debug option", phase)
+}
+
+// list of passes for the compiler
+var passes = [...]pass{
+ // TODO: combine phielim and copyelim into a single pass?
+ {name: "number lines", fn: numberLines, required: true},
+ {name: "early phielim", fn: phielim},
+ {name: "early copyelim", fn: copyelim},
+ {name: "early deadcode", fn: deadcode}, // remove generated dead code to avoid doing pointless work during opt
+ {name: "short circuit", fn: shortcircuit},
+ {name: "decompose args", fn: decomposeArgs, required: !go116lateCallExpansion, disabled: go116lateCallExpansion}, // handled by late call lowering
+ {name: "decompose user", fn: decomposeUser, required: true},
+ {name: "pre-opt deadcode", fn: deadcode},
+ {name: "opt", fn: opt, required: true}, // NB: some generic rules know the name of the opt pass. TODO: split required rules and optimizing rules
+ {name: "zero arg cse", fn: zcse, required: true}, // required to merge OpSB values
+ {name: "opt deadcode", fn: deadcode, required: true}, // remove any blocks orphaned during opt
+ {name: "generic cse", fn: cse},
+ {name: "phiopt", fn: phiopt},
+ {name: "gcse deadcode", fn: deadcode, required: true}, // clean out after cse and phiopt
+ {name: "nilcheckelim", fn: nilcheckelim},
+ {name: "prove", fn: prove},
+ {name: "early fuse", fn: fuseEarly},
+ {name: "decompose builtin", fn: decomposeBuiltIn, required: true},
+ {name: "expand calls", fn: expandCalls, required: true},
+ {name: "softfloat", fn: softfloat, required: true},
+ {name: "late opt", fn: opt, required: true}, // TODO: split required rules and optimizing rules
+ {name: "dead auto elim", fn: elimDeadAutosGeneric},
+ {name: "generic deadcode", fn: deadcode, required: true}, // remove dead stores, which otherwise mess up store chain
+ {name: "check bce", fn: checkbce},
+ {name: "branchelim", fn: branchelim},
+ {name: "late fuse", fn: fuseLate},
+ {name: "dse", fn: dse},
+ {name: "writebarrier", fn: writebarrier, required: true}, // expand write barrier ops
+ {name: "insert resched checks", fn: insertLoopReschedChecks,
+ disabled: objabi.Preemptibleloops_enabled == 0}, // insert resched checks in loops.
+ {name: "lower", fn: lower, required: true},
+ {name: "addressing modes", fn: addressingModes, required: false},
+ {name: "lowered deadcode for cse", fn: deadcode}, // deadcode immediately before CSE avoids CSE making dead values live again
+ {name: "lowered cse", fn: cse},
+ {name: "elim unread autos", fn: elimUnreadAutos},
+ {name: "tighten tuple selectors", fn: tightenTupleSelectors, required: true},
+ {name: "lowered deadcode", fn: deadcode, required: true},
+ {name: "checkLower", fn: checkLower, required: true},
+ {name: "late phielim", fn: phielim},
+ {name: "late copyelim", fn: copyelim},
+ {name: "tighten", fn: tighten}, // move values closer to their uses
+ {name: "late deadcode", fn: deadcode},
+ {name: "critical", fn: critical, required: true}, // remove critical edges
+ {name: "phi tighten", fn: phiTighten}, // place rematerializable phi args near uses to reduce value lifetimes
+ {name: "likelyadjust", fn: likelyadjust},
+ {name: "layout", fn: layout, required: true}, // schedule blocks
+ {name: "schedule", fn: schedule, required: true}, // schedule values
+ {name: "late nilcheck", fn: nilcheckelim2},
+ {name: "flagalloc", fn: flagalloc, required: true}, // allocate flags register
+ {name: "regalloc", fn: regalloc, required: true}, // allocate int & float registers + stack slots
+ {name: "loop rotate", fn: loopRotate},
+ {name: "stackframe", fn: stackframe, required: true},
+ {name: "trim", fn: trim}, // remove empty blocks
+}
+
+// Double-check phase ordering constraints.
+// This code is intended to document the ordering requirements
+// between different phases. It does not override the passes
+// list above.
+type constraint struct {
+ a, b string // a must come before b
+}
+
+var passOrder = [...]constraint{
+ // "insert resched checks" uses mem, better to clean out stores first.
+ {"dse", "insert resched checks"},
+ // insert resched checks adds new blocks containing generic instructions
+ {"insert resched checks", "lower"},
+ {"insert resched checks", "tighten"},
+
+ // prove relies on common-subexpression elimination for maximum benefits.
+ {"generic cse", "prove"},
+ // deadcode after prove to eliminate all new dead blocks.
+ {"prove", "generic deadcode"},
+ // common-subexpression before dead-store elim, so that we recognize
+ // when two address expressions are the same.
+ {"generic cse", "dse"},
+ // cse substantially improves nilcheckelim efficacy
+ {"generic cse", "nilcheckelim"},
+ // allow deadcode to clean up after nilcheckelim
+ {"nilcheckelim", "generic deadcode"},
+ // nilcheckelim generates sequences of plain basic blocks
+ {"nilcheckelim", "late fuse"},
+ // nilcheckelim relies on opt to rewrite user nil checks
+ {"opt", "nilcheckelim"},
+ // tighten will be most effective when as many values have been removed as possible
+ {"generic deadcode", "tighten"},
+ {"generic cse", "tighten"},
+ // checkbce needs the values removed
+ {"generic deadcode", "check bce"},
+ // don't run optimization pass until we've decomposed builtin objects
+ {"decompose builtin", "late opt"},
+ // decompose builtin is the last pass that may introduce new float ops, so run softfloat after it
+ {"decompose builtin", "softfloat"},
+ // tuple selectors must be tightened to generators and de-duplicated before scheduling
+ {"tighten tuple selectors", "schedule"},
+ // remove critical edges before phi tighten, so that phi args get better placement
+ {"critical", "phi tighten"},
+ // don't layout blocks until critical edges have been removed
+ {"critical", "layout"},
+ // regalloc requires the removal of all critical edges
+ {"critical", "regalloc"},
+ // regalloc requires all the values in a block to be scheduled
+ {"schedule", "regalloc"},
+ // checkLower must run after lowering & subsequent dead code elim
+ {"lower", "checkLower"},
+ {"lowered deadcode", "checkLower"},
+ // late nilcheck needs instructions to be scheduled.
+ {"schedule", "late nilcheck"},
+ // flagalloc needs instructions to be scheduled.
+ {"schedule", "flagalloc"},
+ // regalloc needs flags to be allocated first.
+ {"flagalloc", "regalloc"},
+ // loopRotate will confuse regalloc.
+ {"regalloc", "loop rotate"},
+ // stackframe needs to know about spilled registers.
+ {"regalloc", "stackframe"},
+ // trim needs regalloc to be done first.
+ {"regalloc", "trim"},
+}
+
+func init() {
+ for _, c := range passOrder {
+ a, b := c.a, c.b
+ i := -1
+ j := -1
+ for k, p := range passes {
+ if p.name == a {
+ i = k
+ }
+ if p.name == b {
+ j = k
+ }
+ }
+ if i < 0 {
+ log.Panicf("pass %s not found", a)
+ }
+ if j < 0 {
+ log.Panicf("pass %s not found", b)
+ }
+ if i >= j {
+ log.Panicf("passes %s and %s out of order", a, b)
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go
new file mode 100644
index 0000000..0fe0337
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/config.go
@@ -0,0 +1,390 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "cmd/internal/obj"
+ "cmd/internal/objabi"
+ "cmd/internal/src"
+)
+
+// A Config holds readonly compilation information.
+// It is created once, early during compilation,
+// and shared across all compilations.
+type Config struct {
+ arch string // "amd64", etc.
+ PtrSize int64 // 4 or 8; copy of cmd/internal/sys.Arch.PtrSize
+ RegSize int64 // 4 or 8; copy of cmd/internal/sys.Arch.RegSize
+ Types Types
+ lowerBlock blockRewriter // lowering function
+ lowerValue valueRewriter // lowering function
+ splitLoad valueRewriter // function for splitting merged load ops; only used on some architectures
+ registers []Register // machine registers
+ gpRegMask regMask // general purpose integer register mask
+ fpRegMask regMask // floating point register mask
+ fp32RegMask regMask // floating point register mask
+ fp64RegMask regMask // floating point register mask
+ specialRegMask regMask // special register mask
+ GCRegMap []*Register // garbage collector register map, by GC register index
+ FPReg int8 // register number of frame pointer, -1 if not used
+ LinkReg int8 // register number of link register if it is a general purpose register, -1 if not used
+ hasGReg bool // has hardware g register
+ ctxt *obj.Link // Generic arch information
+ optimize bool // Do optimization
+ noDuffDevice bool // Don't use Duff's device
+ useSSE bool // Use SSE for non-float operations
+ useAvg bool // Use optimizations that need Avg* operations
+ useHmul bool // Use optimizations that need Hmul* operations
+ SoftFloat bool //
+ Race bool // race detector enabled
+ NeedsFpScratch bool // No direct move between GP and FP register sets
+ BigEndian bool //
+ UseFMA bool // Use hardware FMA operation
+}
+
+type (
+ blockRewriter func(*Block) bool
+ valueRewriter func(*Value) bool
+)
+
+type Types struct {
+ Bool *types.Type
+ Int8 *types.Type
+ Int16 *types.Type
+ Int32 *types.Type
+ Int64 *types.Type
+ UInt8 *types.Type
+ UInt16 *types.Type
+ UInt32 *types.Type
+ UInt64 *types.Type
+ Int *types.Type
+ Float32 *types.Type
+ Float64 *types.Type
+ UInt *types.Type
+ Uintptr *types.Type
+ String *types.Type
+ BytePtr *types.Type // TODO: use unsafe.Pointer instead?
+ Int32Ptr *types.Type
+ UInt32Ptr *types.Type
+ IntPtr *types.Type
+ UintptrPtr *types.Type
+ Float32Ptr *types.Type
+ Float64Ptr *types.Type
+ BytePtrPtr *types.Type
+}
+
+// NewTypes creates and populates a Types.
+func NewTypes() *Types {
+ t := new(Types)
+ t.SetTypPtrs()
+ return t
+}
+
+// SetTypPtrs populates t.
+func (t *Types) SetTypPtrs() {
+ t.Bool = types.Types[types.TBOOL]
+ t.Int8 = types.Types[types.TINT8]
+ t.Int16 = types.Types[types.TINT16]
+ t.Int32 = types.Types[types.TINT32]
+ t.Int64 = types.Types[types.TINT64]
+ t.UInt8 = types.Types[types.TUINT8]
+ t.UInt16 = types.Types[types.TUINT16]
+ t.UInt32 = types.Types[types.TUINT32]
+ t.UInt64 = types.Types[types.TUINT64]
+ t.Int = types.Types[types.TINT]
+ t.Float32 = types.Types[types.TFLOAT32]
+ t.Float64 = types.Types[types.TFLOAT64]
+ t.UInt = types.Types[types.TUINT]
+ t.Uintptr = types.Types[types.TUINTPTR]
+ t.String = types.Types[types.TSTRING]
+ t.BytePtr = types.NewPtr(types.Types[types.TUINT8])
+ t.Int32Ptr = types.NewPtr(types.Types[types.TINT32])
+ t.UInt32Ptr = types.NewPtr(types.Types[types.TUINT32])
+ t.IntPtr = types.NewPtr(types.Types[types.TINT])
+ t.UintptrPtr = types.NewPtr(types.Types[types.TUINTPTR])
+ t.Float32Ptr = types.NewPtr(types.Types[types.TFLOAT32])
+ t.Float64Ptr = types.NewPtr(types.Types[types.TFLOAT64])
+ t.BytePtrPtr = types.NewPtr(types.NewPtr(types.Types[types.TUINT8]))
+}
+
+type Logger interface {
+ // Logf logs a message from the compiler.
+ Logf(string, ...interface{})
+
+ // Log reports whether logging is not a no-op
+ // some logging calls account for more than a few heap allocations.
+ Log() bool
+
+ // Fatal reports a compiler error and exits.
+ Fatalf(pos src.XPos, msg string, args ...interface{})
+
+ // Warnl writes compiler messages in the form expected by "errorcheck" tests
+ Warnl(pos src.XPos, fmt_ string, args ...interface{})
+
+ // Forwards the Debug flags from gc
+ Debug_checknil() bool
+}
+
+type Frontend interface {
+ CanSSA(t *types.Type) bool
+
+ Logger
+
+ // StringData returns a symbol pointing to the given string's contents.
+ StringData(string) *obj.LSym
+
+ // Auto returns a Node for an auto variable of the given type.
+ // The SSA compiler uses this function to allocate space for spills.
+ Auto(src.XPos, *types.Type) GCNode
+
+ // Given the name for a compound type, returns the name we should use
+ // for the parts of that compound type.
+ SplitString(LocalSlot) (LocalSlot, LocalSlot)
+ SplitInterface(LocalSlot) (LocalSlot, LocalSlot)
+ SplitSlice(LocalSlot) (LocalSlot, LocalSlot, LocalSlot)
+ SplitComplex(LocalSlot) (LocalSlot, LocalSlot)
+ SplitStruct(LocalSlot, int) LocalSlot
+ SplitArray(LocalSlot) LocalSlot // array must be length 1
+ SplitInt64(LocalSlot) (LocalSlot, LocalSlot) // returns (hi, lo)
+ SplitSlot(parent *LocalSlot, suffix string, offset int64, t *types.Type) LocalSlot
+
+ // DerefItab dereferences an itab function
+ // entry, given the symbol of the itab and
+ // the byte offset of the function pointer.
+ // It may return nil.
+ DerefItab(sym *obj.LSym, offset int64) *obj.LSym
+
+ // Line returns a string describing the given position.
+ Line(src.XPos) string
+
+ // AllocFrame assigns frame offsets to all live auto variables.
+ AllocFrame(f *Func)
+
+ // Syslook returns a symbol of the runtime function/variable with the
+ // given name.
+ Syslook(string) *obj.LSym
+
+ // UseWriteBarrier reports whether write barrier is enabled
+ UseWriteBarrier() bool
+
+ // SetWBPos indicates that a write barrier has been inserted
+ // in this function at position pos.
+ SetWBPos(pos src.XPos)
+
+ // MyImportPath provides the import name (roughly, the package) for the function being compiled.
+ MyImportPath() string
+}
+
+// interface used to hold a *gc.Node (a stack variable).
+// We'd use *gc.Node directly but that would lead to an import cycle.
+type GCNode interface {
+ Typ() *types.Type
+ String() string
+ IsSynthetic() bool
+ IsAutoTmp() bool
+ StorageClass() StorageClass
+}
+
+type StorageClass uint8
+
+const (
+ ClassAuto StorageClass = iota // local stack variable
+ ClassParam // argument
+ ClassParamOut // return value
+)
+
+const go116lateCallExpansion = true
+
+// LateCallExpansionEnabledWithin returns true if late call expansion should be tested
+// within compilation of a function/method.
+func LateCallExpansionEnabledWithin(f *Func) bool {
+ return go116lateCallExpansion
+}
+
+// NewConfig returns a new configuration object for the given architecture.
+func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config {
+ c := &Config{arch: arch, Types: types}
+ c.useAvg = true
+ c.useHmul = true
+ switch arch {
+ case "amd64":
+ c.PtrSize = 8
+ c.RegSize = 8
+ c.lowerBlock = rewriteBlockAMD64
+ c.lowerValue = rewriteValueAMD64
+ c.splitLoad = rewriteValueAMD64splitload
+ c.registers = registersAMD64[:]
+ c.gpRegMask = gpRegMaskAMD64
+ c.fpRegMask = fpRegMaskAMD64
+ c.FPReg = framepointerRegAMD64
+ c.LinkReg = linkRegAMD64
+ c.hasGReg = false
+ case "386":
+ c.PtrSize = 4
+ c.RegSize = 4
+ c.lowerBlock = rewriteBlock386
+ c.lowerValue = rewriteValue386
+ c.splitLoad = rewriteValue386splitload
+ c.registers = registers386[:]
+ c.gpRegMask = gpRegMask386
+ c.fpRegMask = fpRegMask386
+ c.FPReg = framepointerReg386
+ c.LinkReg = linkReg386
+ c.hasGReg = false
+ case "arm":
+ c.PtrSize = 4
+ c.RegSize = 4
+ c.lowerBlock = rewriteBlockARM
+ c.lowerValue = rewriteValueARM
+ c.registers = registersARM[:]
+ c.gpRegMask = gpRegMaskARM
+ c.fpRegMask = fpRegMaskARM
+ c.FPReg = framepointerRegARM
+ c.LinkReg = linkRegARM
+ c.hasGReg = true
+ case "arm64":
+ c.PtrSize = 8
+ c.RegSize = 8
+ c.lowerBlock = rewriteBlockARM64
+ c.lowerValue = rewriteValueARM64
+ c.registers = registersARM64[:]
+ c.gpRegMask = gpRegMaskARM64
+ c.fpRegMask = fpRegMaskARM64
+ c.FPReg = framepointerRegARM64
+ c.LinkReg = linkRegARM64
+ c.hasGReg = true
+ c.noDuffDevice = objabi.GOOS == "darwin" || objabi.GOOS == "ios" // darwin linker cannot handle BR26 reloc with non-zero addend
+ case "ppc64":
+ c.BigEndian = true
+ fallthrough
+ case "ppc64le":
+ c.PtrSize = 8
+ c.RegSize = 8
+ c.lowerBlock = rewriteBlockPPC64
+ c.lowerValue = rewriteValuePPC64
+ c.registers = registersPPC64[:]
+ c.gpRegMask = gpRegMaskPPC64
+ c.fpRegMask = fpRegMaskPPC64
+ c.FPReg = framepointerRegPPC64
+ c.LinkReg = linkRegPPC64
+ c.noDuffDevice = true // TODO: Resolve PPC64 DuffDevice (has zero, but not copy)
+ c.hasGReg = true
+ case "mips64":
+ c.BigEndian = true
+ fallthrough
+ case "mips64le":
+ c.PtrSize = 8
+ c.RegSize = 8
+ c.lowerBlock = rewriteBlockMIPS64
+ c.lowerValue = rewriteValueMIPS64
+ c.registers = registersMIPS64[:]
+ c.gpRegMask = gpRegMaskMIPS64
+ c.fpRegMask = fpRegMaskMIPS64
+ c.specialRegMask = specialRegMaskMIPS64
+ c.FPReg = framepointerRegMIPS64
+ c.LinkReg = linkRegMIPS64
+ c.hasGReg = true
+ case "s390x":
+ c.PtrSize = 8
+ c.RegSize = 8
+ c.lowerBlock = rewriteBlockS390X
+ c.lowerValue = rewriteValueS390X
+ c.registers = registersS390X[:]
+ c.gpRegMask = gpRegMaskS390X
+ c.fpRegMask = fpRegMaskS390X
+ c.FPReg = framepointerRegS390X
+ c.LinkReg = linkRegS390X
+ c.hasGReg = true
+ c.noDuffDevice = true
+ c.BigEndian = true
+ case "mips":
+ c.BigEndian = true
+ fallthrough
+ case "mipsle":
+ c.PtrSize = 4
+ c.RegSize = 4
+ c.lowerBlock = rewriteBlockMIPS
+ c.lowerValue = rewriteValueMIPS
+ c.registers = registersMIPS[:]
+ c.gpRegMask = gpRegMaskMIPS
+ c.fpRegMask = fpRegMaskMIPS
+ c.specialRegMask = specialRegMaskMIPS
+ c.FPReg = framepointerRegMIPS
+ c.LinkReg = linkRegMIPS
+ c.hasGReg = true
+ c.noDuffDevice = true
+ case "riscv64":
+ c.PtrSize = 8
+ c.RegSize = 8
+ c.lowerBlock = rewriteBlockRISCV64
+ c.lowerValue = rewriteValueRISCV64
+ c.registers = registersRISCV64[:]
+ c.gpRegMask = gpRegMaskRISCV64
+ c.fpRegMask = fpRegMaskRISCV64
+ c.FPReg = framepointerRegRISCV64
+ c.hasGReg = true
+ case "wasm":
+ c.PtrSize = 8
+ c.RegSize = 8
+ c.lowerBlock = rewriteBlockWasm
+ c.lowerValue = rewriteValueWasm
+ c.registers = registersWasm[:]
+ c.gpRegMask = gpRegMaskWasm
+ c.fpRegMask = fpRegMaskWasm
+ c.fp32RegMask = fp32RegMaskWasm
+ c.fp64RegMask = fp64RegMaskWasm
+ c.FPReg = framepointerRegWasm
+ c.LinkReg = linkRegWasm
+ c.hasGReg = true
+ c.noDuffDevice = true
+ c.useAvg = false
+ c.useHmul = false
+ default:
+ ctxt.Diag("arch %s not implemented", arch)
+ }
+ c.ctxt = ctxt
+ c.optimize = optimize
+ c.useSSE = true
+ c.UseFMA = true
+
+ // On Plan 9, floating point operations are not allowed in note handler.
+ if objabi.GOOS == "plan9" {
+ // Don't use FMA on Plan 9
+ c.UseFMA = false
+
+ // Don't use Duff's device and SSE on Plan 9 AMD64.
+ if arch == "amd64" {
+ c.noDuffDevice = true
+ c.useSSE = false
+ }
+ }
+
+ if ctxt.Flag_shared {
+ // LoweredWB is secretly a CALL and CALLs on 386 in
+ // shared mode get rewritten by obj6.go to go through
+ // the GOT, which clobbers BX.
+ opcodeTable[Op386LoweredWB].reg.clobbers |= 1 << 3 // BX
+ }
+
+ // Create the GC register map index.
+ // TODO: This is only used for debug printing. Maybe export config.registers?
+ gcRegMapSize := int16(0)
+ for _, r := range c.registers {
+ if r.gcNum+1 > gcRegMapSize {
+ gcRegMapSize = r.gcNum + 1
+ }
+ }
+ c.GCRegMap = make([]*Register, gcRegMapSize)
+ for i, r := range c.registers {
+ if r.gcNum != -1 {
+ c.GCRegMap[r.gcNum] = &c.registers[i]
+ }
+ }
+
+ return c
+}
+
+func (c *Config) Ctxt() *obj.Link { return c.ctxt }
diff --git a/src/cmd/compile/internal/ssa/copyelim.go b/src/cmd/compile/internal/ssa/copyelim.go
new file mode 100644
index 0000000..5954d3b
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/copyelim.go
@@ -0,0 +1,84 @@
+// 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
+
+// copyelim removes all uses of OpCopy values from f.
+// A subsequent deadcode pass is needed to actually remove the copies.
+func copyelim(f *Func) {
+ // Modify all values so no arg (including args
+ // of OpCopy) is a copy.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ copyelimValue(v)
+ }
+ }
+
+ // Update block control values.
+ for _, b := range f.Blocks {
+ for i, v := range b.ControlValues() {
+ if v.Op == OpCopy {
+ b.ReplaceControl(i, v.Args[0])
+ }
+ }
+ }
+
+ // Update named values.
+ for _, name := range f.Names {
+ values := f.NamedValues[name]
+ for i, v := range values {
+ if v.Op == OpCopy {
+ values[i] = v.Args[0]
+ }
+ }
+ }
+}
+
+// copySource returns the (non-copy) op which is the
+// ultimate source of v. v must be a copy op.
+func copySource(v *Value) *Value {
+ w := v.Args[0]
+
+ // This loop is just:
+ // for w.Op == OpCopy {
+ // w = w.Args[0]
+ // }
+ // but we take some extra care to make sure we
+ // don't get stuck in an infinite loop.
+ // Infinite copy loops may happen in unreachable code.
+ // (TODO: or can they? Needs a test.)
+ slow := w
+ var advance bool
+ for w.Op == OpCopy {
+ w = w.Args[0]
+ if w == slow {
+ w.reset(OpUnknown)
+ break
+ }
+ if advance {
+ slow = slow.Args[0]
+ }
+ advance = !advance
+ }
+
+ // The answer is w. Update all the copies we saw
+ // to point directly to w. Doing this update makes
+ // sure that we don't end up doing O(n^2) work
+ // for a chain of n copies.
+ for v != w {
+ x := v.Args[0]
+ v.SetArg(0, w)
+ v = x
+ }
+ return w
+}
+
+// copyelimValue ensures that no args of v are copies.
+func copyelimValue(v *Value) {
+ for i, a := range v.Args {
+ if a.Op == OpCopy {
+ v.SetArg(i, copySource(a))
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/copyelim_test.go b/src/cmd/compile/internal/ssa/copyelim_test.go
new file mode 100644
index 0000000..fe31b12
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/copyelim_test.go
@@ -0,0 +1,41 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "fmt"
+ "testing"
+)
+
+func BenchmarkCopyElim1(b *testing.B) { benchmarkCopyElim(b, 1) }
+func BenchmarkCopyElim10(b *testing.B) { benchmarkCopyElim(b, 10) }
+func BenchmarkCopyElim100(b *testing.B) { benchmarkCopyElim(b, 100) }
+func BenchmarkCopyElim1000(b *testing.B) { benchmarkCopyElim(b, 1000) }
+func BenchmarkCopyElim10000(b *testing.B) { benchmarkCopyElim(b, 10000) }
+func BenchmarkCopyElim100000(b *testing.B) { benchmarkCopyElim(b, 100000) }
+
+func benchmarkCopyElim(b *testing.B, n int) {
+ c := testConfig(b)
+
+ values := make([]interface{}, 0, n+2)
+ values = append(values, Valu("mem", OpInitMem, types.TypeMem, 0, nil))
+ last := "mem"
+ for i := 0; i < n; i++ {
+ name := fmt.Sprintf("copy%d", i)
+ values = append(values, Valu(name, OpCopy, types.TypeMem, 0, nil, last))
+ last = name
+ }
+ values = append(values, Exit(last))
+ // Reverse values array to make it hard
+ for i := 0; i < len(values)/2; i++ {
+ values[i], values[len(values)-1-i] = values[len(values)-1-i], values[i]
+ }
+
+ for i := 0; i < b.N; i++ {
+ fun := c.Fun("entry", Bloc("entry", values...))
+ Copyelim(fun.f)
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/critical.go b/src/cmd/compile/internal/ssa/critical.go
new file mode 100644
index 0000000..b85721e
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/critical.go
@@ -0,0 +1,116 @@
+// 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
+
+// critical splits critical edges (those that go from a block with
+// more than one outedge to a block with more than one inedge).
+// Regalloc wants a critical-edge-free CFG so it can implement phi values.
+func critical(f *Func) {
+ // maps from phi arg ID to the new block created for that argument
+ blocks := make([]*Block, f.NumValues())
+ // need to iterate over f.Blocks without range, as we might
+ // need to split critical edges on newly constructed blocks
+ for j := 0; j < len(f.Blocks); j++ {
+ b := f.Blocks[j]
+ if len(b.Preds) <= 1 {
+ continue
+ }
+
+ var phi *Value
+ // determine if we've only got a single phi in this
+ // block, this is easier to handle than the general
+ // case of a block with multiple phi values.
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ if phi != nil {
+ phi = nil
+ break
+ }
+ phi = v
+ }
+ }
+
+ // reset our block map
+ if phi != nil {
+ for _, v := range phi.Args {
+ blocks[v.ID] = nil
+ }
+ }
+
+ // split input edges coming from multi-output blocks.
+ for i := 0; i < len(b.Preds); {
+ e := b.Preds[i]
+ p := e.b
+ pi := e.i
+ if p.Kind == BlockPlain {
+ i++
+ continue // only single output block
+ }
+
+ var d *Block // new block used to remove critical edge
+ reusedBlock := false // if true, then this is not the first use of this block
+ if phi != nil {
+ argID := phi.Args[i].ID
+ // find or record the block that we used to split
+ // critical edges for this argument
+ if d = blocks[argID]; d == nil {
+ // splitting doesn't necessarily remove the critical edge,
+ // since we're iterating over len(f.Blocks) above, this forces
+ // the new blocks to be re-examined.
+ d = f.NewBlock(BlockPlain)
+ d.Pos = p.Pos
+ blocks[argID] = d
+ if f.pass.debug > 0 {
+ f.Warnl(p.Pos, "split critical edge")
+ }
+ } else {
+ reusedBlock = true
+ }
+ } else {
+ // no existing block, so allocate a new block
+ // to place on the edge
+ d = f.NewBlock(BlockPlain)
+ d.Pos = p.Pos
+ if f.pass.debug > 0 {
+ f.Warnl(p.Pos, "split critical edge")
+ }
+ }
+
+ // if this not the first argument for the
+ // block, then we need to remove the
+ // corresponding elements from the block
+ // predecessors and phi args
+ if reusedBlock {
+ // Add p->d edge
+ p.Succs[pi] = Edge{d, len(d.Preds)}
+ d.Preds = append(d.Preds, Edge{p, pi})
+
+ // Remove p as a predecessor from b.
+ b.removePred(i)
+
+ // Update corresponding phi args
+ n := len(b.Preds)
+ phi.Args[i].Uses--
+ phi.Args[i] = phi.Args[n]
+ phi.Args[n] = nil
+ phi.Args = phi.Args[:n]
+ // splitting occasionally leads to a phi having
+ // a single argument (occurs with -N)
+ if n == 1 {
+ phi.Op = OpCopy
+ }
+ // Don't increment i in this case because we moved
+ // an unprocessed predecessor down into slot i.
+ } else {
+ // splice it in
+ p.Succs[pi] = Edge{d, 0}
+ b.Preds[i] = Edge{d, 0}
+ d.Preds = append(d.Preds, Edge{p, pi})
+ d.Succs = append(d.Succs, Edge{b, i})
+ i++
+ }
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/cse.go b/src/cmd/compile/internal/ssa/cse.go
new file mode 100644
index 0000000..3b4f2be
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/cse.go
@@ -0,0 +1,373 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "fmt"
+ "sort"
+)
+
+// cse does common-subexpression elimination on the Function.
+// Values are just relinked, nothing is deleted. A subsequent deadcode
+// pass is required to actually remove duplicate expressions.
+func cse(f *Func) {
+ // Two values are equivalent if they satisfy the following definition:
+ // equivalent(v, w):
+ // v.op == w.op
+ // v.type == w.type
+ // v.aux == w.aux
+ // v.auxint == w.auxint
+ // len(v.args) == len(w.args)
+ // v.block == w.block if v.op == OpPhi
+ // equivalent(v.args[i], w.args[i]) for i in 0..len(v.args)-1
+
+ // The algorithm searches for a partition of f's values into
+ // equivalence classes using the above definition.
+ // It starts with a coarse partition and iteratively refines it
+ // until it reaches a fixed point.
+
+ // Make initial coarse partitions by using a subset of the conditions above.
+ a := make([]*Value, 0, f.NumValues())
+ if f.auxmap == nil {
+ f.auxmap = auxmap{}
+ }
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Type.IsMemory() {
+ continue // memory values can never cse
+ }
+ if f.auxmap[v.Aux] == 0 {
+ f.auxmap[v.Aux] = int32(len(f.auxmap)) + 1
+ }
+ a = append(a, v)
+ }
+ }
+ partition := partitionValues(a, f.auxmap)
+
+ // map from value id back to eqclass id
+ valueEqClass := make([]ID, f.NumValues())
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ // Use negative equivalence class #s for unique values.
+ valueEqClass[v.ID] = -v.ID
+ }
+ }
+ var pNum ID = 1
+ for _, e := range partition {
+ if f.pass.debug > 1 && len(e) > 500 {
+ fmt.Printf("CSE.large partition (%d): ", len(e))
+ for j := 0; j < 3; j++ {
+ fmt.Printf("%s ", e[j].LongString())
+ }
+ fmt.Println()
+ }
+
+ for _, v := range e {
+ valueEqClass[v.ID] = pNum
+ }
+ if f.pass.debug > 2 && len(e) > 1 {
+ fmt.Printf("CSE.partition #%d:", pNum)
+ for _, v := range e {
+ fmt.Printf(" %s", v.String())
+ }
+ fmt.Printf("\n")
+ }
+ pNum++
+ }
+
+ // Split equivalence classes at points where they have
+ // non-equivalent arguments. Repeat until we can't find any
+ // more splits.
+ var splitPoints []int
+ byArgClass := new(partitionByArgClass) // reuseable partitionByArgClass to reduce allocations
+ for {
+ changed := false
+
+ // partition can grow in the loop. By not using a range loop here,
+ // we process new additions as they arrive, avoiding O(n^2) behavior.
+ for i := 0; i < len(partition); i++ {
+ e := partition[i]
+
+ if opcodeTable[e[0].Op].commutative {
+ // Order the first two args before comparison.
+ for _, v := range e {
+ if valueEqClass[v.Args[0].ID] > valueEqClass[v.Args[1].ID] {
+ v.Args[0], v.Args[1] = v.Args[1], v.Args[0]
+ }
+ }
+ }
+
+ // Sort by eq class of arguments.
+ byArgClass.a = e
+ byArgClass.eqClass = valueEqClass
+ sort.Sort(byArgClass)
+
+ // Find split points.
+ splitPoints = append(splitPoints[:0], 0)
+ for j := 1; j < len(e); j++ {
+ v, w := e[j-1], e[j]
+ // Note: commutative args already correctly ordered by byArgClass.
+ eqArgs := true
+ for k, a := range v.Args {
+ b := w.Args[k]
+ if valueEqClass[a.ID] != valueEqClass[b.ID] {
+ eqArgs = false
+ break
+ }
+ }
+ if !eqArgs {
+ splitPoints = append(splitPoints, j)
+ }
+ }
+ if len(splitPoints) == 1 {
+ continue // no splits, leave equivalence class alone.
+ }
+
+ // Move another equivalence class down in place of e.
+ partition[i] = partition[len(partition)-1]
+ partition = partition[:len(partition)-1]
+ i--
+
+ // Add new equivalence classes for the parts of e we found.
+ splitPoints = append(splitPoints, len(e))
+ for j := 0; j < len(splitPoints)-1; j++ {
+ f := e[splitPoints[j]:splitPoints[j+1]]
+ if len(f) == 1 {
+ // Don't add singletons.
+ valueEqClass[f[0].ID] = -f[0].ID
+ continue
+ }
+ for _, v := range f {
+ valueEqClass[v.ID] = pNum
+ }
+ pNum++
+ partition = append(partition, f)
+ }
+ changed = true
+ }
+
+ if !changed {
+ break
+ }
+ }
+
+ sdom := f.Sdom()
+
+ // Compute substitutions we would like to do. We substitute v for w
+ // if v and w are in the same equivalence class and v dominates w.
+ rewrite := make([]*Value, f.NumValues())
+ byDom := new(partitionByDom) // reusable partitionByDom to reduce allocs
+ for _, e := range partition {
+ byDom.a = e
+ byDom.sdom = sdom
+ sort.Sort(byDom)
+ for i := 0; i < len(e)-1; i++ {
+ // e is sorted by domorder, so a maximal dominant element is first in the slice
+ v := e[i]
+ if v == nil {
+ continue
+ }
+
+ e[i] = nil
+ // Replace all elements of e which v dominates
+ for j := i + 1; j < len(e); j++ {
+ w := e[j]
+ if w == nil {
+ continue
+ }
+ if sdom.IsAncestorEq(v.Block, w.Block) {
+ rewrite[w.ID] = v
+ e[j] = nil
+ } else {
+ // e is sorted by domorder, so v.Block doesn't dominate any subsequent blocks in e
+ break
+ }
+ }
+ }
+ }
+
+ rewrites := int64(0)
+
+ // Apply substitutions
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ for i, w := range v.Args {
+ if x := rewrite[w.ID]; x != nil {
+ if w.Pos.IsStmt() == src.PosIsStmt {
+ // about to lose a statement marker, w
+ // w is an input to v; if they're in the same block
+ // and the same line, v is a good-enough new statement boundary.
+ if w.Block == v.Block && w.Pos.Line() == v.Pos.Line() {
+ v.Pos = v.Pos.WithIsStmt()
+ w.Pos = w.Pos.WithNotStmt()
+ } // TODO and if this fails?
+ }
+ v.SetArg(i, x)
+ rewrites++
+ }
+ }
+ }
+ for i, v := range b.ControlValues() {
+ if x := rewrite[v.ID]; x != nil {
+ if v.Op == OpNilCheck {
+ // nilcheck pass will remove the nil checks and log
+ // them appropriately, so don't mess with them here.
+ continue
+ }
+ b.ReplaceControl(i, x)
+ }
+ }
+ }
+
+ if f.pass.stats > 0 {
+ f.LogStat("CSE REWRITES", rewrites)
+ }
+}
+
+// An eqclass approximates an equivalence class. During the
+// algorithm it may represent the union of several of the
+// final equivalence classes.
+type eqclass []*Value
+
+// partitionValues partitions the values into equivalence classes
+// based on having all the following features match:
+// - opcode
+// - type
+// - auxint
+// - aux
+// - nargs
+// - block # if a phi op
+// - first two arg's opcodes and auxint
+// - NOT first two arg's aux; that can break CSE.
+// partitionValues returns a list of equivalence classes, each
+// being a sorted by ID list of *Values. The eqclass slices are
+// backed by the same storage as the input slice.
+// Equivalence classes of size 1 are ignored.
+func partitionValues(a []*Value, auxIDs auxmap) []eqclass {
+ sort.Sort(sortvalues{a, auxIDs})
+
+ var partition []eqclass
+ for len(a) > 0 {
+ v := a[0]
+ j := 1
+ for ; j < len(a); j++ {
+ w := a[j]
+ if cmpVal(v, w, auxIDs) != types.CMPeq {
+ break
+ }
+ }
+ if j > 1 {
+ partition = append(partition, a[:j])
+ }
+ a = a[j:]
+ }
+
+ return partition
+}
+func lt2Cmp(isLt bool) types.Cmp {
+ if isLt {
+ return types.CMPlt
+ }
+ return types.CMPgt
+}
+
+type auxmap map[interface{}]int32
+
+func cmpVal(v, w *Value, auxIDs auxmap) types.Cmp {
+ // Try to order these comparison by cost (cheaper first)
+ if v.Op != w.Op {
+ return lt2Cmp(v.Op < w.Op)
+ }
+ if v.AuxInt != w.AuxInt {
+ return lt2Cmp(v.AuxInt < w.AuxInt)
+ }
+ if len(v.Args) != len(w.Args) {
+ return lt2Cmp(len(v.Args) < len(w.Args))
+ }
+ if v.Op == OpPhi && v.Block != w.Block {
+ return lt2Cmp(v.Block.ID < w.Block.ID)
+ }
+ if v.Type.IsMemory() {
+ // We will never be able to CSE two values
+ // that generate memory.
+ return lt2Cmp(v.ID < w.ID)
+ }
+ // OpSelect is a pseudo-op. We need to be more aggressive
+ // regarding CSE to keep multiple OpSelect's of the same
+ // argument from existing.
+ if v.Op != OpSelect0 && v.Op != OpSelect1 {
+ if tc := v.Type.Compare(w.Type); tc != types.CMPeq {
+ return tc
+ }
+ }
+
+ if v.Aux != w.Aux {
+ if v.Aux == nil {
+ return types.CMPlt
+ }
+ if w.Aux == nil {
+ return types.CMPgt
+ }
+ return lt2Cmp(auxIDs[v.Aux] < auxIDs[w.Aux])
+ }
+
+ return types.CMPeq
+}
+
+// Sort values to make the initial partition.
+type sortvalues struct {
+ a []*Value // array of values
+ auxIDs auxmap // aux -> aux ID map
+}
+
+func (sv sortvalues) Len() int { return len(sv.a) }
+func (sv sortvalues) Swap(i, j int) { sv.a[i], sv.a[j] = sv.a[j], sv.a[i] }
+func (sv sortvalues) Less(i, j int) bool {
+ v := sv.a[i]
+ w := sv.a[j]
+ if cmp := cmpVal(v, w, sv.auxIDs); cmp != types.CMPeq {
+ return cmp == types.CMPlt
+ }
+
+ // Sort by value ID last to keep the sort result deterministic.
+ return v.ID < w.ID
+}
+
+type partitionByDom struct {
+ a []*Value // array of values
+ sdom SparseTree
+}
+
+func (sv partitionByDom) Len() int { return len(sv.a) }
+func (sv partitionByDom) Swap(i, j int) { sv.a[i], sv.a[j] = sv.a[j], sv.a[i] }
+func (sv partitionByDom) Less(i, j int) bool {
+ v := sv.a[i]
+ w := sv.a[j]
+ return sv.sdom.domorder(v.Block) < sv.sdom.domorder(w.Block)
+}
+
+type partitionByArgClass struct {
+ a []*Value // array of values
+ eqClass []ID // equivalence class IDs of values
+}
+
+func (sv partitionByArgClass) Len() int { return len(sv.a) }
+func (sv partitionByArgClass) Swap(i, j int) { sv.a[i], sv.a[j] = sv.a[j], sv.a[i] }
+func (sv partitionByArgClass) Less(i, j int) bool {
+ v := sv.a[i]
+ w := sv.a[j]
+ for i, a := range v.Args {
+ b := w.Args[i]
+ if sv.eqClass[a.ID] < sv.eqClass[b.ID] {
+ return true
+ }
+ if sv.eqClass[a.ID] > sv.eqClass[b.ID] {
+ return false
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/cse_test.go b/src/cmd/compile/internal/ssa/cse_test.go
new file mode 100644
index 0000000..9e76645
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/cse_test.go
@@ -0,0 +1,129 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "testing"
+)
+
+type tstAux struct {
+ s string
+}
+
+// This tests for a bug found when partitioning, but not sorting by the Aux value.
+func TestCSEAuxPartitionBug(t *testing.T) {
+ c := testConfig(t)
+ arg1Aux := &tstAux{"arg1-aux"}
+ arg2Aux := &tstAux{"arg2-aux"}
+ arg3Aux := &tstAux{"arg3-aux"}
+ a := c.Frontend().Auto(src.NoXPos, c.config.Types.Int8)
+
+ // construct lots of values with args that have aux values and place
+ // them in an order that triggers the bug
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
+ Valu("r7", OpAdd64, c.config.Types.Int64, 0, nil, "arg3", "arg1"),
+ Valu("r1", OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
+ Valu("arg1", OpArg, c.config.Types.Int64, 0, arg1Aux),
+ Valu("arg2", OpArg, c.config.Types.Int64, 0, arg2Aux),
+ Valu("arg3", OpArg, c.config.Types.Int64, 0, arg3Aux),
+ Valu("r9", OpAdd64, c.config.Types.Int64, 0, nil, "r7", "r8"),
+ Valu("r4", OpAdd64, c.config.Types.Int64, 0, nil, "r1", "r2"),
+ Valu("r8", OpAdd64, c.config.Types.Int64, 0, nil, "arg3", "arg2"),
+ Valu("r2", OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
+ Valu("raddr", OpLocalAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sp", "start"),
+ Valu("raddrdef", OpVarDef, types.TypeMem, 0, a, "start"),
+ Valu("r6", OpAdd64, c.config.Types.Int64, 0, nil, "r4", "r5"),
+ Valu("r3", OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
+ Valu("r5", OpAdd64, c.config.Types.Int64, 0, nil, "r2", "r3"),
+ Valu("r10", OpAdd64, c.config.Types.Int64, 0, nil, "r6", "r9"),
+ Valu("rstore", OpStore, types.TypeMem, 0, c.config.Types.Int64, "raddr", "r10", "raddrdef"),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("rstore")))
+
+ CheckFunc(fun.f)
+ cse(fun.f)
+ deadcode(fun.f)
+ CheckFunc(fun.f)
+
+ s1Cnt := 2
+ // r1 == r2 == r3, needs to remove two of this set
+ s2Cnt := 1
+ // r4 == r5, needs to remove one of these
+ for k, v := range fun.values {
+ if v.Op == OpInvalid {
+ switch k {
+ case "r1":
+ fallthrough
+ case "r2":
+ fallthrough
+ case "r3":
+ if s1Cnt == 0 {
+ t.Errorf("cse removed all of r1,r2,r3")
+ }
+ s1Cnt--
+
+ case "r4":
+ fallthrough
+ case "r5":
+ if s2Cnt == 0 {
+ t.Errorf("cse removed all of r4,r5")
+ }
+ s2Cnt--
+ default:
+ t.Errorf("cse removed %s, but shouldn't have", k)
+ }
+ }
+ }
+
+ if s1Cnt != 0 || s2Cnt != 0 {
+ t.Errorf("%d values missed during cse", s1Cnt+s2Cnt)
+ }
+}
+
+// TestZCSE tests the zero arg cse.
+func TestZCSE(t *testing.T) {
+ c := testConfig(t)
+ a := c.Frontend().Auto(src.NoXPos, c.config.Types.Int8)
+
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
+ Valu("sb1", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("sb2", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("addr1", OpAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sb1"),
+ Valu("addr2", OpAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sb2"),
+ Valu("a1ld", OpLoad, c.config.Types.Int64, 0, nil, "addr1", "start"),
+ Valu("a2ld", OpLoad, c.config.Types.Int64, 0, nil, "addr2", "start"),
+ Valu("c1", OpConst64, c.config.Types.Int64, 1, nil),
+ Valu("r1", OpAdd64, c.config.Types.Int64, 0, nil, "a1ld", "c1"),
+ Valu("c2", OpConst64, c.config.Types.Int64, 1, nil),
+ Valu("r2", OpAdd64, c.config.Types.Int64, 0, nil, "a2ld", "c2"),
+ Valu("r3", OpAdd64, c.config.Types.Int64, 0, nil, "r1", "r2"),
+ Valu("raddr", OpLocalAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sp", "start"),
+ Valu("raddrdef", OpVarDef, types.TypeMem, 0, a, "start"),
+ Valu("rstore", OpStore, types.TypeMem, 0, c.config.Types.Int64, "raddr", "r3", "raddrdef"),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("rstore")))
+
+ CheckFunc(fun.f)
+ zcse(fun.f)
+ deadcode(fun.f)
+ CheckFunc(fun.f)
+
+ if fun.values["c1"].Op != OpInvalid && fun.values["c2"].Op != OpInvalid {
+ t.Errorf("zsce should have removed c1 or c2")
+ }
+ if fun.values["sb1"].Op != OpInvalid && fun.values["sb2"].Op != OpInvalid {
+ t.Errorf("zsce should have removed sb1 or sb2")
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go
new file mode 100644
index 0000000..96b552e
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/deadcode.go
@@ -0,0 +1,393 @@
+// 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 (
+ "cmd/internal/src"
+)
+
+// findlive returns the reachable blocks and live values in f.
+// The caller should call f.retDeadcodeLive(live) when it is done with it.
+func findlive(f *Func) (reachable []bool, live []bool) {
+ reachable = ReachableBlocks(f)
+ var order []*Value
+ live, order = liveValues(f, reachable)
+ f.retDeadcodeLiveOrderStmts(order)
+ return
+}
+
+// ReachableBlocks returns the reachable blocks in f.
+func ReachableBlocks(f *Func) []bool {
+ reachable := make([]bool, f.NumBlocks())
+ reachable[f.Entry.ID] = true
+ p := make([]*Block, 0, 64) // stack-like worklist
+ p = append(p, f.Entry)
+ for len(p) > 0 {
+ // Pop a reachable block
+ b := p[len(p)-1]
+ p = p[:len(p)-1]
+ // Mark successors as reachable
+ s := b.Succs
+ if b.Kind == BlockFirst {
+ s = s[:1]
+ }
+ for _, e := range s {
+ c := e.b
+ if int(c.ID) >= len(reachable) {
+ f.Fatalf("block %s >= f.NumBlocks()=%d?", c, len(reachable))
+ }
+ if !reachable[c.ID] {
+ reachable[c.ID] = true
+ p = append(p, c) // push
+ }
+ }
+ }
+ return reachable
+}
+
+// liveValues returns the live values in f and a list of values that are eligible
+// to be statements in reversed data flow order.
+// The second result is used to help conserve statement boundaries for debugging.
+// reachable is a map from block ID to whether the block is reachable.
+// The caller should call f.retDeadcodeLive(live) and f.retDeadcodeLiveOrderStmts(liveOrderStmts)
+// when they are done with the return values.
+func liveValues(f *Func, reachable []bool) (live []bool, liveOrderStmts []*Value) {
+ live = f.newDeadcodeLive()
+ if cap(live) < f.NumValues() {
+ live = make([]bool, f.NumValues())
+ } else {
+ live = live[:f.NumValues()]
+ for i := range live {
+ live[i] = false
+ }
+ }
+
+ liveOrderStmts = f.newDeadcodeLiveOrderStmts()
+ liveOrderStmts = liveOrderStmts[:0]
+
+ // After regalloc, consider all values to be live.
+ // See the comment at the top of regalloc.go and in deadcode for details.
+ if f.RegAlloc != nil {
+ for i := range live {
+ live[i] = true
+ }
+ return
+ }
+
+ // Record all the inline indexes we need
+ var liveInlIdx map[int]bool
+ pt := f.Config.ctxt.PosTable
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ i := pt.Pos(v.Pos).Base().InliningIndex()
+ if i < 0 {
+ continue
+ }
+ if liveInlIdx == nil {
+ liveInlIdx = map[int]bool{}
+ }
+ liveInlIdx[i] = true
+ }
+ i := pt.Pos(b.Pos).Base().InliningIndex()
+ if i < 0 {
+ continue
+ }
+ if liveInlIdx == nil {
+ liveInlIdx = map[int]bool{}
+ }
+ liveInlIdx[i] = true
+ }
+
+ // Find all live values
+ q := f.Cache.deadcode.q[:0]
+ defer func() { f.Cache.deadcode.q = q }()
+
+ // Starting set: all control values of reachable blocks are live.
+ // Calls are live (because callee can observe the memory state).
+ for _, b := range f.Blocks {
+ if !reachable[b.ID] {
+ continue
+ }
+ for _, v := range b.ControlValues() {
+ if !live[v.ID] {
+ live[v.ID] = true
+ q = append(q, v)
+ if v.Pos.IsStmt() != src.PosNotStmt {
+ liveOrderStmts = append(liveOrderStmts, v)
+ }
+ }
+ }
+ for _, v := range b.Values {
+ if (opcodeTable[v.Op].call || opcodeTable[v.Op].hasSideEffects) && !live[v.ID] {
+ live[v.ID] = true
+ q = append(q, v)
+ if v.Pos.IsStmt() != src.PosNotStmt {
+ liveOrderStmts = append(liveOrderStmts, v)
+ }
+ }
+ if v.Type.IsVoid() && !live[v.ID] {
+ // The only Void ops are nil checks and inline marks. We must keep these.
+ if v.Op == OpInlMark && !liveInlIdx[int(v.AuxInt)] {
+ // We don't need marks for bodies that
+ // have been completely optimized away.
+ // TODO: save marks only for bodies which
+ // have a faulting instruction or a call?
+ continue
+ }
+ live[v.ID] = true
+ q = append(q, v)
+ if v.Pos.IsStmt() != src.PosNotStmt {
+ liveOrderStmts = append(liveOrderStmts, v)
+ }
+ }
+ }
+ }
+
+ // Compute transitive closure of live values.
+ for len(q) > 0 {
+ // pop a reachable value
+ v := q[len(q)-1]
+ q = q[:len(q)-1]
+ for i, x := range v.Args {
+ if v.Op == OpPhi && !reachable[v.Block.Preds[i].b.ID] {
+ continue
+ }
+ if !live[x.ID] {
+ live[x.ID] = true
+ q = append(q, x) // push
+ if x.Pos.IsStmt() != src.PosNotStmt {
+ liveOrderStmts = append(liveOrderStmts, x)
+ }
+ }
+ }
+ }
+
+ return
+}
+
+// deadcode removes dead code from f.
+func deadcode(f *Func) {
+ // deadcode after regalloc is forbidden for now. Regalloc
+ // doesn't quite generate legal SSA which will lead to some
+ // required moves being eliminated. See the comment at the
+ // top of regalloc.go for details.
+ if f.RegAlloc != nil {
+ f.Fatalf("deadcode after regalloc")
+ }
+
+ // Find reachable blocks.
+ reachable := ReachableBlocks(f)
+
+ // Get rid of edges from dead to live code.
+ for _, b := range f.Blocks {
+ if reachable[b.ID] {
+ continue
+ }
+ for i := 0; i < len(b.Succs); {
+ e := b.Succs[i]
+ if reachable[e.b.ID] {
+ b.removeEdge(i)
+ } else {
+ i++
+ }
+ }
+ }
+
+ // Get rid of dead edges from live code.
+ for _, b := range f.Blocks {
+ if !reachable[b.ID] {
+ continue
+ }
+ if b.Kind != BlockFirst {
+ continue
+ }
+ b.removeEdge(1)
+ b.Kind = BlockPlain
+ b.Likely = BranchUnknown
+ }
+
+ // Splice out any copies introduced during dead block removal.
+ copyelim(f)
+
+ // Find live values.
+ live, order := liveValues(f, reachable)
+ defer f.retDeadcodeLive(live)
+ defer f.retDeadcodeLiveOrderStmts(order)
+
+ // Remove dead & duplicate entries from namedValues map.
+ s := f.newSparseSet(f.NumValues())
+ defer f.retSparseSet(s)
+ i := 0
+ for _, name := range f.Names {
+ j := 0
+ s.clear()
+ values := f.NamedValues[name]
+ for _, v := range values {
+ if live[v.ID] && !s.contains(v.ID) {
+ values[j] = v
+ j++
+ s.add(v.ID)
+ }
+ }
+ if j == 0 {
+ delete(f.NamedValues, name)
+ } else {
+ f.Names[i] = name
+ i++
+ for k := len(values) - 1; k >= j; k-- {
+ values[k] = nil
+ }
+ f.NamedValues[name] = values[:j]
+ }
+ }
+ clearNames := f.Names[i:]
+ for j := range clearNames {
+ clearNames[j] = LocalSlot{}
+ }
+ f.Names = f.Names[:i]
+
+ pendingLines := f.cachedLineStarts // Holds statement boundaries that need to be moved to a new value/block
+ pendingLines.clear()
+
+ // Unlink values and conserve statement boundaries
+ for i, b := range f.Blocks {
+ if !reachable[b.ID] {
+ // TODO what if control is statement boundary? Too late here.
+ b.ResetControls()
+ }
+ for _, v := range b.Values {
+ if !live[v.ID] {
+ v.resetArgs()
+ if v.Pos.IsStmt() == src.PosIsStmt && reachable[b.ID] {
+ pendingLines.set(v.Pos, int32(i)) // TODO could be more than one pos for a line
+ }
+ }
+ }
+ }
+
+ // Find new homes for lost lines -- require earliest in data flow with same line that is also in same block
+ for i := len(order) - 1; i >= 0; i-- {
+ w := order[i]
+ if j := pendingLines.get(w.Pos); j > -1 && f.Blocks[j] == w.Block {
+ w.Pos = w.Pos.WithIsStmt()
+ pendingLines.remove(w.Pos)
+ }
+ }
+
+ // Any boundary that failed to match a live value can move to a block end
+ pendingLines.foreachEntry(func(j int32, l uint, bi int32) {
+ b := f.Blocks[bi]
+ if b.Pos.Line() == l && b.Pos.FileIndex() == j {
+ b.Pos = b.Pos.WithIsStmt()
+ }
+ })
+
+ // Remove dead values from blocks' value list. Return dead
+ // values to the allocator.
+ for _, b := range f.Blocks {
+ i := 0
+ for _, v := range b.Values {
+ if live[v.ID] {
+ b.Values[i] = v
+ i++
+ } else {
+ f.freeValue(v)
+ }
+ }
+ b.truncateValues(i)
+ }
+
+ // Remove dead blocks from WBLoads list.
+ i = 0
+ for _, b := range f.WBLoads {
+ if reachable[b.ID] {
+ f.WBLoads[i] = b
+ i++
+ }
+ }
+ clearWBLoads := f.WBLoads[i:]
+ for j := range clearWBLoads {
+ clearWBLoads[j] = nil
+ }
+ f.WBLoads = f.WBLoads[:i]
+
+ // Remove unreachable blocks. Return dead blocks to allocator.
+ i = 0
+ for _, b := range f.Blocks {
+ if reachable[b.ID] {
+ f.Blocks[i] = b
+ i++
+ } else {
+ if len(b.Values) > 0 {
+ b.Fatalf("live values in unreachable block %v: %v", b, b.Values)
+ }
+ f.freeBlock(b)
+ }
+ }
+ // zero remainder to help GC
+ tail := f.Blocks[i:]
+ for j := range tail {
+ tail[j] = nil
+ }
+ f.Blocks = f.Blocks[:i]
+}
+
+// removeEdge removes the i'th outgoing edge from b (and
+// the corresponding incoming edge from b.Succs[i].b).
+func (b *Block) removeEdge(i int) {
+ e := b.Succs[i]
+ c := e.b
+ j := e.i
+
+ // Adjust b.Succs
+ b.removeSucc(i)
+
+ // Adjust c.Preds
+ c.removePred(j)
+
+ // Remove phi args from c's phis.
+ n := len(c.Preds)
+ for _, v := range c.Values {
+ if v.Op != OpPhi {
+ continue
+ }
+ v.Args[j].Uses--
+ v.Args[j] = v.Args[n]
+ v.Args[n] = nil
+ v.Args = v.Args[:n]
+ phielimValue(v)
+ // Note: this is trickier than it looks. Replacing
+ // a Phi with a Copy can in general cause problems because
+ // Phi and Copy don't have exactly the same semantics.
+ // Phi arguments always come from a predecessor block,
+ // whereas copies don't. This matters in loops like:
+ // 1: x = (Phi y)
+ // y = (Add x 1)
+ // goto 1
+ // If we replace Phi->Copy, we get
+ // 1: x = (Copy y)
+ // y = (Add x 1)
+ // goto 1
+ // (Phi y) refers to the *previous* value of y, whereas
+ // (Copy y) refers to the *current* value of y.
+ // The modified code has a cycle and the scheduler
+ // will barf on it.
+ //
+ // Fortunately, this situation can only happen for dead
+ // code loops. We know the code we're working with is
+ // not dead, so we're ok.
+ // Proof: If we have a potential bad cycle, we have a
+ // situation like this:
+ // x = (Phi z)
+ // y = (op1 x ...)
+ // z = (op2 y ...)
+ // Where opX are not Phi ops. But such a situation
+ // implies a cycle in the dominator graph. In the
+ // example, x.Block dominates y.Block, y.Block dominates
+ // z.Block, and z.Block dominates x.Block (treating
+ // "dominates" as reflexive). Cycles in the dominator
+ // graph can only happen in an unreachable cycle.
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/deadcode_test.go b/src/cmd/compile/internal/ssa/deadcode_test.go
new file mode 100644
index 0000000..5777b84
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/deadcode_test.go
@@ -0,0 +1,161 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "fmt"
+ "strconv"
+ "testing"
+)
+
+func TestDeadLoop(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")),
+ // dead loop
+ Bloc("deadblock",
+ // dead value in dead block
+ Valu("deadval", OpConstBool, c.config.Types.Bool, 1, nil),
+ If("deadval", "deadblock", "exit")))
+
+ CheckFunc(fun.f)
+ Deadcode(fun.f)
+ CheckFunc(fun.f)
+
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["deadblock"] {
+ t.Errorf("dead block not removed")
+ }
+ for _, v := range b.Values {
+ if v == fun.values["deadval"] {
+ t.Errorf("control value of dead block not removed")
+ }
+ }
+ }
+}
+
+func TestDeadValue(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("deadval", OpConst64, c.config.Types.Int64, 37, nil),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ Deadcode(fun.f)
+ CheckFunc(fun.f)
+
+ for _, b := range fun.f.Blocks {
+ for _, v := range b.Values {
+ if v == fun.values["deadval"] {
+ t.Errorf("dead value not removed")
+ }
+ }
+ }
+}
+
+func TestNeverTaken(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("cond", OpConstBool, c.config.Types.Bool, 0, nil),
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ If("cond", "then", "else")),
+ Bloc("then",
+ Goto("exit")),
+ Bloc("else",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ Opt(fun.f)
+ Deadcode(fun.f)
+ CheckFunc(fun.f)
+
+ if fun.blocks["entry"].Kind != BlockPlain {
+ t.Errorf("if(false) not simplified")
+ }
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["then"] {
+ t.Errorf("then block still present")
+ }
+ for _, v := range b.Values {
+ if v == fun.values["cond"] {
+ t.Errorf("constant condition still present")
+ }
+ }
+ }
+
+}
+
+func TestNestedDeadBlocks(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("cond", OpConstBool, c.config.Types.Bool, 0, nil),
+ If("cond", "b2", "b4")),
+ Bloc("b2",
+ If("cond", "b3", "b4")),
+ Bloc("b3",
+ If("cond", "b3", "b4")),
+ Bloc("b4",
+ If("cond", "b3", "exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ Opt(fun.f)
+ CheckFunc(fun.f)
+ Deadcode(fun.f)
+ CheckFunc(fun.f)
+ if fun.blocks["entry"].Kind != BlockPlain {
+ t.Errorf("if(false) not simplified")
+ }
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["b2"] {
+ t.Errorf("b2 block still present")
+ }
+ if b == fun.blocks["b3"] {
+ t.Errorf("b3 block still present")
+ }
+ for _, v := range b.Values {
+ if v == fun.values["cond"] {
+ t.Errorf("constant condition still present")
+ }
+ }
+ }
+}
+
+func BenchmarkDeadCode(b *testing.B) {
+ for _, n := range [...]int{1, 10, 100, 1000, 10000, 100000, 200000} {
+ b.Run(strconv.Itoa(n), func(b *testing.B) {
+ c := testConfig(b)
+ blocks := make([]bloc, 0, n+2)
+ blocks = append(blocks,
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Goto("exit")))
+ blocks = append(blocks, Bloc("exit", Exit("mem")))
+ for i := 0; i < n; i++ {
+ blocks = append(blocks, Bloc(fmt.Sprintf("dead%d", i), Goto("exit")))
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ fun := c.Fun("entry", blocks...)
+ Deadcode(fun.f)
+ }
+ })
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go
new file mode 100644
index 0000000..0664013
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/deadstore.go
@@ -0,0 +1,348 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+)
+
+// dse does dead-store elimination on the Function.
+// Dead stores are those which are unconditionally followed by
+// another store to the same location, with no intervening load.
+// This implementation only works within a basic block. TODO: use something more global.
+func dse(f *Func) {
+ var stores []*Value
+ loadUse := f.newSparseSet(f.NumValues())
+ defer f.retSparseSet(loadUse)
+ storeUse := f.newSparseSet(f.NumValues())
+ defer f.retSparseSet(storeUse)
+ shadowed := f.newSparseMap(f.NumValues())
+ defer f.retSparseMap(shadowed)
+ for _, b := range f.Blocks {
+ // Find all the stores in this block. Categorize their uses:
+ // loadUse contains stores which are used by a subsequent load.
+ // storeUse contains stores which are used by a subsequent store.
+ loadUse.clear()
+ storeUse.clear()
+ stores = stores[:0]
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ // Ignore phis - they will always be first and can't be eliminated
+ continue
+ }
+ if v.Type.IsMemory() {
+ stores = append(stores, v)
+ for _, a := range v.Args {
+ if a.Block == b && a.Type.IsMemory() {
+ storeUse.add(a.ID)
+ if v.Op != OpStore && v.Op != OpZero && v.Op != OpVarDef && v.Op != OpVarKill {
+ // CALL, DUFFCOPY, etc. are both
+ // reads and writes.
+ loadUse.add(a.ID)
+ }
+ }
+ }
+ } else {
+ for _, a := range v.Args {
+ if a.Block == b && a.Type.IsMemory() {
+ loadUse.add(a.ID)
+ }
+ }
+ }
+ }
+ if len(stores) == 0 {
+ continue
+ }
+
+ // find last store in the block
+ var last *Value
+ for _, v := range stores {
+ if storeUse.contains(v.ID) {
+ continue
+ }
+ if last != nil {
+ b.Fatalf("two final stores - simultaneous live stores %s %s", last.LongString(), v.LongString())
+ }
+ last = v
+ }
+ if last == nil {
+ b.Fatalf("no last store found - cycle?")
+ }
+
+ // Walk backwards looking for dead stores. Keep track of shadowed addresses.
+ // A "shadowed address" is a pointer and a size describing a memory region that
+ // is known to be written. We keep track of shadowed addresses in the shadowed
+ // map, mapping the ID of the address to the size of the shadowed region.
+ // Since we're walking backwards, writes to a shadowed region are useless,
+ // as they will be immediately overwritten.
+ shadowed.clear()
+ v := last
+
+ walkloop:
+ if loadUse.contains(v.ID) {
+ // Someone might be reading this memory state.
+ // Clear all shadowed addresses.
+ shadowed.clear()
+ }
+ if v.Op == OpStore || v.Op == OpZero {
+ var sz int64
+ if v.Op == OpStore {
+ sz = v.Aux.(*types.Type).Size()
+ } else { // OpZero
+ sz = v.AuxInt
+ }
+ if shadowedSize := int64(shadowed.get(v.Args[0].ID)); shadowedSize != -1 && shadowedSize >= sz {
+ // Modify the store/zero into a copy of the memory state,
+ // effectively eliding the store operation.
+ if v.Op == OpStore {
+ // store addr value mem
+ v.SetArgs1(v.Args[2])
+ } else {
+ // zero addr mem
+ v.SetArgs1(v.Args[1])
+ }
+ v.Aux = nil
+ v.AuxInt = 0
+ v.Op = OpCopy
+ } else {
+ if sz > 0x7fffffff { // work around sparseMap's int32 value type
+ sz = 0x7fffffff
+ }
+ shadowed.set(v.Args[0].ID, int32(sz), src.NoXPos)
+ }
+ }
+ // walk to previous store
+ if v.Op == OpPhi {
+ // At start of block. Move on to next block.
+ // The memory phi, if it exists, is always
+ // the first logical store in the block.
+ // (Even if it isn't the first in the current b.Values order.)
+ continue
+ }
+ for _, a := range v.Args {
+ if a.Block == b && a.Type.IsMemory() {
+ v = a
+ goto walkloop
+ }
+ }
+ }
+}
+
+// elimDeadAutosGeneric deletes autos that are never accessed. To achieve this
+// we track the operations that the address of each auto reaches and if it only
+// reaches stores then we delete all the stores. The other operations will then
+// be eliminated by the dead code elimination pass.
+func elimDeadAutosGeneric(f *Func) {
+ addr := make(map[*Value]GCNode) // values that the address of the auto reaches
+ elim := make(map[*Value]GCNode) // values that could be eliminated if the auto is
+ used := make(map[GCNode]bool) // used autos that must be kept
+
+ // visit the value and report whether any of the maps are updated
+ visit := func(v *Value) (changed bool) {
+ args := v.Args
+ switch v.Op {
+ case OpAddr, OpLocalAddr:
+ // Propagate the address if it points to an auto.
+ n, ok := v.Aux.(GCNode)
+ if !ok || n.StorageClass() != ClassAuto {
+ return
+ }
+ if addr[v] == nil {
+ addr[v] = n
+ changed = true
+ }
+ return
+ case OpVarDef, OpVarKill:
+ // v should be eliminated if we eliminate the auto.
+ n, ok := v.Aux.(GCNode)
+ if !ok || n.StorageClass() != ClassAuto {
+ return
+ }
+ if elim[v] == nil {
+ elim[v] = n
+ changed = true
+ }
+ return
+ case OpVarLive:
+ // Don't delete the auto if it needs to be kept alive.
+
+ // We depend on this check to keep the autotmp stack slots
+ // for open-coded defers from being removed (since they
+ // may not be used by the inline code, but will be used by
+ // panic processing).
+ n, ok := v.Aux.(GCNode)
+ if !ok || n.StorageClass() != ClassAuto {
+ return
+ }
+ if !used[n] {
+ used[n] = true
+ changed = true
+ }
+ return
+ case OpStore, OpMove, OpZero:
+ // v should be eliminated if we eliminate the auto.
+ n, ok := addr[args[0]]
+ if ok && elim[v] == nil {
+ elim[v] = n
+ changed = true
+ }
+ // Other args might hold pointers to autos.
+ args = args[1:]
+ }
+
+ // The code below assumes that we have handled all the ops
+ // with sym effects already. Sanity check that here.
+ // Ignore Args since they can't be autos.
+ if v.Op.SymEffect() != SymNone && v.Op != OpArg {
+ panic("unhandled op with sym effect")
+ }
+
+ if v.Uses == 0 && v.Op != OpNilCheck || len(args) == 0 {
+ // Nil check has no use, but we need to keep it.
+ return
+ }
+
+ // If the address of the auto reaches a memory or control
+ // operation not covered above then we probably need to keep it.
+ // We also need to keep autos if they reach Phis (issue #26153).
+ if v.Type.IsMemory() || v.Type.IsFlags() || v.Op == OpPhi || v.MemoryArg() != nil {
+ for _, a := range args {
+ if n, ok := addr[a]; ok {
+ if !used[n] {
+ used[n] = true
+ changed = true
+ }
+ }
+ }
+ return
+ }
+
+ // Propagate any auto addresses through v.
+ node := GCNode(nil)
+ for _, a := range args {
+ if n, ok := addr[a]; ok && !used[n] {
+ if node == nil {
+ node = n
+ } else if node != n {
+ // Most of the time we only see one pointer
+ // reaching an op, but some ops can take
+ // multiple pointers (e.g. NeqPtr, Phi etc.).
+ // This is rare, so just propagate the first
+ // value to keep things simple.
+ used[n] = true
+ changed = true
+ }
+ }
+ }
+ if node == nil {
+ return
+ }
+ if addr[v] == nil {
+ // The address of an auto reaches this op.
+ addr[v] = node
+ changed = true
+ return
+ }
+ if addr[v] != node {
+ // This doesn't happen in practice, but catch it just in case.
+ used[node] = true
+ changed = true
+ }
+ return
+ }
+
+ iterations := 0
+ for {
+ if iterations == 4 {
+ // give up
+ return
+ }
+ iterations++
+ changed := false
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ changed = visit(v) || changed
+ }
+ // keep the auto if its address reaches a control value
+ for _, c := range b.ControlValues() {
+ if n, ok := addr[c]; ok && !used[n] {
+ used[n] = true
+ changed = true
+ }
+ }
+ }
+ if !changed {
+ break
+ }
+ }
+
+ // Eliminate stores to unread autos.
+ for v, n := range elim {
+ if used[n] {
+ continue
+ }
+ // replace with OpCopy
+ v.SetArgs1(v.MemoryArg())
+ v.Aux = nil
+ v.AuxInt = 0
+ v.Op = OpCopy
+ }
+}
+
+// elimUnreadAutos deletes stores (and associated bookkeeping ops VarDef and VarKill)
+// to autos that are never read from.
+func elimUnreadAutos(f *Func) {
+ // Loop over all ops that affect autos taking note of which
+ // autos we need and also stores that we might be able to
+ // eliminate.
+ seen := make(map[GCNode]bool)
+ var stores []*Value
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ n, ok := v.Aux.(GCNode)
+ if !ok {
+ continue
+ }
+ if n.StorageClass() != ClassAuto {
+ continue
+ }
+
+ effect := v.Op.SymEffect()
+ switch effect {
+ case SymNone, SymWrite:
+ // If we haven't seen the auto yet
+ // then this might be a store we can
+ // eliminate.
+ if !seen[n] {
+ stores = append(stores, v)
+ }
+ default:
+ // Assume the auto is needed (loaded,
+ // has its address taken, etc.).
+ // Note we have to check the uses
+ // because dead loads haven't been
+ // eliminated yet.
+ if v.Uses > 0 {
+ seen[n] = true
+ }
+ }
+ }
+ }
+
+ // Eliminate stores to unread autos.
+ for _, store := range stores {
+ n, _ := store.Aux.(GCNode)
+ if seen[n] {
+ continue
+ }
+
+ // replace store with OpCopy
+ store.SetArgs1(store.MemoryArg())
+ store.Aux = nil
+ store.AuxInt = 0
+ store.Op = OpCopy
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/deadstore_test.go b/src/cmd/compile/internal/ssa/deadstore_test.go
new file mode 100644
index 0000000..33cb4b9
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/deadstore_test.go
@@ -0,0 +1,129 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "testing"
+)
+
+func TestDeadStore(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ t.Logf("PTRTYPE %v", ptrType)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("v", OpConstBool, c.config.Types.Bool, 1, nil),
+ Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
+ Valu("addr2", OpAddr, ptrType, 0, nil, "sb"),
+ Valu("addr3", OpAddr, ptrType, 0, nil, "sb"),
+ Valu("zero1", OpZero, types.TypeMem, 1, c.config.Types.Bool, "addr3", "start"),
+ Valu("store1", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "zero1"),
+ Valu("store2", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr2", "v", "store1"),
+ Valu("store3", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "store2"),
+ Valu("store4", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr3", "v", "store3"),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("store3")))
+
+ CheckFunc(fun.f)
+ dse(fun.f)
+ CheckFunc(fun.f)
+
+ v1 := fun.values["store1"]
+ if v1.Op != OpCopy {
+ t.Errorf("dead store not removed")
+ }
+
+ v2 := fun.values["zero1"]
+ if v2.Op != OpCopy {
+ t.Errorf("dead store (zero) not removed")
+ }
+}
+func TestDeadStorePhi(t *testing.T) {
+ // make sure we don't get into an infinite loop with phi values.
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("v", OpConstBool, c.config.Types.Bool, 1, nil),
+ Valu("addr", OpAddr, ptrType, 0, nil, "sb"),
+ Goto("loop")),
+ Bloc("loop",
+ Valu("phi", OpPhi, types.TypeMem, 0, nil, "start", "store"),
+ Valu("store", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr", "v", "phi"),
+ If("v", "loop", "exit")),
+ Bloc("exit",
+ Exit("store")))
+
+ CheckFunc(fun.f)
+ dse(fun.f)
+ CheckFunc(fun.f)
+}
+
+func TestDeadStoreTypes(t *testing.T) {
+ // Make sure a narrow store can't shadow a wider one. We test an even
+ // stronger restriction, that one store can't shadow another unless the
+ // types of the address fields are identical (where identicalness is
+ // decided by the CSE pass).
+ c := testConfig(t)
+ t1 := c.config.Types.UInt64.PtrTo()
+ t2 := c.config.Types.UInt32.PtrTo()
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("v", OpConstBool, c.config.Types.Bool, 1, nil),
+ Valu("addr1", OpAddr, t1, 0, nil, "sb"),
+ Valu("addr2", OpAddr, t2, 0, nil, "sb"),
+ Valu("store1", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "start"),
+ Valu("store2", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr2", "v", "store1"),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("store2")))
+
+ CheckFunc(fun.f)
+ cse(fun.f)
+ dse(fun.f)
+ CheckFunc(fun.f)
+
+ v := fun.values["store1"]
+ if v.Op == OpCopy {
+ t.Errorf("store %s incorrectly removed", v)
+ }
+}
+
+func TestDeadStoreUnsafe(t *testing.T) {
+ // Make sure a narrow store can't shadow a wider one. The test above
+ // covers the case of two different types, but unsafe pointer casting
+ // can get to a point where the size is changed but type unchanged.
+ c := testConfig(t)
+ ptrType := c.config.Types.UInt64.PtrTo()
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("v", OpConstBool, c.config.Types.Bool, 1, nil),
+ Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
+ Valu("store1", OpStore, types.TypeMem, 0, c.config.Types.Int64, "addr1", "v", "start"), // store 8 bytes
+ Valu("store2", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "store1"), // store 1 byte
+ Goto("exit")),
+ Bloc("exit",
+ Exit("store2")))
+
+ CheckFunc(fun.f)
+ cse(fun.f)
+ dse(fun.f)
+ CheckFunc(fun.f)
+
+ v := fun.values["store1"]
+ if v.Op == OpCopy {
+ t.Errorf("store %s incorrectly removed", v)
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go
new file mode 100644
index 0000000..6353f72
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/debug.go
@@ -0,0 +1,1187 @@
+// Copyright 2017 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 (
+ "cmd/internal/dwarf"
+ "cmd/internal/obj"
+ "encoding/hex"
+ "fmt"
+ "math/bits"
+ "sort"
+ "strings"
+)
+
+type SlotID int32
+type VarID int32
+
+// A FuncDebug contains all the debug information for the variables in a
+// function. Variables are identified by their LocalSlot, which may be the
+// result of decomposing a larger variable.
+type FuncDebug struct {
+ // Slots is all the slots used in the debug info, indexed by their SlotID.
+ Slots []LocalSlot
+ // The user variables, indexed by VarID.
+ Vars []GCNode
+ // The slots that make up each variable, indexed by VarID.
+ VarSlots [][]SlotID
+ // The location list data, indexed by VarID. Must be processed by PutLocationList.
+ LocationLists [][]byte
+
+ // Filled in by the user. Translates Block and Value ID to PC.
+ GetPC func(ID, ID) int64
+}
+
+type BlockDebug struct {
+ // Whether the block had any changes to user variables at all.
+ relevant bool
+ // State at the end of the block if it's fully processed. Immutable once initialized.
+ endState []liveSlot
+}
+
+// A liveSlot is a slot that's live in loc at entry/exit of a block.
+type liveSlot struct {
+ // An inlined VarLoc, so it packs into 16 bytes instead of 20.
+ Registers RegisterSet
+ StackOffset
+
+ slot SlotID
+}
+
+func (loc liveSlot) absent() bool {
+ return loc.Registers == 0 && !loc.onStack()
+}
+
+// StackOffset encodes whether a value is on the stack and if so, where. It is
+// a 31-bit integer followed by a presence flag at the low-order bit.
+type StackOffset int32
+
+func (s StackOffset) onStack() bool {
+ return s != 0
+}
+
+func (s StackOffset) stackOffsetValue() int32 {
+ return int32(s) >> 1
+}
+
+// stateAtPC is the current state of all variables at some point.
+type stateAtPC struct {
+ // The location of each known slot, indexed by SlotID.
+ slots []VarLoc
+ // The slots present in each register, indexed by register number.
+ registers [][]SlotID
+}
+
+// reset fills state with the live variables from live.
+func (state *stateAtPC) reset(live []liveSlot) {
+ slots, registers := state.slots, state.registers
+ for i := range slots {
+ slots[i] = VarLoc{}
+ }
+ for i := range registers {
+ registers[i] = registers[i][:0]
+ }
+ for _, live := range live {
+ slots[live.slot] = VarLoc{live.Registers, live.StackOffset}
+ if live.Registers == 0 {
+ continue
+ }
+
+ mask := uint64(live.Registers)
+ for {
+ if mask == 0 {
+ break
+ }
+ reg := uint8(bits.TrailingZeros64(mask))
+ mask &^= 1 << reg
+
+ registers[reg] = append(registers[reg], live.slot)
+ }
+ }
+ state.slots, state.registers = slots, registers
+}
+
+func (s *debugState) LocString(loc VarLoc) string {
+ if loc.absent() {
+ return "<nil>"
+ }
+
+ var storage []string
+ if loc.onStack() {
+ storage = append(storage, "stack")
+ }
+
+ mask := uint64(loc.Registers)
+ for {
+ if mask == 0 {
+ break
+ }
+ reg := uint8(bits.TrailingZeros64(mask))
+ mask &^= 1 << reg
+
+ storage = append(storage, s.registers[reg].String())
+ }
+ return strings.Join(storage, ",")
+}
+
+// A VarLoc describes the storage for part of a user variable.
+type VarLoc struct {
+ // The registers this variable is available in. There can be more than
+ // one in various situations, e.g. it's being moved between registers.
+ Registers RegisterSet
+
+ StackOffset
+}
+
+func (loc VarLoc) absent() bool {
+ return loc.Registers == 0 && !loc.onStack()
+}
+
+var BlockStart = &Value{
+ ID: -10000,
+ Op: OpInvalid,
+ Aux: "BlockStart",
+}
+
+var BlockEnd = &Value{
+ ID: -20000,
+ Op: OpInvalid,
+ Aux: "BlockEnd",
+}
+
+// RegisterSet is a bitmap of registers, indexed by Register.num.
+type RegisterSet uint64
+
+// logf prints debug-specific logging to stdout (always stdout) if the current
+// function is tagged by GOSSAFUNC (for ssa output directed either to stdout or html).
+func (s *debugState) logf(msg string, args ...interface{}) {
+ if s.f.PrintOrHtmlSSA {
+ fmt.Printf(msg, args...)
+ }
+}
+
+type debugState struct {
+ // See FuncDebug.
+ slots []LocalSlot
+ vars []GCNode
+ varSlots [][]SlotID
+ lists [][]byte
+
+ // The user variable that each slot rolls up to, indexed by SlotID.
+ slotVars []VarID
+
+ f *Func
+ loggingEnabled bool
+ registers []Register
+ stackOffset func(LocalSlot) int32
+ ctxt *obj.Link
+
+ // The names (slots) associated with each value, indexed by Value ID.
+ valueNames [][]SlotID
+
+ // The current state of whatever analysis is running.
+ currentState stateAtPC
+ liveCount []int
+ changedVars *sparseSet
+
+ // The pending location list entry for each user variable, indexed by VarID.
+ pendingEntries []pendingEntry
+
+ varParts map[GCNode][]SlotID
+ blockDebug []BlockDebug
+ pendingSlotLocs []VarLoc
+ liveSlots []liveSlot
+ liveSlotSliceBegin int
+ partsByVarOffset sort.Interface
+}
+
+func (state *debugState) initializeCache(f *Func, numVars, numSlots int) {
+ // One blockDebug per block. Initialized in allocBlock.
+ if cap(state.blockDebug) < f.NumBlocks() {
+ state.blockDebug = make([]BlockDebug, f.NumBlocks())
+ } else {
+ // This local variable, and the ones like it below, enable compiler
+ // optimizations. Don't inline them.
+ b := state.blockDebug[:f.NumBlocks()]
+ for i := range b {
+ b[i] = BlockDebug{}
+ }
+ }
+
+ // A list of slots per Value. Reuse the previous child slices.
+ if cap(state.valueNames) < f.NumValues() {
+ old := state.valueNames
+ state.valueNames = make([][]SlotID, f.NumValues())
+ copy(state.valueNames, old)
+ }
+ vn := state.valueNames[:f.NumValues()]
+ for i := range vn {
+ vn[i] = vn[i][:0]
+ }
+
+ // Slot and register contents for currentState. Cleared by reset().
+ if cap(state.currentState.slots) < numSlots {
+ state.currentState.slots = make([]VarLoc, numSlots)
+ } else {
+ state.currentState.slots = state.currentState.slots[:numSlots]
+ }
+ if cap(state.currentState.registers) < len(state.registers) {
+ state.currentState.registers = make([][]SlotID, len(state.registers))
+ } else {
+ state.currentState.registers = state.currentState.registers[:len(state.registers)]
+ }
+
+ // Used many times by mergePredecessors.
+ if cap(state.liveCount) < numSlots {
+ state.liveCount = make([]int, numSlots)
+ } else {
+ state.liveCount = state.liveCount[:numSlots]
+ }
+
+ // A relatively small slice, but used many times as the return from processValue.
+ state.changedVars = newSparseSet(numVars)
+
+ // A pending entry per user variable, with space to track each of its pieces.
+ numPieces := 0
+ for i := range state.varSlots {
+ numPieces += len(state.varSlots[i])
+ }
+ if cap(state.pendingSlotLocs) < numPieces {
+ state.pendingSlotLocs = make([]VarLoc, numPieces)
+ } else {
+ psl := state.pendingSlotLocs[:numPieces]
+ for i := range psl {
+ psl[i] = VarLoc{}
+ }
+ }
+ if cap(state.pendingEntries) < numVars {
+ state.pendingEntries = make([]pendingEntry, numVars)
+ }
+ pe := state.pendingEntries[:numVars]
+ freePieceIdx := 0
+ for varID, slots := range state.varSlots {
+ pe[varID] = pendingEntry{
+ pieces: state.pendingSlotLocs[freePieceIdx : freePieceIdx+len(slots)],
+ }
+ freePieceIdx += len(slots)
+ }
+ state.pendingEntries = pe
+
+ if cap(state.lists) < numVars {
+ state.lists = make([][]byte, numVars)
+ } else {
+ state.lists = state.lists[:numVars]
+ for i := range state.lists {
+ state.lists[i] = nil
+ }
+ }
+
+ state.liveSlots = state.liveSlots[:0]
+ state.liveSlotSliceBegin = 0
+}
+
+func (state *debugState) allocBlock(b *Block) *BlockDebug {
+ return &state.blockDebug[b.ID]
+}
+
+func (state *debugState) appendLiveSlot(ls liveSlot) {
+ state.liveSlots = append(state.liveSlots, ls)
+}
+
+func (state *debugState) getLiveSlotSlice() []liveSlot {
+ s := state.liveSlots[state.liveSlotSliceBegin:]
+ state.liveSlotSliceBegin = len(state.liveSlots)
+ return s
+}
+
+func (s *debugState) blockEndStateString(b *BlockDebug) string {
+ endState := stateAtPC{slots: make([]VarLoc, len(s.slots)), registers: make([][]SlotID, len(s.registers))}
+ endState.reset(b.endState)
+ return s.stateString(endState)
+}
+
+func (s *debugState) stateString(state stateAtPC) string {
+ var strs []string
+ for slotID, loc := range state.slots {
+ if !loc.absent() {
+ strs = append(strs, fmt.Sprintf("\t%v = %v\n", s.slots[slotID], s.LocString(loc)))
+ }
+ }
+
+ strs = append(strs, "\n")
+ for reg, slots := range state.registers {
+ if len(slots) != 0 {
+ var slotStrs []string
+ for _, slot := range slots {
+ slotStrs = append(slotStrs, s.slots[slot].String())
+ }
+ strs = append(strs, fmt.Sprintf("\t%v = %v\n", &s.registers[reg], slotStrs))
+ }
+ }
+
+ if len(strs) == 1 {
+ return "(no vars)\n"
+ }
+ return strings.Join(strs, "")
+}
+
+// BuildFuncDebug returns debug information for f.
+// f must be fully processed, so that each Value is where it will be when
+// machine code is emitted.
+func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset func(LocalSlot) int32) *FuncDebug {
+ if f.RegAlloc == nil {
+ f.Fatalf("BuildFuncDebug on func %v that has not been fully processed", f)
+ }
+ state := &f.Cache.debugState
+ state.loggingEnabled = loggingEnabled
+ state.f = f
+ state.registers = f.Config.registers
+ state.stackOffset = stackOffset
+ state.ctxt = ctxt
+
+ if state.loggingEnabled {
+ state.logf("Generating location lists for function %q\n", f.Name)
+ }
+
+ if state.varParts == nil {
+ state.varParts = make(map[GCNode][]SlotID)
+ } else {
+ for n := range state.varParts {
+ delete(state.varParts, n)
+ }
+ }
+
+ // Recompose any decomposed variables, and establish the canonical
+ // IDs for each var and slot by filling out state.vars and state.slots.
+
+ state.slots = state.slots[:0]
+ state.vars = state.vars[:0]
+ for i, slot := range f.Names {
+ state.slots = append(state.slots, slot)
+ if slot.N.IsSynthetic() {
+ continue
+ }
+
+ topSlot := &slot
+ for topSlot.SplitOf != nil {
+ topSlot = topSlot.SplitOf
+ }
+ if _, ok := state.varParts[topSlot.N]; !ok {
+ state.vars = append(state.vars, topSlot.N)
+ }
+ state.varParts[topSlot.N] = append(state.varParts[topSlot.N], SlotID(i))
+ }
+
+ // Recreate the LocalSlot for each stack-only variable.
+ // This would probably be better as an output from stackframe.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op == OpVarDef || v.Op == OpVarKill {
+ n := v.Aux.(GCNode)
+ if n.IsSynthetic() {
+ continue
+ }
+
+ if _, ok := state.varParts[n]; !ok {
+ slot := LocalSlot{N: n, Type: v.Type, Off: 0}
+ state.slots = append(state.slots, slot)
+ state.varParts[n] = []SlotID{SlotID(len(state.slots) - 1)}
+ state.vars = append(state.vars, n)
+ }
+ }
+ }
+ }
+
+ // Fill in the var<->slot mappings.
+ if cap(state.varSlots) < len(state.vars) {
+ state.varSlots = make([][]SlotID, len(state.vars))
+ } else {
+ state.varSlots = state.varSlots[:len(state.vars)]
+ for i := range state.varSlots {
+ state.varSlots[i] = state.varSlots[i][:0]
+ }
+ }
+ if cap(state.slotVars) < len(state.slots) {
+ state.slotVars = make([]VarID, len(state.slots))
+ } else {
+ state.slotVars = state.slotVars[:len(state.slots)]
+ }
+
+ if state.partsByVarOffset == nil {
+ state.partsByVarOffset = &partsByVarOffset{}
+ }
+ for varID, n := range state.vars {
+ parts := state.varParts[n]
+ state.varSlots[varID] = parts
+ for _, slotID := range parts {
+ state.slotVars[slotID] = VarID(varID)
+ }
+ *state.partsByVarOffset.(*partsByVarOffset) = partsByVarOffset{parts, state.slots}
+ sort.Sort(state.partsByVarOffset)
+ }
+
+ state.initializeCache(f, len(state.varParts), len(state.slots))
+
+ for i, slot := range f.Names {
+ if slot.N.IsSynthetic() {
+ continue
+ }
+ for _, value := range f.NamedValues[slot] {
+ state.valueNames[value.ID] = append(state.valueNames[value.ID], SlotID(i))
+ }
+ }
+
+ blockLocs := state.liveness()
+ state.buildLocationLists(blockLocs)
+
+ return &FuncDebug{
+ Slots: state.slots,
+ VarSlots: state.varSlots,
+ Vars: state.vars,
+ LocationLists: state.lists,
+ }
+}
+
+// liveness walks the function in control flow order, calculating the start
+// and end state of each block.
+func (state *debugState) liveness() []*BlockDebug {
+ blockLocs := make([]*BlockDebug, state.f.NumBlocks())
+
+ // Reverse postorder: visit a block after as many as possible of its
+ // predecessors have been visited.
+ po := state.f.Postorder()
+ for i := len(po) - 1; i >= 0; i-- {
+ b := po[i]
+
+ // Build the starting state for the block from the final
+ // state of its predecessors.
+ startState, startValid := state.mergePredecessors(b, blockLocs, nil)
+ changed := false
+ if state.loggingEnabled {
+ state.logf("Processing %v, initial state:\n%v", b, state.stateString(state.currentState))
+ }
+
+ // Update locs/registers with the effects of each Value.
+ for _, v := range b.Values {
+ slots := state.valueNames[v.ID]
+
+ // Loads and stores inherit the names of their sources.
+ var source *Value
+ switch v.Op {
+ case OpStoreReg:
+ source = v.Args[0]
+ case OpLoadReg:
+ switch a := v.Args[0]; a.Op {
+ case OpArg, OpPhi:
+ source = a
+ case OpStoreReg:
+ source = a.Args[0]
+ default:
+ if state.loggingEnabled {
+ state.logf("at %v: load with unexpected source op: %v (%v)\n", v, a.Op, a)
+ }
+ }
+ }
+ // Update valueNames with the source so that later steps
+ // don't need special handling.
+ if source != nil {
+ slots = append(slots, state.valueNames[source.ID]...)
+ state.valueNames[v.ID] = slots
+ }
+
+ reg, _ := state.f.getHome(v.ID).(*Register)
+ c := state.processValue(v, slots, reg)
+ changed = changed || c
+ }
+
+ if state.loggingEnabled {
+ state.f.Logf("Block %v done, locs:\n%v", b, state.stateString(state.currentState))
+ }
+
+ locs := state.allocBlock(b)
+ locs.relevant = changed
+ if !changed && startValid {
+ locs.endState = startState
+ } else {
+ for slotID, slotLoc := range state.currentState.slots {
+ if slotLoc.absent() {
+ continue
+ }
+ state.appendLiveSlot(liveSlot{slot: SlotID(slotID), Registers: slotLoc.Registers, StackOffset: slotLoc.StackOffset})
+ }
+ locs.endState = state.getLiveSlotSlice()
+ }
+ blockLocs[b.ID] = locs
+ }
+ return blockLocs
+}
+
+// mergePredecessors takes the end state of each of b's predecessors and
+// intersects them to form the starting state for b. It puts that state in
+// blockLocs, and fills state.currentState with it. If convenient, it returns
+// a reused []liveSlot, true that represents the starting state.
+// If previousBlock is non-nil, it registers changes vs. that block's end
+// state in state.changedVars. Note that previousBlock will often not be a
+// predecessor.
+func (state *debugState) mergePredecessors(b *Block, blockLocs []*BlockDebug, previousBlock *Block) ([]liveSlot, bool) {
+ // Filter out back branches.
+ var predsBuf [10]*Block
+ preds := predsBuf[:0]
+ for _, pred := range b.Preds {
+ if blockLocs[pred.b.ID] != nil {
+ preds = append(preds, pred.b)
+ }
+ }
+
+ if state.loggingEnabled {
+ // The logf below would cause preds to be heap-allocated if
+ // it were passed directly.
+ preds2 := make([]*Block, len(preds))
+ copy(preds2, preds)
+ state.logf("Merging %v into %v\n", preds2, b)
+ }
+
+ // TODO all the calls to this are overkill; only need to do this for slots that are not present in the merge.
+ markChangedVars := func(slots []liveSlot) {
+ for _, live := range slots {
+ state.changedVars.add(ID(state.slotVars[live.slot]))
+ }
+ }
+
+ if len(preds) == 0 {
+ if previousBlock != nil {
+ // Mark everything in previous block as changed because it is not a predecessor.
+ markChangedVars(blockLocs[previousBlock.ID].endState)
+ }
+ state.currentState.reset(nil)
+ return nil, true
+ }
+
+ p0 := blockLocs[preds[0].ID].endState
+ if len(preds) == 1 {
+ if previousBlock != nil && preds[0].ID != previousBlock.ID {
+ // Mark everything in previous block as changed because it is not a predecessor.
+ markChangedVars(blockLocs[previousBlock.ID].endState)
+ }
+ state.currentState.reset(p0)
+ return p0, true
+ }
+
+ baseID := preds[0].ID
+ baseState := p0
+
+ // If previous block is not a predecessor, its location information changes at boundary with this block.
+ previousBlockIsNotPredecessor := previousBlock != nil // If it's nil, no info to change.
+
+ if previousBlock != nil {
+ // Try to use previousBlock as the base state
+ // if possible.
+ for _, pred := range preds[1:] {
+ if pred.ID == previousBlock.ID {
+ baseID = pred.ID
+ baseState = blockLocs[pred.ID].endState
+ previousBlockIsNotPredecessor = false
+ break
+ }
+ }
+ }
+
+ if state.loggingEnabled {
+ state.logf("Starting %v with state from b%v:\n%v", b, baseID, state.blockEndStateString(blockLocs[baseID]))
+ }
+
+ slotLocs := state.currentState.slots
+ for _, predSlot := range baseState {
+ slotLocs[predSlot.slot] = VarLoc{predSlot.Registers, predSlot.StackOffset}
+ state.liveCount[predSlot.slot] = 1
+ }
+ for _, pred := range preds {
+ if pred.ID == baseID {
+ continue
+ }
+ if state.loggingEnabled {
+ state.logf("Merging in state from %v:\n%v", pred, state.blockEndStateString(blockLocs[pred.ID]))
+ }
+ for _, predSlot := range blockLocs[pred.ID].endState {
+ state.liveCount[predSlot.slot]++
+ liveLoc := slotLocs[predSlot.slot]
+ if !liveLoc.onStack() || !predSlot.onStack() || liveLoc.StackOffset != predSlot.StackOffset {
+ liveLoc.StackOffset = 0
+ }
+ liveLoc.Registers &= predSlot.Registers
+ slotLocs[predSlot.slot] = liveLoc
+ }
+ }
+
+ // Check if the final state is the same as the first predecessor's
+ // final state, and reuse it if so. In principle it could match any,
+ // but it's probably not worth checking more than the first.
+ unchanged := true
+ for _, predSlot := range baseState {
+ if state.liveCount[predSlot.slot] != len(preds) ||
+ slotLocs[predSlot.slot].Registers != predSlot.Registers ||
+ slotLocs[predSlot.slot].StackOffset != predSlot.StackOffset {
+ unchanged = false
+ break
+ }
+ }
+ if unchanged {
+ if state.loggingEnabled {
+ state.logf("After merge, %v matches b%v exactly.\n", b, baseID)
+ }
+ if previousBlockIsNotPredecessor {
+ // Mark everything in previous block as changed because it is not a predecessor.
+ markChangedVars(blockLocs[previousBlock.ID].endState)
+ }
+ state.currentState.reset(baseState)
+ return baseState, true
+ }
+
+ for reg := range state.currentState.registers {
+ state.currentState.registers[reg] = state.currentState.registers[reg][:0]
+ }
+
+ // A slot is live if it was seen in all predecessors, and they all had
+ // some storage in common.
+ for _, predSlot := range baseState {
+ slotLoc := slotLocs[predSlot.slot]
+
+ if state.liveCount[predSlot.slot] != len(preds) {
+ // Seen in only some predecessors. Clear it out.
+ slotLocs[predSlot.slot] = VarLoc{}
+ continue
+ }
+
+ // Present in all predecessors.
+ mask := uint64(slotLoc.Registers)
+ for {
+ if mask == 0 {
+ break
+ }
+ reg := uint8(bits.TrailingZeros64(mask))
+ mask &^= 1 << reg
+ state.currentState.registers[reg] = append(state.currentState.registers[reg], predSlot.slot)
+ }
+ }
+
+ if previousBlockIsNotPredecessor {
+ // Mark everything in previous block as changed because it is not a predecessor.
+ markChangedVars(blockLocs[previousBlock.ID].endState)
+
+ }
+ return nil, false
+}
+
+// processValue updates locs and state.registerContents to reflect v, a value with
+// the names in vSlots and homed in vReg. "v" becomes visible after execution of
+// the instructions evaluating it. It returns which VarIDs were modified by the
+// Value's execution.
+func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register) bool {
+ locs := state.currentState
+ changed := false
+ setSlot := func(slot SlotID, loc VarLoc) {
+ changed = true
+ state.changedVars.add(ID(state.slotVars[slot]))
+ state.currentState.slots[slot] = loc
+ }
+
+ // Handle any register clobbering. Call operations, for example,
+ // clobber all registers even though they don't explicitly write to
+ // them.
+ clobbers := uint64(opcodeTable[v.Op].reg.clobbers)
+ for {
+ if clobbers == 0 {
+ break
+ }
+ reg := uint8(bits.TrailingZeros64(clobbers))
+ clobbers &^= 1 << reg
+
+ for _, slot := range locs.registers[reg] {
+ if state.loggingEnabled {
+ state.logf("at %v: %v clobbered out of %v\n", v, state.slots[slot], &state.registers[reg])
+ }
+
+ last := locs.slots[slot]
+ if last.absent() {
+ state.f.Fatalf("at %v: slot %v in register %v with no location entry", v, state.slots[slot], &state.registers[reg])
+ continue
+ }
+ regs := last.Registers &^ (1 << reg)
+ setSlot(slot, VarLoc{regs, last.StackOffset})
+ }
+
+ locs.registers[reg] = locs.registers[reg][:0]
+ }
+
+ switch {
+ case v.Op == OpVarDef, v.Op == OpVarKill:
+ n := v.Aux.(GCNode)
+ if n.IsSynthetic() {
+ break
+ }
+
+ slotID := state.varParts[n][0]
+ var stackOffset StackOffset
+ if v.Op == OpVarDef {
+ stackOffset = StackOffset(state.stackOffset(state.slots[slotID])<<1 | 1)
+ }
+ setSlot(slotID, VarLoc{0, stackOffset})
+ if state.loggingEnabled {
+ if v.Op == OpVarDef {
+ state.logf("at %v: stack-only var %v now live\n", v, state.slots[slotID])
+ } else {
+ state.logf("at %v: stack-only var %v now dead\n", v, state.slots[slotID])
+ }
+ }
+
+ case v.Op == OpArg:
+ home := state.f.getHome(v.ID).(LocalSlot)
+ stackOffset := state.stackOffset(home)<<1 | 1
+ for _, slot := range vSlots {
+ if state.loggingEnabled {
+ state.logf("at %v: arg %v now on stack in location %v\n", v, state.slots[slot], home)
+ if last := locs.slots[slot]; !last.absent() {
+ state.logf("at %v: unexpected arg op on already-live slot %v\n", v, state.slots[slot])
+ }
+ }
+
+ setSlot(slot, VarLoc{0, StackOffset(stackOffset)})
+ }
+
+ case v.Op == OpStoreReg:
+ home := state.f.getHome(v.ID).(LocalSlot)
+ stackOffset := state.stackOffset(home)<<1 | 1
+ for _, slot := range vSlots {
+ last := locs.slots[slot]
+ if last.absent() {
+ if state.loggingEnabled {
+ state.logf("at %v: unexpected spill of unnamed register %s\n", v, vReg)
+ }
+ break
+ }
+
+ setSlot(slot, VarLoc{last.Registers, StackOffset(stackOffset)})
+ if state.loggingEnabled {
+ state.logf("at %v: %v spilled to stack location %v\n", v, state.slots[slot], home)
+ }
+ }
+
+ case vReg != nil:
+ if state.loggingEnabled {
+ newSlots := make([]bool, len(state.slots))
+ for _, slot := range vSlots {
+ newSlots[slot] = true
+ }
+
+ for _, slot := range locs.registers[vReg.num] {
+ if !newSlots[slot] {
+ state.logf("at %v: overwrote %v in register %v\n", v, state.slots[slot], vReg)
+ }
+ }
+ }
+
+ for _, slot := range locs.registers[vReg.num] {
+ last := locs.slots[slot]
+ setSlot(slot, VarLoc{last.Registers &^ (1 << uint8(vReg.num)), last.StackOffset})
+ }
+ locs.registers[vReg.num] = locs.registers[vReg.num][:0]
+ locs.registers[vReg.num] = append(locs.registers[vReg.num], vSlots...)
+ for _, slot := range vSlots {
+ if state.loggingEnabled {
+ state.logf("at %v: %v now in %s\n", v, state.slots[slot], vReg)
+ }
+
+ last := locs.slots[slot]
+ setSlot(slot, VarLoc{1<<uint8(vReg.num) | last.Registers, last.StackOffset})
+ }
+ }
+ return changed
+}
+
+// varOffset returns the offset of slot within the user variable it was
+// decomposed from. This has nothing to do with its stack offset.
+func varOffset(slot LocalSlot) int64 {
+ offset := slot.Off
+ s := &slot
+ for ; s.SplitOf != nil; s = s.SplitOf {
+ offset += s.SplitOffset
+ }
+ return offset
+}
+
+type partsByVarOffset struct {
+ slotIDs []SlotID
+ slots []LocalSlot
+}
+
+func (a partsByVarOffset) Len() int { return len(a.slotIDs) }
+func (a partsByVarOffset) Less(i, j int) bool {
+ return varOffset(a.slots[a.slotIDs[i]]) < varOffset(a.slots[a.slotIDs[j]])
+}
+func (a partsByVarOffset) Swap(i, j int) { a.slotIDs[i], a.slotIDs[j] = a.slotIDs[j], a.slotIDs[i] }
+
+// A pendingEntry represents the beginning of a location list entry, missing
+// only its end coordinate.
+type pendingEntry struct {
+ present bool
+ startBlock, startValue ID
+ // The location of each piece of the variable, in the same order as the
+ // SlotIDs in varParts.
+ pieces []VarLoc
+}
+
+func (e *pendingEntry) clear() {
+ e.present = false
+ e.startBlock = 0
+ e.startValue = 0
+ for i := range e.pieces {
+ e.pieces[i] = VarLoc{}
+ }
+}
+
+// canMerge reports whether the location description for new is the same as
+// pending.
+func canMerge(pending, new VarLoc) bool {
+ if pending.absent() && new.absent() {
+ return true
+ }
+ if pending.absent() || new.absent() {
+ return false
+ }
+ if pending.onStack() {
+ return pending.StackOffset == new.StackOffset
+ }
+ if pending.Registers != 0 && new.Registers != 0 {
+ return firstReg(pending.Registers) == firstReg(new.Registers)
+ }
+ return false
+}
+
+// firstReg returns the first register in set that is present.
+func firstReg(set RegisterSet) uint8 {
+ if set == 0 {
+ // This is wrong, but there seem to be some situations where we
+ // produce locations with no storage.
+ return 0
+ }
+ return uint8(bits.TrailingZeros64(uint64(set)))
+}
+
+// buildLocationLists builds location lists for all the user variables in
+// state.f, using the information about block state in blockLocs.
+// The returned location lists are not fully complete. They are in terms of
+// SSA values rather than PCs, and have no base address/end entries. They will
+// be finished by PutLocationList.
+func (state *debugState) buildLocationLists(blockLocs []*BlockDebug) {
+ // Run through the function in program text order, building up location
+ // lists as we go. The heavy lifting has mostly already been done.
+
+ var prevBlock *Block
+ for _, b := range state.f.Blocks {
+ state.mergePredecessors(b, blockLocs, prevBlock)
+
+ if !blockLocs[b.ID].relevant {
+ // Handle any differences among predecessor blocks and previous block (perhaps not a predecessor)
+ for _, varID := range state.changedVars.contents() {
+ state.updateVar(VarID(varID), b, BlockStart)
+ }
+ continue
+ }
+
+ zeroWidthPending := false
+ apcChangedSize := 0 // size of changedVars for leading Args, Phi, ClosurePtr
+ // expect to see values in pattern (apc)* (zerowidth|real)*
+ for _, v := range b.Values {
+ slots := state.valueNames[v.ID]
+ reg, _ := state.f.getHome(v.ID).(*Register)
+ changed := state.processValue(v, slots, reg) // changed == added to state.changedVars
+
+ if opcodeTable[v.Op].zeroWidth {
+ if changed {
+ if v.Op == OpArg || v.Op == OpPhi || v.Op.isLoweredGetClosurePtr() {
+ // These ranges begin at true beginning of block, not after first instruction
+ if zeroWidthPending {
+ b.Func.Fatalf("Unexpected op mixed with OpArg/OpPhi/OpLoweredGetClosurePtr at beginning of block %s in %s\n%s", b, b.Func.Name, b.Func)
+ }
+ apcChangedSize = len(state.changedVars.contents())
+ continue
+ }
+ // Other zero-width ops must wait on a "real" op.
+ zeroWidthPending = true
+ }
+ continue
+ }
+
+ if !changed && !zeroWidthPending {
+ continue
+ }
+ // Not zero-width; i.e., a "real" instruction.
+
+ zeroWidthPending = false
+ for i, varID := range state.changedVars.contents() {
+ if i < apcChangedSize { // buffered true start-of-block changes
+ state.updateVar(VarID(varID), v.Block, BlockStart)
+ } else {
+ state.updateVar(VarID(varID), v.Block, v)
+ }
+ }
+ state.changedVars.clear()
+ apcChangedSize = 0
+ }
+ for i, varID := range state.changedVars.contents() {
+ if i < apcChangedSize { // buffered true start-of-block changes
+ state.updateVar(VarID(varID), b, BlockStart)
+ } else {
+ state.updateVar(VarID(varID), b, BlockEnd)
+ }
+ }
+
+ prevBlock = b
+ }
+
+ if state.loggingEnabled {
+ state.logf("location lists:\n")
+ }
+
+ // Flush any leftover entries live at the end of the last block.
+ for varID := range state.lists {
+ state.writePendingEntry(VarID(varID), state.f.Blocks[len(state.f.Blocks)-1].ID, BlockEnd.ID)
+ list := state.lists[varID]
+ if state.loggingEnabled {
+ if len(list) == 0 {
+ state.logf("\t%v : empty list\n", state.vars[varID])
+ } else {
+ state.logf("\t%v : %q\n", state.vars[varID], hex.EncodeToString(state.lists[varID]))
+ }
+ }
+ }
+}
+
+// updateVar updates the pending location list entry for varID to
+// reflect the new locations in curLoc, beginning at v in block b.
+// v may be one of the special values indicating block start or end.
+func (state *debugState) updateVar(varID VarID, b *Block, v *Value) {
+ curLoc := state.currentState.slots
+ // Assemble the location list entry with whatever's live.
+ empty := true
+ for _, slotID := range state.varSlots[varID] {
+ if !curLoc[slotID].absent() {
+ empty = false
+ break
+ }
+ }
+ pending := &state.pendingEntries[varID]
+ if empty {
+ state.writePendingEntry(varID, b.ID, v.ID)
+ pending.clear()
+ return
+ }
+
+ // Extend the previous entry if possible.
+ if pending.present {
+ merge := true
+ for i, slotID := range state.varSlots[varID] {
+ if !canMerge(pending.pieces[i], curLoc[slotID]) {
+ merge = false
+ break
+ }
+ }
+ if merge {
+ return
+ }
+ }
+
+ state.writePendingEntry(varID, b.ID, v.ID)
+ pending.present = true
+ pending.startBlock = b.ID
+ pending.startValue = v.ID
+ for i, slot := range state.varSlots[varID] {
+ pending.pieces[i] = curLoc[slot]
+ }
+}
+
+// writePendingEntry writes out the pending entry for varID, if any,
+// terminated at endBlock/Value.
+func (state *debugState) writePendingEntry(varID VarID, endBlock, endValue ID) {
+ pending := state.pendingEntries[varID]
+ if !pending.present {
+ return
+ }
+
+ // Pack the start/end coordinates into the start/end addresses
+ // of the entry, for decoding by PutLocationList.
+ start, startOK := encodeValue(state.ctxt, pending.startBlock, pending.startValue)
+ end, endOK := encodeValue(state.ctxt, endBlock, endValue)
+ if !startOK || !endOK {
+ // If someone writes a function that uses >65K values,
+ // they get incomplete debug info on 32-bit platforms.
+ return
+ }
+ if start == end {
+ if state.loggingEnabled {
+ // Printf not logf so not gated by GOSSAFUNC; this should fire very rarely.
+ fmt.Printf("Skipping empty location list for %v in %s\n", state.vars[varID], state.f.Name)
+ }
+ return
+ }
+
+ list := state.lists[varID]
+ list = appendPtr(state.ctxt, list, start)
+ list = appendPtr(state.ctxt, list, end)
+ // Where to write the length of the location description once
+ // we know how big it is.
+ sizeIdx := len(list)
+ list = list[:len(list)+2]
+
+ if state.loggingEnabled {
+ var partStrs []string
+ for i, slot := range state.varSlots[varID] {
+ partStrs = append(partStrs, fmt.Sprintf("%v@%v", state.slots[slot], state.LocString(pending.pieces[i])))
+ }
+ state.logf("Add entry for %v: \tb%vv%v-b%vv%v = \t%v\n", state.vars[varID], pending.startBlock, pending.startValue, endBlock, endValue, strings.Join(partStrs, " "))
+ }
+
+ for i, slotID := range state.varSlots[varID] {
+ loc := pending.pieces[i]
+ slot := state.slots[slotID]
+
+ if !loc.absent() {
+ if loc.onStack() {
+ if loc.stackOffsetValue() == 0 {
+ list = append(list, dwarf.DW_OP_call_frame_cfa)
+ } else {
+ list = append(list, dwarf.DW_OP_fbreg)
+ list = dwarf.AppendSleb128(list, int64(loc.stackOffsetValue()))
+ }
+ } else {
+ regnum := state.ctxt.Arch.DWARFRegisters[state.registers[firstReg(loc.Registers)].ObjNum()]
+ if regnum < 32 {
+ list = append(list, dwarf.DW_OP_reg0+byte(regnum))
+ } else {
+ list = append(list, dwarf.DW_OP_regx)
+ list = dwarf.AppendUleb128(list, uint64(regnum))
+ }
+ }
+ }
+
+ if len(state.varSlots[varID]) > 1 {
+ list = append(list, dwarf.DW_OP_piece)
+ list = dwarf.AppendUleb128(list, uint64(slot.Type.Size()))
+ }
+ }
+ state.ctxt.Arch.ByteOrder.PutUint16(list[sizeIdx:], uint16(len(list)-sizeIdx-2))
+ state.lists[varID] = list
+}
+
+// PutLocationList adds list (a location list in its intermediate representation) to listSym.
+func (debugInfo *FuncDebug) PutLocationList(list []byte, ctxt *obj.Link, listSym, startPC *obj.LSym) {
+ getPC := debugInfo.GetPC
+
+ if ctxt.UseBASEntries {
+ listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, ^0)
+ listSym.WriteAddr(ctxt, listSym.Size, ctxt.Arch.PtrSize, startPC, 0)
+ }
+
+ // Re-read list, translating its address from block/value ID to PC.
+ for i := 0; i < len(list); {
+ begin := getPC(decodeValue(ctxt, readPtr(ctxt, list[i:])))
+ end := getPC(decodeValue(ctxt, readPtr(ctxt, list[i+ctxt.Arch.PtrSize:])))
+
+ // Horrible hack. If a range contains only zero-width
+ // instructions, e.g. an Arg, and it's at the beginning of the
+ // function, this would be indistinguishable from an
+ // end entry. Fudge it.
+ if begin == 0 && end == 0 {
+ end = 1
+ }
+
+ if ctxt.UseBASEntries {
+ listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, int64(begin))
+ listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, int64(end))
+ } else {
+ listSym.WriteCURelativeAddr(ctxt, listSym.Size, startPC, int64(begin))
+ listSym.WriteCURelativeAddr(ctxt, listSym.Size, startPC, int64(end))
+ }
+
+ i += 2 * ctxt.Arch.PtrSize
+ datalen := 2 + int(ctxt.Arch.ByteOrder.Uint16(list[i:]))
+ listSym.WriteBytes(ctxt, listSym.Size, list[i:i+datalen]) // copy datalen and location encoding
+ i += datalen
+ }
+
+ // Location list contents, now with real PCs.
+ // End entry.
+ listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, 0)
+ listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, 0)
+}
+
+// Pack a value and block ID into an address-sized uint, returning ~0 if they
+// don't fit.
+func encodeValue(ctxt *obj.Link, b, v ID) (uint64, bool) {
+ if ctxt.Arch.PtrSize == 8 {
+ result := uint64(b)<<32 | uint64(uint32(v))
+ //ctxt.Logf("b %#x (%d) v %#x (%d) -> %#x\n", b, b, v, v, result)
+ return result, true
+ }
+ if ctxt.Arch.PtrSize != 4 {
+ panic("unexpected pointer size")
+ }
+ if ID(int16(b)) != b || ID(int16(v)) != v {
+ return 0, false
+ }
+ return uint64(b)<<16 | uint64(uint16(v)), true
+}
+
+// Unpack a value and block ID encoded by encodeValue.
+func decodeValue(ctxt *obj.Link, word uint64) (ID, ID) {
+ if ctxt.Arch.PtrSize == 8 {
+ b, v := ID(word>>32), ID(word)
+ //ctxt.Logf("%#x -> b %#x (%d) v %#x (%d)\n", word, b, b, v, v)
+ return b, v
+ }
+ if ctxt.Arch.PtrSize != 4 {
+ panic("unexpected pointer size")
+ }
+ return ID(word >> 16), ID(int16(word))
+}
+
+// Append a pointer-sized uint to buf.
+func appendPtr(ctxt *obj.Link, buf []byte, word uint64) []byte {
+ if cap(buf) < len(buf)+20 {
+ b := make([]byte, len(buf), 20+cap(buf)*2)
+ copy(b, buf)
+ buf = b
+ }
+ writeAt := len(buf)
+ buf = buf[0 : len(buf)+ctxt.Arch.PtrSize]
+ writePtr(ctxt, buf[writeAt:], word)
+ return buf
+}
+
+// Write a pointer-sized uint to the beginning of buf.
+func writePtr(ctxt *obj.Link, buf []byte, word uint64) {
+ switch ctxt.Arch.PtrSize {
+ case 4:
+ ctxt.Arch.ByteOrder.PutUint32(buf, uint32(word))
+ case 8:
+ ctxt.Arch.ByteOrder.PutUint64(buf, word)
+ default:
+ panic("unexpected pointer size")
+ }
+
+}
+
+// Read a pointer-sized uint from the beginning of buf.
+func readPtr(ctxt *obj.Link, buf []byte) uint64 {
+ switch ctxt.Arch.PtrSize {
+ case 4:
+ return uint64(ctxt.Arch.ByteOrder.Uint32(buf))
+ case 8:
+ return ctxt.Arch.ByteOrder.Uint64(buf)
+ default:
+ panic("unexpected pointer size")
+ }
+
+}
diff --git a/src/cmd/compile/internal/ssa/debug_test.go b/src/cmd/compile/internal/ssa/debug_test.go
new file mode 100644
index 0000000..3346312
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/debug_test.go
@@ -0,0 +1,1020 @@
+// Copyright 2017 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_test
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "internal/testenv"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "runtime"
+ "strconv"
+ "strings"
+ "testing"
+ "time"
+)
+
+var (
+ update = flag.Bool("u", false, "update test reference files")
+ verbose = flag.Bool("v", false, "print debugger interactions (very verbose)")
+ dryrun = flag.Bool("n", false, "just print the command line and first debugging bits")
+ useGdb = flag.Bool("g", false, "use Gdb instead of Delve (dlv), use gdb reference files")
+ force = flag.Bool("f", false, "force run under not linux-amd64; also do not use tempdir")
+ repeats = flag.Bool("r", false, "detect repeats in debug steps and don't ignore them")
+ inlines = flag.Bool("i", false, "do inlining for gdb (makes testing flaky till inlining info is correct)")
+)
+
+var (
+ hexRe = regexp.MustCompile("0x[a-zA-Z0-9]+")
+ numRe = regexp.MustCompile("-?[0-9]+")
+ stringRe = regexp.MustCompile("\"([^\\\"]|(\\.))*\"")
+ leadingDollarNumberRe = regexp.MustCompile("^[$][0-9]+")
+ optOutGdbRe = regexp.MustCompile("[<]optimized out[>]")
+ numberColonRe = regexp.MustCompile("^ *[0-9]+:")
+)
+
+var gdb = "gdb" // Might be "ggdb" on Darwin, because gdb no longer part of XCode
+var debugger = "dlv" // For naming files, etc.
+
+var gogcflags = os.Getenv("GO_GCFLAGS")
+
+// optimizedLibs usually means "not running in a noopt test builder".
+var optimizedLibs = (!strings.Contains(gogcflags, "-N") && !strings.Contains(gogcflags, "-l"))
+
+// TestNexting go-builds a file, then uses a debugger (default delve, optionally gdb)
+// to next through the generated executable, recording each line landed at, and
+// then compares those lines with reference file(s).
+// Flag -u updates the reference file(s).
+// Flag -g changes the debugger to gdb (and uses gdb-specific reference files)
+// Flag -v is ever-so-slightly verbose.
+// Flag -n is for dry-run, and prints the shell and first debug commands.
+//
+// Because this test (combined with existing compiler deficiencies) is flaky,
+// for gdb-based testing by default inlining is disabled
+// (otherwise output depends on library internals)
+// and for both gdb and dlv by default repeated lines in the next stream are ignored
+// (because this appears to be timing-dependent in gdb, and the cleanest fix is in code common to gdb and dlv).
+//
+// Also by default, any source code outside of .../testdata/ is not mentioned
+// in the debugging histories. This deals both with inlined library code once
+// the compiler is generating clean inline records, and also deals with
+// runtime code between return from main and process exit. This is hidden
+// so that those files (in the runtime/library) can change without affecting
+// this test.
+//
+// These choices can be reversed with -i (inlining on) and -r (repeats detected) which
+// will also cause their own failures against the expected outputs. Note that if the compiler
+// and debugger were behaving properly, the inlined code and repeated lines would not appear,
+// so the expected output is closer to what we hope to see, though it also encodes all our
+// current bugs.
+//
+// The file being tested may contain comments of the form
+// //DBG-TAG=(v1,v2,v3)
+// where DBG = {gdb,dlv} and TAG={dbg,opt}
+// each variable may optionally be followed by a / and one or more of S,A,N,O
+// to indicate normalization of Strings, (hex) addresses, and numbers.
+// "O" is an explicit indication that we expect it to be optimized out.
+// For example:
+//
+// if len(os.Args) > 1 { //gdb-dbg=(hist/A,cannedInput/A) //dlv-dbg=(hist/A,cannedInput/A)
+//
+// TODO: not implemented for Delve yet, but this is the plan
+//
+// After a compiler change that causes a difference in the debug behavior, check
+// to see if it is sensible or not, and if it is, update the reference files with
+// go test debug_test.go -args -u
+// (for Delve)
+// go test debug_test.go -args -u -d
+//
+func TestNexting(t *testing.T) {
+ testenv.SkipFlaky(t, 37404)
+
+ skipReasons := "" // Many possible skip reasons, list all that apply
+ if testing.Short() {
+ skipReasons = "not run in short mode; "
+ }
+ testenv.MustHaveGoBuild(t)
+
+ if *useGdb && !*force && !(runtime.GOOS == "linux" && runtime.GOARCH == "amd64") {
+ // Running gdb on OSX/darwin is very flaky.
+ // Sometimes it is called ggdb, depending on how it is installed.
+ // It also sometimes requires an admin password typed into a dialog box.
+ // Various architectures tend to differ slightly sometimes, and keeping them
+ // all in sync is a pain for people who don't have them all at hand,
+ // so limit testing to amd64 (for now)
+ skipReasons += "not run when testing gdb (-g) unless forced (-f) or linux-amd64; "
+ }
+
+ if !*useGdb && !*force && testenv.Builder() == "linux-386-longtest" {
+ // The latest version of Delve does support linux/386. However, the version currently
+ // installed in the linux-386-longtest builder does not. See golang.org/issue/39309.
+ skipReasons += "not run when testing delve on linux-386-longtest builder unless forced (-f); "
+ }
+
+ if *useGdb {
+ debugger = "gdb"
+ _, err := exec.LookPath(gdb)
+ if err != nil {
+ if runtime.GOOS != "darwin" {
+ skipReasons += "not run because gdb not on path; "
+ } else {
+ // On Darwin, MacPorts installs gdb as "ggdb".
+ _, err = exec.LookPath("ggdb")
+ if err != nil {
+ skipReasons += "not run because gdb (and also ggdb) request by -g option not on path; "
+ } else {
+ gdb = "ggdb"
+ }
+ }
+ }
+ } else { // Delve
+ debugger = "dlv"
+ _, err := exec.LookPath("dlv")
+ if err != nil {
+ skipReasons += "not run because dlv not on path; "
+ }
+ }
+
+ if skipReasons != "" {
+ t.Skip(skipReasons[:len(skipReasons)-2])
+ }
+
+ optFlags := "" // Whatever flags are needed to test debugging of optimized code.
+ dbgFlags := "-N -l"
+ if *useGdb && !*inlines {
+ // For gdb (default), disable inlining so that a compiler test does not depend on library code.
+ // TODO: Technically not necessary in 1.10 and later, but it causes a largish regression that needs investigation.
+ optFlags += " -l"
+ }
+
+ moreargs := []string{}
+ if *useGdb && (runtime.GOOS == "darwin" || runtime.GOOS == "windows") {
+ // gdb and lldb on Darwin do not deal with compressed dwarf.
+ // also, Windows.
+ moreargs = append(moreargs, "-ldflags=-compressdwarf=false")
+ }
+
+ subTest(t, debugger+"-dbg", "hist", dbgFlags, moreargs...)
+ subTest(t, debugger+"-dbg", "scopes", dbgFlags, moreargs...)
+ subTest(t, debugger+"-dbg", "i22558", dbgFlags, moreargs...)
+
+ subTest(t, debugger+"-dbg-race", "i22600", dbgFlags, append(moreargs, "-race")...)
+
+ optSubTest(t, debugger+"-opt", "hist", optFlags, 1000, moreargs...)
+ optSubTest(t, debugger+"-opt", "scopes", optFlags, 1000, moreargs...)
+
+ // Was optSubtest, this test is observed flaky on Linux in Docker on (busy) macOS, probably because of timing
+ // glitches in this harness.
+ // TODO get rid of timing glitches in this harness.
+ skipSubTest(t, debugger+"-opt", "infloop", optFlags, 10, moreargs...)
+
+}
+
+// subTest creates a subtest that compiles basename.go with the specified gcflags and additional compiler arguments,
+// then runs the debugger on the resulting binary, with any comment-specified actions matching tag triggered.
+func subTest(t *testing.T, tag string, basename string, gcflags string, moreargs ...string) {
+ t.Run(tag+"-"+basename, func(t *testing.T) {
+ if t.Name() == "TestNexting/gdb-dbg-i22558" {
+ testenv.SkipFlaky(t, 31263)
+ }
+ testNexting(t, basename, tag, gcflags, 1000, moreargs...)
+ })
+}
+
+// skipSubTest is the same as subTest except that it skips the test if execution is not forced (-f)
+func skipSubTest(t *testing.T, tag string, basename string, gcflags string, count int, moreargs ...string) {
+ t.Run(tag+"-"+basename, func(t *testing.T) {
+ if *force {
+ testNexting(t, basename, tag, gcflags, count, moreargs...)
+ } else {
+ t.Skip("skipping flaky test becaused not forced (-f)")
+ }
+ })
+}
+
+// optSubTest is the same as subTest except that it skips the test if the runtime and libraries
+// were not compiled with optimization turned on. (The skip may not be necessary with Go 1.10 and later)
+func optSubTest(t *testing.T, tag string, basename string, gcflags string, count int, moreargs ...string) {
+ // If optimized test is run with unoptimized libraries (compiled with -N -l), it is very likely to fail.
+ // This occurs in the noopt builders (for example).
+ t.Run(tag+"-"+basename, func(t *testing.T) {
+ if *force || optimizedLibs {
+ testNexting(t, basename, tag, gcflags, count, moreargs...)
+ } else {
+ t.Skip("skipping for unoptimized stdlib/runtime")
+ }
+ })
+}
+
+func testNexting(t *testing.T, base, tag, gcflags string, count int, moreArgs ...string) {
+ // (1) In testdata, build sample.go into test-sample.<tag>
+ // (2) Run debugger gathering a history
+ // (3) Read expected history from testdata/sample.<tag>.nexts
+ // optionally, write out testdata/sample.<tag>.nexts
+
+ testbase := filepath.Join("testdata", base) + "." + tag
+ tmpbase := filepath.Join("testdata", "test-"+base+"."+tag)
+
+ // Use a temporary directory unless -f is specified
+ if !*force {
+ tmpdir, err := ioutil.TempDir("", "debug_test")
+ if err != nil {
+ panic(fmt.Sprintf("Problem creating TempDir, error %v\n", err))
+ }
+ tmpbase = filepath.Join(tmpdir, "test-"+base+"."+tag)
+ if *verbose {
+ fmt.Printf("Tempdir is %s\n", tmpdir)
+ }
+ defer os.RemoveAll(tmpdir)
+ }
+ exe := tmpbase
+
+ runGoArgs := []string{"build", "-o", exe, "-gcflags=all=" + gcflags}
+ runGoArgs = append(runGoArgs, moreArgs...)
+ runGoArgs = append(runGoArgs, filepath.Join("testdata", base+".go"))
+
+ runGo(t, "", runGoArgs...)
+
+ nextlog := testbase + ".nexts"
+ tmplog := tmpbase + ".nexts"
+ var dbg dbgr
+ if *useGdb {
+ dbg = newGdb(tag, exe)
+ } else {
+ dbg = newDelve(tag, exe)
+ }
+ h1 := runDbgr(dbg, count)
+ if *dryrun {
+ fmt.Printf("# Tag for above is %s\n", dbg.tag())
+ return
+ }
+ if *update {
+ h1.write(nextlog)
+ } else {
+ h0 := &nextHist{}
+ h0.read(nextlog)
+ if !h0.equals(h1) {
+ // Be very noisy about exactly what's wrong to simplify debugging.
+ h1.write(tmplog)
+ cmd := exec.Command("diff", "-u", nextlog, tmplog)
+ line := asCommandLine("", cmd)
+ bytes, err := cmd.CombinedOutput()
+ if err != nil && len(bytes) == 0 {
+ t.Fatalf("step/next histories differ, diff command %s failed with error=%v", line, err)
+ }
+ t.Fatalf("step/next histories differ, diff=\n%s", string(bytes))
+ }
+ }
+}
+
+type dbgr interface {
+ start()
+ stepnext(s string) bool // step or next, possible with parameter, gets line etc. returns true for success, false for unsure response
+ quit()
+ hist() *nextHist
+ tag() string
+}
+
+func runDbgr(dbg dbgr, maxNext int) *nextHist {
+ dbg.start()
+ if *dryrun {
+ return nil
+ }
+ for i := 0; i < maxNext; i++ {
+ if !dbg.stepnext("n") {
+ break
+ }
+ }
+ dbg.quit()
+ h := dbg.hist()
+ return h
+}
+
+func runGo(t *testing.T, dir string, args ...string) string {
+ var stdout, stderr bytes.Buffer
+ cmd := exec.Command(testenv.GoToolPath(t), args...)
+ cmd.Dir = dir
+ if *dryrun {
+ fmt.Printf("%s\n", asCommandLine("", cmd))
+ return ""
+ }
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+
+ if err := cmd.Run(); err != nil {
+ t.Fatalf("error running cmd (%s): %v\nstdout:\n%sstderr:\n%s\n", asCommandLine("", cmd), err, stdout.String(), stderr.String())
+ }
+
+ if s := stderr.String(); s != "" {
+ t.Fatalf("Stderr = %s\nWant empty", s)
+ }
+
+ return stdout.String()
+}
+
+// tstring provides two strings, o (stdout) and e (stderr)
+type tstring struct {
+ o string
+ e string
+}
+
+func (t tstring) String() string {
+ return t.o + t.e
+}
+
+type pos struct {
+ line uint32
+ file uint8 // Artifact of plans to implement differencing instead of calling out to diff.
+}
+
+type nextHist struct {
+ f2i map[string]uint8
+ fs []string
+ ps []pos
+ texts []string
+ vars [][]string
+}
+
+func (h *nextHist) write(filename string) {
+ file, err := os.Create(filename)
+ if err != nil {
+ panic(fmt.Sprintf("Problem opening %s, error %v\n", filename, err))
+ }
+ defer file.Close()
+ var lastfile uint8
+ for i, x := range h.texts {
+ p := h.ps[i]
+ if lastfile != p.file {
+ fmt.Fprintf(file, " %s\n", h.fs[p.file-1])
+ lastfile = p.file
+ }
+ fmt.Fprintf(file, "%d:%s\n", p.line, x)
+ // TODO, normalize between gdb and dlv into a common, comparable format.
+ for _, y := range h.vars[i] {
+ y = strings.TrimSpace(y)
+ fmt.Fprintf(file, "%s\n", y)
+ }
+ }
+ file.Close()
+}
+
+func (h *nextHist) read(filename string) {
+ h.f2i = make(map[string]uint8)
+ bytes, err := ioutil.ReadFile(filename)
+ if err != nil {
+ panic(fmt.Sprintf("Problem reading %s, error %v\n", filename, err))
+ }
+ var lastfile string
+ lines := strings.Split(string(bytes), "\n")
+ for i, l := range lines {
+ if len(l) > 0 && l[0] != '#' {
+ if l[0] == ' ' {
+ // file -- first two characters expected to be " "
+ lastfile = strings.TrimSpace(l)
+ } else if numberColonRe.MatchString(l) {
+ // line number -- <number>:<line>
+ colonPos := strings.Index(l, ":")
+ if colonPos == -1 {
+ panic(fmt.Sprintf("Line %d (%s) in file %s expected to contain '<number>:' but does not.\n", i+1, l, filename))
+ }
+ h.add(lastfile, l[0:colonPos], l[colonPos+1:])
+ } else {
+ h.addVar(l)
+ }
+ }
+ }
+}
+
+// add appends file (name), line (number) and text (string) to the history,
+// provided that the file+line combo does not repeat the previous position,
+// and provided that the file is within the testdata directory. The return
+// value indicates whether the append occurred.
+func (h *nextHist) add(file, line, text string) bool {
+ // Only record source code in testdata unless the inlines flag is set
+ if !*inlines && !strings.Contains(file, "/testdata/") {
+ return false
+ }
+ fi := h.f2i[file]
+ if fi == 0 {
+ h.fs = append(h.fs, file)
+ fi = uint8(len(h.fs))
+ h.f2i[file] = fi
+ }
+
+ line = strings.TrimSpace(line)
+ var li int
+ var err error
+ if line != "" {
+ li, err = strconv.Atoi(line)
+ if err != nil {
+ panic(fmt.Sprintf("Non-numeric line: %s, error %v\n", line, err))
+ }
+ }
+ l := len(h.ps)
+ p := pos{line: uint32(li), file: fi}
+
+ if l == 0 || *repeats || h.ps[l-1] != p {
+ h.ps = append(h.ps, p)
+ h.texts = append(h.texts, text)
+ h.vars = append(h.vars, []string{})
+ return true
+ }
+ return false
+}
+
+func (h *nextHist) addVar(text string) {
+ l := len(h.texts)
+ h.vars[l-1] = append(h.vars[l-1], text)
+}
+
+func invertMapSU8(hf2i map[string]uint8) map[uint8]string {
+ hi2f := make(map[uint8]string)
+ for hs, i := range hf2i {
+ hi2f[i] = hs
+ }
+ return hi2f
+}
+
+func (h *nextHist) equals(k *nextHist) bool {
+ if len(h.f2i) != len(k.f2i) {
+ return false
+ }
+ if len(h.ps) != len(k.ps) {
+ return false
+ }
+ hi2f := invertMapSU8(h.f2i)
+ ki2f := invertMapSU8(k.f2i)
+
+ for i, hs := range hi2f {
+ if hs != ki2f[i] {
+ return false
+ }
+ }
+
+ for i, x := range h.ps {
+ if k.ps[i] != x {
+ return false
+ }
+ }
+
+ for i, hv := range h.vars {
+ kv := k.vars[i]
+ if len(hv) != len(kv) {
+ return false
+ }
+ for j, hvt := range hv {
+ if hvt != kv[j] {
+ return false
+ }
+ }
+ }
+
+ return true
+}
+
+// canonFileName strips everything before "/src/" from a filename.
+// This makes file names portable across different machines,
+// home directories, and temporary directories.
+func canonFileName(f string) string {
+ i := strings.Index(f, "/src/")
+ if i != -1 {
+ f = f[i+1:]
+ }
+ return f
+}
+
+/* Delve */
+
+type delveState struct {
+ cmd *exec.Cmd
+ tagg string
+ *ioState
+ atLineRe *regexp.Regexp // "\n =>"
+ funcFileLinePCre *regexp.Regexp // "^> ([^ ]+) ([^:]+):([0-9]+) .*[(]PC: (0x[a-z0-9]+)"
+ line string
+ file string
+ function string
+}
+
+func newDelve(tag, executable string, args ...string) dbgr {
+ cmd := exec.Command("dlv", "exec", executable)
+ cmd.Env = replaceEnv(cmd.Env, "TERM", "dumb")
+ if len(args) > 0 {
+ cmd.Args = append(cmd.Args, "--")
+ cmd.Args = append(cmd.Args, args...)
+ }
+ s := &delveState{tagg: tag, cmd: cmd}
+ // HAHA Delve has control characters embedded to change the color of the => and the line number
+ // that would be '(\\x1b\\[[0-9;]+m)?' OR TERM=dumb
+ s.atLineRe = regexp.MustCompile("\n=>[[:space:]]+[0-9]+:(.*)")
+ s.funcFileLinePCre = regexp.MustCompile("> ([^ ]+) ([^:]+):([0-9]+) .*[(]PC: (0x[a-z0-9]+)[)]\n")
+ s.ioState = newIoState(s.cmd)
+ return s
+}
+
+func (s *delveState) tag() string {
+ return s.tagg
+}
+
+func (s *delveState) stepnext(ss string) bool {
+ x := s.ioState.writeReadExpect(ss+"\n", "[(]dlv[)] ")
+ excerpts := s.atLineRe.FindStringSubmatch(x.o)
+ locations := s.funcFileLinePCre.FindStringSubmatch(x.o)
+ excerpt := ""
+ if len(excerpts) > 1 {
+ excerpt = excerpts[1]
+ }
+ if len(locations) > 0 {
+ fn := canonFileName(locations[2])
+ if *verbose {
+ if s.file != fn {
+ fmt.Printf("%s\n", locations[2]) // don't canonocalize verbose logging
+ }
+ fmt.Printf(" %s\n", locations[3])
+ }
+ s.line = locations[3]
+ s.file = fn
+ s.function = locations[1]
+ s.ioState.history.add(s.file, s.line, excerpt)
+ // TODO: here is where variable processing will be added. See gdbState.stepnext as a guide.
+ // Adding this may require some amount of normalization so that logs are comparable.
+ return true
+ }
+ if *verbose {
+ fmt.Printf("DID NOT MATCH EXPECTED NEXT OUTPUT\nO='%s'\nE='%s'\n", x.o, x.e)
+ }
+ return false
+}
+
+func (s *delveState) start() {
+ if *dryrun {
+ fmt.Printf("%s\n", asCommandLine("", s.cmd))
+ fmt.Printf("b main.test\n")
+ fmt.Printf("c\n")
+ return
+ }
+ err := s.cmd.Start()
+ if err != nil {
+ line := asCommandLine("", s.cmd)
+ panic(fmt.Sprintf("There was an error [start] running '%s', %v\n", line, err))
+ }
+ s.ioState.readExpecting(-1, 5000, "Type 'help' for list of commands.")
+ s.ioState.writeReadExpect("b main.test\n", "[(]dlv[)] ")
+ s.stepnext("c")
+}
+
+func (s *delveState) quit() {
+ expect("", s.ioState.writeRead("q\n"))
+}
+
+/* Gdb */
+
+type gdbState struct {
+ cmd *exec.Cmd
+ tagg string
+ args []string
+ *ioState
+ atLineRe *regexp.Regexp
+ funcFileLinePCre *regexp.Regexp
+ line string
+ file string
+ function string
+}
+
+func newGdb(tag, executable string, args ...string) dbgr {
+ // Turn off shell, necessary for Darwin apparently
+ cmd := exec.Command(gdb, "-nx",
+ "-iex", fmt.Sprintf("add-auto-load-safe-path %s/src/runtime", runtime.GOROOT()),
+ "-ex", "set startup-with-shell off", executable)
+ cmd.Env = replaceEnv(cmd.Env, "TERM", "dumb")
+ s := &gdbState{tagg: tag, cmd: cmd, args: args}
+ s.atLineRe = regexp.MustCompile("(^|\n)([0-9]+)(.*)")
+ s.funcFileLinePCre = regexp.MustCompile(
+ "([^ ]+) [(][^)]*[)][ \\t\\n]+at ([^:]+):([0-9]+)")
+ // runtime.main () at /Users/drchase/GoogleDrive/work/go/src/runtime/proc.go:201
+ // function file line
+ // Thread 2 hit Breakpoint 1, main.main () at /Users/drchase/GoogleDrive/work/debug/hist.go:18
+ s.ioState = newIoState(s.cmd)
+ return s
+}
+
+func (s *gdbState) tag() string {
+ return s.tagg
+}
+
+func (s *gdbState) start() {
+ run := "run"
+ for _, a := range s.args {
+ run += " " + a // Can't quote args for gdb, it will pass them through including the quotes
+ }
+ if *dryrun {
+ fmt.Printf("%s\n", asCommandLine("", s.cmd))
+ fmt.Printf("tbreak main.test\n")
+ fmt.Printf("%s\n", run)
+ return
+ }
+ err := s.cmd.Start()
+ if err != nil {
+ line := asCommandLine("", s.cmd)
+ panic(fmt.Sprintf("There was an error [start] running '%s', %v\n", line, err))
+ }
+ s.ioState.readSimpleExpecting("[(]gdb[)] ")
+ x := s.ioState.writeReadExpect("b main.test\n", "[(]gdb[)] ")
+ expect("Breakpoint [0-9]+ at", x)
+ s.stepnext(run)
+}
+
+func (s *gdbState) stepnext(ss string) bool {
+ x := s.ioState.writeReadExpect(ss+"\n", "[(]gdb[)] ")
+ excerpts := s.atLineRe.FindStringSubmatch(x.o)
+ locations := s.funcFileLinePCre.FindStringSubmatch(x.o)
+ excerpt := ""
+ addedLine := false
+ if len(excerpts) == 0 && len(locations) == 0 {
+ if *verbose {
+ fmt.Printf("DID NOT MATCH %s", x.o)
+ }
+ return false
+ }
+ if len(excerpts) > 0 {
+ excerpt = excerpts[3]
+ }
+ if len(locations) > 0 {
+ fn := canonFileName(locations[2])
+ if *verbose {
+ if s.file != fn {
+ fmt.Printf("%s\n", locations[2])
+ }
+ fmt.Printf(" %s\n", locations[3])
+ }
+ s.line = locations[3]
+ s.file = fn
+ s.function = locations[1]
+ addedLine = s.ioState.history.add(s.file, s.line, excerpt)
+ }
+ if len(excerpts) > 0 {
+ if *verbose {
+ fmt.Printf(" %s\n", excerpts[2])
+ }
+ s.line = excerpts[2]
+ addedLine = s.ioState.history.add(s.file, s.line, excerpt)
+ }
+
+ if !addedLine {
+ // True if this was a repeat line
+ return true
+ }
+ // Look for //gdb-<tag>=(v1,v2,v3) and print v1, v2, v3
+ vars := varsToPrint(excerpt, "//"+s.tag()+"=(")
+ for _, v := range vars {
+ response := printVariableAndNormalize(v, func(v string) string {
+ return s.ioState.writeReadExpect("p "+v+"\n", "[(]gdb[)] ").String()
+ })
+ s.ioState.history.addVar(response)
+ }
+ return true
+}
+
+// printVariableAndNormalize extracts any slash-indicated normalizing requests from the variable
+// name, then uses printer to get the value of the variable from the debugger, and then
+// normalizes and returns the response.
+func printVariableAndNormalize(v string, printer func(v string) string) string {
+ slashIndex := strings.Index(v, "/")
+ substitutions := ""
+ if slashIndex != -1 {
+ substitutions = v[slashIndex:]
+ v = v[:slashIndex]
+ }
+ response := printer(v)
+ // expect something like "$1 = ..."
+ dollar := strings.Index(response, "$")
+ cr := strings.Index(response, "\n")
+
+ if dollar == -1 { // some not entirely expected response, whine and carry on.
+ if cr == -1 {
+ response = strings.TrimSpace(response) // discards trailing newline
+ response = strings.Replace(response, "\n", "<BR>", -1)
+ return "$ Malformed response " + response
+ }
+ response = strings.TrimSpace(response[:cr])
+ return "$ " + response
+ }
+ if cr == -1 {
+ cr = len(response)
+ }
+ // Convert the leading $<number> into the variable name to enhance readability
+ // and reduce scope of diffs if an earlier print-variable is added.
+ response = strings.TrimSpace(response[dollar:cr])
+ response = leadingDollarNumberRe.ReplaceAllString(response, v)
+
+ // Normalize value as requested.
+ if strings.Contains(substitutions, "A") {
+ response = hexRe.ReplaceAllString(response, "<A>")
+ }
+ if strings.Contains(substitutions, "N") {
+ response = numRe.ReplaceAllString(response, "<N>")
+ }
+ if strings.Contains(substitutions, "S") {
+ response = stringRe.ReplaceAllString(response, "<S>")
+ }
+ if strings.Contains(substitutions, "O") {
+ response = optOutGdbRe.ReplaceAllString(response, "<Optimized out, as expected>")
+ }
+ return response
+}
+
+// varsToPrint takes a source code line, and extracts the comma-separated variable names
+// found between lookfor and the next ")".
+// For example, if line includes "... //gdb-foo=(v1,v2,v3)" and
+// lookfor="//gdb-foo=(", then varsToPrint returns ["v1", "v2", "v3"]
+func varsToPrint(line, lookfor string) []string {
+ var vars []string
+ if strings.Contains(line, lookfor) {
+ x := line[strings.Index(line, lookfor)+len(lookfor):]
+ end := strings.Index(x, ")")
+ if end == -1 {
+ panic(fmt.Sprintf("Saw variable list begin %s in %s but no closing ')'", lookfor, line))
+ }
+ vars = strings.Split(x[:end], ",")
+ for i, y := range vars {
+ vars[i] = strings.TrimSpace(y)
+ }
+ }
+ return vars
+}
+
+func (s *gdbState) quit() {
+ response := s.ioState.writeRead("q\n")
+ if strings.Contains(response.o, "Quit anyway? (y or n)") {
+ defer func() {
+ if r := recover(); r != nil {
+ if s, ok := r.(string); !(ok && strings.Contains(s, "'Y\n'")) {
+ // Not the panic that was expected.
+ fmt.Printf("Expected a broken pipe panic, but saw the following panic instead")
+ panic(r)
+ }
+ }
+ }()
+ s.ioState.writeRead("Y\n")
+ }
+}
+
+type ioState struct {
+ stdout io.ReadCloser
+ stderr io.ReadCloser
+ stdin io.WriteCloser
+ outChan chan string
+ errChan chan string
+ last tstring // Output of previous step
+ history *nextHist
+}
+
+func newIoState(cmd *exec.Cmd) *ioState {
+ var err error
+ s := &ioState{}
+ s.history = &nextHist{}
+ s.history.f2i = make(map[string]uint8)
+ s.stdout, err = cmd.StdoutPipe()
+ line := asCommandLine("", cmd)
+ if err != nil {
+ panic(fmt.Sprintf("There was an error [stdoutpipe] running '%s', %v\n", line, err))
+ }
+ s.stderr, err = cmd.StderrPipe()
+ if err != nil {
+ panic(fmt.Sprintf("There was an error [stdouterr] running '%s', %v\n", line, err))
+ }
+ s.stdin, err = cmd.StdinPipe()
+ if err != nil {
+ panic(fmt.Sprintf("There was an error [stdinpipe] running '%s', %v\n", line, err))
+ }
+
+ s.outChan = make(chan string, 1)
+ s.errChan = make(chan string, 1)
+ go func() {
+ buffer := make([]byte, 4096)
+ for {
+ n, err := s.stdout.Read(buffer)
+ if n > 0 {
+ s.outChan <- string(buffer[0:n])
+ }
+ if err == io.EOF || n == 0 {
+ break
+ }
+ if err != nil {
+ fmt.Printf("Saw an error forwarding stdout")
+ break
+ }
+ }
+ close(s.outChan)
+ s.stdout.Close()
+ }()
+
+ go func() {
+ buffer := make([]byte, 4096)
+ for {
+ n, err := s.stderr.Read(buffer)
+ if n > 0 {
+ s.errChan <- string(buffer[0:n])
+ }
+ if err == io.EOF || n == 0 {
+ break
+ }
+ if err != nil {
+ fmt.Printf("Saw an error forwarding stderr")
+ break
+ }
+ }
+ close(s.errChan)
+ s.stderr.Close()
+ }()
+ return s
+}
+
+func (s *ioState) hist() *nextHist {
+ return s.history
+}
+
+// writeRead writes ss, then reads stdout and stderr, waiting 500ms to
+// be sure all the output has appeared.
+func (s *ioState) writeRead(ss string) tstring {
+ if *verbose {
+ fmt.Printf("=> %s", ss)
+ }
+ _, err := io.WriteString(s.stdin, ss)
+ if err != nil {
+ panic(fmt.Sprintf("There was an error writing '%s', %v\n", ss, err))
+ }
+ return s.readExpecting(-1, 500, "")
+}
+
+// writeReadExpect writes ss, then reads stdout and stderr until something
+// that matches expectRE appears. expectRE should not be ""
+func (s *ioState) writeReadExpect(ss, expectRE string) tstring {
+ if *verbose {
+ fmt.Printf("=> %s", ss)
+ }
+ if expectRE == "" {
+ panic("expectRE should not be empty; use .* instead")
+ }
+ _, err := io.WriteString(s.stdin, ss)
+ if err != nil {
+ panic(fmt.Sprintf("There was an error writing '%s', %v\n", ss, err))
+ }
+ return s.readSimpleExpecting(expectRE)
+}
+
+func (s *ioState) readExpecting(millis, interlineTimeout int, expectedRE string) tstring {
+ timeout := time.Millisecond * time.Duration(millis)
+ interline := time.Millisecond * time.Duration(interlineTimeout)
+ s.last = tstring{}
+ var re *regexp.Regexp
+ if expectedRE != "" {
+ re = regexp.MustCompile(expectedRE)
+ }
+loop:
+ for {
+ var timer <-chan time.Time
+ if timeout > 0 {
+ timer = time.After(timeout)
+ }
+ select {
+ case x, ok := <-s.outChan:
+ if !ok {
+ s.outChan = nil
+ }
+ s.last.o += x
+ case x, ok := <-s.errChan:
+ if !ok {
+ s.errChan = nil
+ }
+ s.last.e += x
+ case <-timer:
+ break loop
+ }
+ if re != nil {
+ if re.MatchString(s.last.o) {
+ break
+ }
+ if re.MatchString(s.last.e) {
+ break
+ }
+ }
+ timeout = interline
+ }
+ if *verbose {
+ fmt.Printf("<= %s%s", s.last.o, s.last.e)
+ }
+ return s.last
+}
+
+func (s *ioState) readSimpleExpecting(expectedRE string) tstring {
+ s.last = tstring{}
+ var re *regexp.Regexp
+ if expectedRE != "" {
+ re = regexp.MustCompile(expectedRE)
+ }
+ for {
+ select {
+ case x, ok := <-s.outChan:
+ if !ok {
+ s.outChan = nil
+ }
+ s.last.o += x
+ case x, ok := <-s.errChan:
+ if !ok {
+ s.errChan = nil
+ }
+ s.last.e += x
+ }
+ if re != nil {
+ if re.MatchString(s.last.o) {
+ break
+ }
+ if re.MatchString(s.last.e) {
+ break
+ }
+ }
+ }
+ if *verbose {
+ fmt.Printf("<= %s%s", s.last.o, s.last.e)
+ }
+ return s.last
+}
+
+// replaceEnv returns a new environment derived from env
+// by removing any existing definition of ev and adding ev=evv.
+func replaceEnv(env []string, ev string, evv string) []string {
+ evplus := ev + "="
+ var found bool
+ for i, v := range env {
+ if strings.HasPrefix(v, evplus) {
+ found = true
+ env[i] = evplus + evv
+ }
+ }
+ if !found {
+ env = append(env, evplus+evv)
+ }
+ return env
+}
+
+// asCommandLine renders cmd as something that could be copy-and-pasted into a command line
+// If cwd is not empty and different from the command's directory, prepend an appropriate "cd"
+func asCommandLine(cwd string, cmd *exec.Cmd) string {
+ s := "("
+ if cmd.Dir != "" && cmd.Dir != cwd {
+ s += "cd" + escape(cmd.Dir) + ";"
+ }
+ for _, e := range cmd.Env {
+ if !strings.HasPrefix(e, "PATH=") &&
+ !strings.HasPrefix(e, "HOME=") &&
+ !strings.HasPrefix(e, "USER=") &&
+ !strings.HasPrefix(e, "SHELL=") {
+ s += escape(e)
+ }
+ }
+ for _, a := range cmd.Args {
+ s += escape(a)
+ }
+ s += " )"
+ return s
+}
+
+// escape inserts escapes appropriate for use in a shell command line
+func escape(s string) string {
+ s = strings.Replace(s, "\\", "\\\\", -1)
+ s = strings.Replace(s, "'", "\\'", -1)
+ // Conservative guess at characters that will force quoting
+ if strings.ContainsAny(s, "\\ ;#*&$~?!|[]()<>{}`") {
+ s = " '" + s + "'"
+ } else {
+ s = " " + s
+ }
+ return s
+}
+
+func expect(want string, got tstring) {
+ if want != "" {
+ match, err := regexp.MatchString(want, got.o)
+ if err != nil {
+ panic(fmt.Sprintf("Error for regexp %s, %v\n", want, err))
+ }
+ if match {
+ return
+ }
+ // Ignore error as we have already checked for it before
+ match, _ = regexp.MatchString(want, got.e)
+ if match {
+ return
+ }
+ fmt.Printf("EXPECTED '%s'\n GOT O='%s'\nAND E='%s'\n", want, got.o, got.e)
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/decompose.go b/src/cmd/compile/internal/ssa/decompose.go
new file mode 100644
index 0000000..bf7f1e8
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/decompose.go
@@ -0,0 +1,449 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "sort"
+)
+
+// decompose converts phi ops on compound builtin types into phi
+// ops on simple types, then invokes rewrite rules to decompose
+// other ops on those types.
+func decomposeBuiltIn(f *Func) {
+ // Decompose phis
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ continue
+ }
+ decomposeBuiltInPhi(v)
+ }
+ }
+
+ // Decompose other values
+ // Note: deadcode is false because we need to keep the original
+ // values around so the name component resolution below can still work.
+ applyRewrite(f, rewriteBlockdec, rewriteValuedec, leaveDeadValues)
+ if f.Config.RegSize == 4 {
+ applyRewrite(f, rewriteBlockdec64, rewriteValuedec64, leaveDeadValues)
+ }
+
+ // Split up named values into their components.
+ // accumulate old names for aggregates (that are decomposed) in toDelete for efficient bulk deletion,
+ // accumulate new LocalSlots in newNames for addition after the iteration. This decomposition is for
+ // builtin types with leaf components, and thus there is no need to reprocess the newly create LocalSlots.
+ var toDelete []namedVal
+ var newNames []LocalSlot
+ for i, name := range f.Names {
+ t := name.Type
+ switch {
+ case t.IsInteger() && t.Size() > f.Config.RegSize:
+ hiName, loName := f.fe.SplitInt64(name)
+ newNames = append(newNames, hiName, loName)
+ for j, v := range f.NamedValues[name] {
+ if v.Op != OpInt64Make {
+ continue
+ }
+ f.NamedValues[hiName] = append(f.NamedValues[hiName], v.Args[0])
+ f.NamedValues[loName] = append(f.NamedValues[loName], v.Args[1])
+ toDelete = append(toDelete, namedVal{i, j})
+ }
+ case t.IsComplex():
+ rName, iName := f.fe.SplitComplex(name)
+ newNames = append(newNames, rName, iName)
+ for j, v := range f.NamedValues[name] {
+ if v.Op != OpComplexMake {
+ continue
+ }
+ f.NamedValues[rName] = append(f.NamedValues[rName], v.Args[0])
+ f.NamedValues[iName] = append(f.NamedValues[iName], v.Args[1])
+ toDelete = append(toDelete, namedVal{i, j})
+ }
+ case t.IsString():
+ ptrName, lenName := f.fe.SplitString(name)
+ newNames = append(newNames, ptrName, lenName)
+ for j, v := range f.NamedValues[name] {
+ if v.Op != OpStringMake {
+ continue
+ }
+ f.NamedValues[ptrName] = append(f.NamedValues[ptrName], v.Args[0])
+ f.NamedValues[lenName] = append(f.NamedValues[lenName], v.Args[1])
+ toDelete = append(toDelete, namedVal{i, j})
+ }
+ case t.IsSlice():
+ ptrName, lenName, capName := f.fe.SplitSlice(name)
+ newNames = append(newNames, ptrName, lenName, capName)
+ for j, v := range f.NamedValues[name] {
+ if v.Op != OpSliceMake {
+ continue
+ }
+ f.NamedValues[ptrName] = append(f.NamedValues[ptrName], v.Args[0])
+ f.NamedValues[lenName] = append(f.NamedValues[lenName], v.Args[1])
+ f.NamedValues[capName] = append(f.NamedValues[capName], v.Args[2])
+ toDelete = append(toDelete, namedVal{i, j})
+ }
+ case t.IsInterface():
+ typeName, dataName := f.fe.SplitInterface(name)
+ newNames = append(newNames, typeName, dataName)
+ for j, v := range f.NamedValues[name] {
+ if v.Op != OpIMake {
+ continue
+ }
+ f.NamedValues[typeName] = append(f.NamedValues[typeName], v.Args[0])
+ f.NamedValues[dataName] = append(f.NamedValues[dataName], v.Args[1])
+ toDelete = append(toDelete, namedVal{i, j})
+ }
+ case t.IsFloat():
+ // floats are never decomposed, even ones bigger than RegSize
+ case t.Size() > f.Config.RegSize:
+ f.Fatalf("undecomposed named type %s %v", name, t)
+ }
+ }
+
+ deleteNamedVals(f, toDelete)
+ f.Names = append(f.Names, newNames...)
+}
+
+func decomposeBuiltInPhi(v *Value) {
+ switch {
+ case v.Type.IsInteger() && v.Type.Size() > v.Block.Func.Config.RegSize:
+ decomposeInt64Phi(v)
+ case v.Type.IsComplex():
+ decomposeComplexPhi(v)
+ case v.Type.IsString():
+ decomposeStringPhi(v)
+ case v.Type.IsSlice():
+ decomposeSlicePhi(v)
+ case v.Type.IsInterface():
+ decomposeInterfacePhi(v)
+ case v.Type.IsFloat():
+ // floats are never decomposed, even ones bigger than RegSize
+ case v.Type.Size() > v.Block.Func.Config.RegSize:
+ v.Fatalf("undecomposed type %s", v.Type)
+ }
+}
+
+func decomposeStringPhi(v *Value) {
+ types := &v.Block.Func.Config.Types
+ ptrType := types.BytePtr
+ lenType := types.Int
+
+ ptr := v.Block.NewValue0(v.Pos, OpPhi, ptrType)
+ len := v.Block.NewValue0(v.Pos, OpPhi, lenType)
+ for _, a := range v.Args {
+ ptr.AddArg(a.Block.NewValue1(v.Pos, OpStringPtr, ptrType, a))
+ len.AddArg(a.Block.NewValue1(v.Pos, OpStringLen, lenType, a))
+ }
+ v.reset(OpStringMake)
+ v.AddArg(ptr)
+ v.AddArg(len)
+}
+
+func decomposeSlicePhi(v *Value) {
+ types := &v.Block.Func.Config.Types
+ ptrType := v.Type.Elem().PtrTo()
+ lenType := types.Int
+
+ ptr := v.Block.NewValue0(v.Pos, OpPhi, ptrType)
+ len := v.Block.NewValue0(v.Pos, OpPhi, lenType)
+ cap := v.Block.NewValue0(v.Pos, OpPhi, lenType)
+ for _, a := range v.Args {
+ ptr.AddArg(a.Block.NewValue1(v.Pos, OpSlicePtr, ptrType, a))
+ len.AddArg(a.Block.NewValue1(v.Pos, OpSliceLen, lenType, a))
+ cap.AddArg(a.Block.NewValue1(v.Pos, OpSliceCap, lenType, a))
+ }
+ v.reset(OpSliceMake)
+ v.AddArg(ptr)
+ v.AddArg(len)
+ v.AddArg(cap)
+}
+
+func decomposeInt64Phi(v *Value) {
+ cfgtypes := &v.Block.Func.Config.Types
+ var partType *types.Type
+ if v.Type.IsSigned() {
+ partType = cfgtypes.Int32
+ } else {
+ partType = cfgtypes.UInt32
+ }
+
+ hi := v.Block.NewValue0(v.Pos, OpPhi, partType)
+ lo := v.Block.NewValue0(v.Pos, OpPhi, cfgtypes.UInt32)
+ for _, a := range v.Args {
+ hi.AddArg(a.Block.NewValue1(v.Pos, OpInt64Hi, partType, a))
+ lo.AddArg(a.Block.NewValue1(v.Pos, OpInt64Lo, cfgtypes.UInt32, a))
+ }
+ v.reset(OpInt64Make)
+ v.AddArg(hi)
+ v.AddArg(lo)
+}
+
+func decomposeComplexPhi(v *Value) {
+ cfgtypes := &v.Block.Func.Config.Types
+ var partType *types.Type
+ switch z := v.Type.Size(); z {
+ case 8:
+ partType = cfgtypes.Float32
+ case 16:
+ partType = cfgtypes.Float64
+ default:
+ v.Fatalf("decomposeComplexPhi: bad complex size %d", z)
+ }
+
+ real := v.Block.NewValue0(v.Pos, OpPhi, partType)
+ imag := v.Block.NewValue0(v.Pos, OpPhi, partType)
+ for _, a := range v.Args {
+ real.AddArg(a.Block.NewValue1(v.Pos, OpComplexReal, partType, a))
+ imag.AddArg(a.Block.NewValue1(v.Pos, OpComplexImag, partType, a))
+ }
+ v.reset(OpComplexMake)
+ v.AddArg(real)
+ v.AddArg(imag)
+}
+
+func decomposeInterfacePhi(v *Value) {
+ uintptrType := v.Block.Func.Config.Types.Uintptr
+ ptrType := v.Block.Func.Config.Types.BytePtr
+
+ itab := v.Block.NewValue0(v.Pos, OpPhi, uintptrType)
+ data := v.Block.NewValue0(v.Pos, OpPhi, ptrType)
+ for _, a := range v.Args {
+ itab.AddArg(a.Block.NewValue1(v.Pos, OpITab, uintptrType, a))
+ data.AddArg(a.Block.NewValue1(v.Pos, OpIData, ptrType, a))
+ }
+ v.reset(OpIMake)
+ v.AddArg(itab)
+ v.AddArg(data)
+}
+
+func decomposeArgs(f *Func) {
+ applyRewrite(f, rewriteBlockdecArgs, rewriteValuedecArgs, removeDeadValues)
+}
+
+func decomposeUser(f *Func) {
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ continue
+ }
+ decomposeUserPhi(v)
+ }
+ }
+ // Split up named values into their components.
+ i := 0
+ var newNames []LocalSlot
+ for _, name := range f.Names {
+ t := name.Type
+ switch {
+ case t.IsStruct():
+ newNames = decomposeUserStructInto(f, name, newNames)
+ case t.IsArray():
+ newNames = decomposeUserArrayInto(f, name, newNames)
+ default:
+ f.Names[i] = name
+ i++
+ }
+ }
+ f.Names = f.Names[:i]
+ f.Names = append(f.Names, newNames...)
+}
+
+// decomposeUserArrayInto creates names for the element(s) of arrays referenced
+// by name where possible, and appends those new names to slots, which is then
+// returned.
+func decomposeUserArrayInto(f *Func, name LocalSlot, slots []LocalSlot) []LocalSlot {
+ t := name.Type
+ if t.NumElem() == 0 {
+ // TODO(khr): Not sure what to do here. Probably nothing.
+ // Names for empty arrays aren't important.
+ return slots
+ }
+ if t.NumElem() != 1 {
+ // shouldn't get here due to CanSSA
+ f.Fatalf("array not of size 1")
+ }
+ elemName := f.fe.SplitArray(name)
+ var keep []*Value
+ for _, v := range f.NamedValues[name] {
+ if v.Op != OpArrayMake1 {
+ keep = append(keep, v)
+ continue
+ }
+ f.NamedValues[elemName] = append(f.NamedValues[elemName], v.Args[0])
+ }
+ if len(keep) == 0 {
+ // delete the name for the array as a whole
+ delete(f.NamedValues, name)
+ } else {
+ f.NamedValues[name] = keep
+ }
+
+ if t.Elem().IsArray() {
+ return decomposeUserArrayInto(f, elemName, slots)
+ } else if t.Elem().IsStruct() {
+ return decomposeUserStructInto(f, elemName, slots)
+ }
+
+ return append(slots, elemName)
+}
+
+// decomposeUserStructInto creates names for the fields(s) of structs referenced
+// by name where possible, and appends those new names to slots, which is then
+// returned.
+func decomposeUserStructInto(f *Func, name LocalSlot, slots []LocalSlot) []LocalSlot {
+ fnames := []LocalSlot{} // slots for struct in name
+ t := name.Type
+ n := t.NumFields()
+
+ for i := 0; i < n; i++ {
+ fs := f.fe.SplitStruct(name, i)
+ fnames = append(fnames, fs)
+ // arrays and structs will be decomposed further, so
+ // there's no need to record a name
+ if !fs.Type.IsArray() && !fs.Type.IsStruct() {
+ slots = append(slots, fs)
+ }
+ }
+
+ makeOp := StructMakeOp(n)
+ var keep []*Value
+ // create named values for each struct field
+ for _, v := range f.NamedValues[name] {
+ if v.Op != makeOp {
+ keep = append(keep, v)
+ continue
+ }
+ for i := 0; i < len(fnames); i++ {
+ f.NamedValues[fnames[i]] = append(f.NamedValues[fnames[i]], v.Args[i])
+ }
+ }
+ if len(keep) == 0 {
+ // delete the name for the struct as a whole
+ delete(f.NamedValues, name)
+ } else {
+ f.NamedValues[name] = keep
+ }
+
+ // now that this f.NamedValues contains values for the struct
+ // fields, recurse into nested structs
+ for i := 0; i < n; i++ {
+ if name.Type.FieldType(i).IsStruct() {
+ slots = decomposeUserStructInto(f, fnames[i], slots)
+ delete(f.NamedValues, fnames[i])
+ } else if name.Type.FieldType(i).IsArray() {
+ slots = decomposeUserArrayInto(f, fnames[i], slots)
+ delete(f.NamedValues, fnames[i])
+ }
+ }
+ return slots
+}
+func decomposeUserPhi(v *Value) {
+ switch {
+ case v.Type.IsStruct():
+ decomposeStructPhi(v)
+ case v.Type.IsArray():
+ decomposeArrayPhi(v)
+ }
+}
+
+// decomposeStructPhi replaces phi-of-struct with structmake(phi-for-each-field),
+// and then recursively decomposes the phis for each field.
+func decomposeStructPhi(v *Value) {
+ t := v.Type
+ n := t.NumFields()
+ var fields [MaxStruct]*Value
+ for i := 0; i < n; i++ {
+ fields[i] = v.Block.NewValue0(v.Pos, OpPhi, t.FieldType(i))
+ }
+ for _, a := range v.Args {
+ for i := 0; i < n; i++ {
+ fields[i].AddArg(a.Block.NewValue1I(v.Pos, OpStructSelect, t.FieldType(i), int64(i), a))
+ }
+ }
+ v.reset(StructMakeOp(n))
+ v.AddArgs(fields[:n]...)
+
+ // Recursively decompose phis for each field.
+ for _, f := range fields[:n] {
+ decomposeUserPhi(f)
+ }
+}
+
+// decomposeArrayPhi replaces phi-of-array with arraymake(phi-of-array-element),
+// and then recursively decomposes the element phi.
+func decomposeArrayPhi(v *Value) {
+ t := v.Type
+ if t.NumElem() == 0 {
+ v.reset(OpArrayMake0)
+ return
+ }
+ if t.NumElem() != 1 {
+ v.Fatalf("SSAable array must have no more than 1 element")
+ }
+ elem := v.Block.NewValue0(v.Pos, OpPhi, t.Elem())
+ for _, a := range v.Args {
+ elem.AddArg(a.Block.NewValue1I(v.Pos, OpArraySelect, t.Elem(), 0, a))
+ }
+ v.reset(OpArrayMake1)
+ v.AddArg(elem)
+
+ // Recursively decompose elem phi.
+ decomposeUserPhi(elem)
+}
+
+// MaxStruct is the maximum number of fields a struct
+// can have and still be SSAable.
+const MaxStruct = 4
+
+// StructMakeOp returns the opcode to construct a struct with the
+// given number of fields.
+func StructMakeOp(nf int) Op {
+ switch nf {
+ case 0:
+ return OpStructMake0
+ case 1:
+ return OpStructMake1
+ case 2:
+ return OpStructMake2
+ case 3:
+ return OpStructMake3
+ case 4:
+ return OpStructMake4
+ }
+ panic("too many fields in an SSAable struct")
+}
+
+type namedVal struct {
+ locIndex, valIndex int // f.NamedValues[f.Names[locIndex]][valIndex] = key
+}
+
+// deleteNamedVals removes particular values with debugger names from f's naming data structures
+func deleteNamedVals(f *Func, toDelete []namedVal) {
+ // Arrange to delete from larger indices to smaller, to ensure swap-with-end deletion does not invalid pending indices.
+ sort.Slice(toDelete, func(i, j int) bool {
+ if toDelete[i].locIndex != toDelete[j].locIndex {
+ return toDelete[i].locIndex > toDelete[j].locIndex
+ }
+ return toDelete[i].valIndex > toDelete[j].valIndex
+
+ })
+
+ // Get rid of obsolete names
+ for _, d := range toDelete {
+ loc := f.Names[d.locIndex]
+ vals := f.NamedValues[loc]
+ l := len(vals) - 1
+ if l > 0 {
+ vals[d.valIndex] = vals[l]
+ f.NamedValues[loc] = vals[:l]
+ } else {
+ delete(f.NamedValues, loc)
+ l = len(f.Names) - 1
+ f.Names[d.locIndex] = f.Names[l]
+ f.Names = f.Names[:l]
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/dom.go b/src/cmd/compile/internal/ssa/dom.go
new file mode 100644
index 0000000..f31e7df
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/dom.go
@@ -0,0 +1,302 @@
+// 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
+
+// This file contains code to compute the dominator tree
+// of a control-flow graph.
+
+// postorder computes a postorder traversal ordering for the
+// basic blocks in f. Unreachable blocks will not appear.
+func postorder(f *Func) []*Block {
+ return postorderWithNumbering(f, nil)
+}
+
+type blockAndIndex struct {
+ b *Block
+ index int // index is the number of successor edges of b that have already been explored.
+}
+
+// postorderWithNumbering provides a DFS postordering.
+// This seems to make loop-finding more robust.
+func postorderWithNumbering(f *Func, ponums []int32) []*Block {
+ seen := make([]bool, f.NumBlocks())
+
+ // result ordering
+ order := make([]*Block, 0, len(f.Blocks))
+
+ // stack of blocks and next child to visit
+ // A constant bound allows this to be stack-allocated. 32 is
+ // enough to cover almost every postorderWithNumbering call.
+ s := make([]blockAndIndex, 0, 32)
+ s = append(s, blockAndIndex{b: f.Entry})
+ seen[f.Entry.ID] = true
+ for len(s) > 0 {
+ tos := len(s) - 1
+ x := s[tos]
+ b := x.b
+ if i := x.index; i < len(b.Succs) {
+ s[tos].index++
+ bb := b.Succs[i].Block()
+ if !seen[bb.ID] {
+ seen[bb.ID] = true
+ s = append(s, blockAndIndex{b: bb})
+ }
+ continue
+ }
+ s = s[:tos]
+ if ponums != nil {
+ ponums[b.ID] = int32(len(order))
+ }
+ order = append(order, b)
+ }
+ return order
+}
+
+type linkedBlocks func(*Block) []Edge
+
+const nscratchslices = 7
+
+// experimentally, functions with 512 or fewer blocks account
+// for 75% of memory (size) allocation for dominator computation
+// in make.bash.
+const minscratchblocks = 512
+
+func (cache *Cache) scratchBlocksForDom(maxBlockID int) (a, b, c, d, e, f, g []ID) {
+ tot := maxBlockID * nscratchslices
+ scratch := cache.domblockstore
+ if len(scratch) < tot {
+ // req = min(1.5*tot, nscratchslices*minscratchblocks)
+ // 50% padding allows for graph growth in later phases.
+ req := (tot * 3) >> 1
+ if req < nscratchslices*minscratchblocks {
+ req = nscratchslices * minscratchblocks
+ }
+ scratch = make([]ID, req)
+ cache.domblockstore = scratch
+ } else {
+ // Clear as much of scratch as we will (re)use
+ scratch = scratch[0:tot]
+ for i := range scratch {
+ scratch[i] = 0
+ }
+ }
+
+ a = scratch[0*maxBlockID : 1*maxBlockID]
+ b = scratch[1*maxBlockID : 2*maxBlockID]
+ c = scratch[2*maxBlockID : 3*maxBlockID]
+ d = scratch[3*maxBlockID : 4*maxBlockID]
+ e = scratch[4*maxBlockID : 5*maxBlockID]
+ f = scratch[5*maxBlockID : 6*maxBlockID]
+ g = scratch[6*maxBlockID : 7*maxBlockID]
+
+ return
+}
+
+func dominators(f *Func) []*Block {
+ preds := func(b *Block) []Edge { return b.Preds }
+ succs := func(b *Block) []Edge { return b.Succs }
+
+ //TODO: benchmark and try to find criteria for swapping between
+ // dominatorsSimple and dominatorsLT
+ return f.dominatorsLTOrig(f.Entry, preds, succs)
+}
+
+// dominatorsLTOrig runs Lengauer-Tarjan to compute a dominator tree starting at
+// entry and using predFn/succFn to find predecessors/successors to allow
+// computing both dominator and post-dominator trees.
+func (f *Func) dominatorsLTOrig(entry *Block, predFn linkedBlocks, succFn linkedBlocks) []*Block {
+ // Adapted directly from the original TOPLAS article's "simple" algorithm
+
+ maxBlockID := entry.Func.NumBlocks()
+ semi, vertex, label, parent, ancestor, bucketHead, bucketLink := f.Cache.scratchBlocksForDom(maxBlockID)
+
+ // This version uses integers for most of the computation,
+ // to make the work arrays smaller and pointer-free.
+ // fromID translates from ID to *Block where that is needed.
+ fromID := make([]*Block, maxBlockID)
+ for _, v := range f.Blocks {
+ fromID[v.ID] = v
+ }
+ idom := make([]*Block, maxBlockID)
+
+ // Step 1. Carry out a depth first search of the problem graph. Number
+ // the vertices from 1 to n as they are reached during the search.
+ n := f.dfsOrig(entry, succFn, semi, vertex, label, parent)
+
+ for i := n; i >= 2; i-- {
+ w := vertex[i]
+
+ // step2 in TOPLAS paper
+ for _, e := range predFn(fromID[w]) {
+ v := e.b
+ if semi[v.ID] == 0 {
+ // skip unreachable predecessor
+ // not in original, but we're using existing pred instead of building one.
+ continue
+ }
+ u := evalOrig(v.ID, ancestor, semi, label)
+ if semi[u] < semi[w] {
+ semi[w] = semi[u]
+ }
+ }
+
+ // add w to bucket[vertex[semi[w]]]
+ // implement bucket as a linked list implemented
+ // in a pair of arrays.
+ vsw := vertex[semi[w]]
+ bucketLink[w] = bucketHead[vsw]
+ bucketHead[vsw] = w
+
+ linkOrig(parent[w], w, ancestor)
+
+ // step3 in TOPLAS paper
+ for v := bucketHead[parent[w]]; v != 0; v = bucketLink[v] {
+ u := evalOrig(v, ancestor, semi, label)
+ if semi[u] < semi[v] {
+ idom[v] = fromID[u]
+ } else {
+ idom[v] = fromID[parent[w]]
+ }
+ }
+ }
+ // step 4 in toplas paper
+ for i := ID(2); i <= n; i++ {
+ w := vertex[i]
+ if idom[w].ID != vertex[semi[w]] {
+ idom[w] = idom[idom[w].ID]
+ }
+ }
+
+ return idom
+}
+
+// dfs performs a depth first search over the blocks starting at entry block
+// (in arbitrary order). This is a de-recursed version of dfs from the
+// original Tarjan-Lengauer TOPLAS article. It's important to return the
+// same values for parent as the original algorithm.
+func (f *Func) dfsOrig(entry *Block, succFn linkedBlocks, semi, vertex, label, parent []ID) ID {
+ n := ID(0)
+ s := make([]*Block, 0, 256)
+ s = append(s, entry)
+
+ for len(s) > 0 {
+ v := s[len(s)-1]
+ s = s[:len(s)-1]
+ // recursing on v
+
+ if semi[v.ID] != 0 {
+ continue // already visited
+ }
+ n++
+ semi[v.ID] = n
+ vertex[n] = v.ID
+ label[v.ID] = v.ID
+ // ancestor[v] already zero
+ for _, e := range succFn(v) {
+ w := e.b
+ // if it has a dfnum, we've already visited it
+ if semi[w.ID] == 0 {
+ // yes, w can be pushed multiple times.
+ s = append(s, w)
+ parent[w.ID] = v.ID // keep overwriting this till it is visited.
+ }
+ }
+ }
+ return n
+}
+
+// compressOrig is the "simple" compress function from LT paper
+func compressOrig(v ID, ancestor, semi, label []ID) {
+ if ancestor[ancestor[v]] != 0 {
+ compressOrig(ancestor[v], ancestor, semi, label)
+ if semi[label[ancestor[v]]] < semi[label[v]] {
+ label[v] = label[ancestor[v]]
+ }
+ ancestor[v] = ancestor[ancestor[v]]
+ }
+}
+
+// evalOrig is the "simple" eval function from LT paper
+func evalOrig(v ID, ancestor, semi, label []ID) ID {
+ if ancestor[v] == 0 {
+ return v
+ }
+ compressOrig(v, ancestor, semi, label)
+ return label[v]
+}
+
+func linkOrig(v, w ID, ancestor []ID) {
+ ancestor[w] = v
+}
+
+// dominators computes the dominator tree for f. It returns a slice
+// which maps block ID to the immediate dominator of that block.
+// Unreachable blocks map to nil. The entry block maps to nil.
+func dominatorsSimple(f *Func) []*Block {
+ // A simple algorithm for now
+ // Cooper, Harvey, Kennedy
+ idom := make([]*Block, f.NumBlocks())
+
+ // Compute postorder walk
+ post := f.postorder()
+
+ // Make map from block id to order index (for intersect call)
+ postnum := make([]int, f.NumBlocks())
+ for i, b := range post {
+ postnum[b.ID] = i
+ }
+
+ // Make the entry block a self-loop
+ idom[f.Entry.ID] = f.Entry
+ if postnum[f.Entry.ID] != len(post)-1 {
+ f.Fatalf("entry block %v not last in postorder", f.Entry)
+ }
+
+ // Compute relaxation of idom entries
+ for {
+ changed := false
+
+ for i := len(post) - 2; i >= 0; i-- {
+ b := post[i]
+ var d *Block
+ for _, e := range b.Preds {
+ p := e.b
+ if idom[p.ID] == nil {
+ continue
+ }
+ if d == nil {
+ d = p
+ continue
+ }
+ d = intersect(d, p, postnum, idom)
+ }
+ if d != idom[b.ID] {
+ idom[b.ID] = d
+ changed = true
+ }
+ }
+ if !changed {
+ break
+ }
+ }
+ // Set idom of entry block to nil instead of itself.
+ idom[f.Entry.ID] = nil
+ return idom
+}
+
+// intersect finds the closest dominator of both b and c.
+// It requires a postorder numbering of all the blocks.
+func intersect(b, c *Block, postnum []int, idom []*Block) *Block {
+ // TODO: This loop is O(n^2). It used to be used in nilcheck,
+ // see BenchmarkNilCheckDeep*.
+ for b != c {
+ if postnum[b.ID] < postnum[c.ID] {
+ b = idom[b.ID]
+ } else {
+ c = idom[c.ID]
+ }
+ }
+ return b
+}
diff --git a/src/cmd/compile/internal/ssa/dom_test.go b/src/cmd/compile/internal/ssa/dom_test.go
new file mode 100644
index 0000000..fa51718
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/dom_test.go
@@ -0,0 +1,608 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "testing"
+)
+
+func BenchmarkDominatorsLinear(b *testing.B) { benchmarkDominators(b, 10000, genLinear) }
+func BenchmarkDominatorsFwdBack(b *testing.B) { benchmarkDominators(b, 10000, genFwdBack) }
+func BenchmarkDominatorsManyPred(b *testing.B) { benchmarkDominators(b, 10000, genManyPred) }
+func BenchmarkDominatorsMaxPred(b *testing.B) { benchmarkDominators(b, 10000, genMaxPred) }
+func BenchmarkDominatorsMaxPredVal(b *testing.B) { benchmarkDominators(b, 10000, genMaxPredValue) }
+
+type blockGen func(size int) []bloc
+
+// genLinear creates an array of blocks that succeed one another
+// b_n -> [b_n+1].
+func genLinear(size int) []bloc {
+ var blocs []bloc
+ blocs = append(blocs,
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Goto(blockn(0)),
+ ),
+ )
+ for i := 0; i < size; i++ {
+ blocs = append(blocs, Bloc(blockn(i),
+ Goto(blockn(i+1))))
+ }
+
+ blocs = append(blocs,
+ Bloc(blockn(size), Goto("exit")),
+ Bloc("exit", Exit("mem")),
+ )
+
+ return blocs
+}
+
+// genLinear creates an array of blocks that alternate between
+// b_n -> [b_n+1], b_n -> [b_n+1, b_n-1] , b_n -> [b_n+1, b_n+2]
+func genFwdBack(size int) []bloc {
+ var blocs []bloc
+ blocs = append(blocs,
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ Goto(blockn(0)),
+ ),
+ )
+ for i := 0; i < size; i++ {
+ switch i % 2 {
+ case 0:
+ blocs = append(blocs, Bloc(blockn(i),
+ If("p", blockn(i+1), blockn(i+2))))
+ case 1:
+ blocs = append(blocs, Bloc(blockn(i),
+ If("p", blockn(i+1), blockn(i-1))))
+ }
+ }
+
+ blocs = append(blocs,
+ Bloc(blockn(size), Goto("exit")),
+ Bloc("exit", Exit("mem")),
+ )
+
+ return blocs
+}
+
+// genManyPred creates an array of blocks where 1/3rd have a successor of the
+// first block, 1/3rd the last block, and the remaining third are plain.
+func genManyPred(size int) []bloc {
+ var blocs []bloc
+ blocs = append(blocs,
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ Goto(blockn(0)),
+ ),
+ )
+
+ // We want predecessor lists to be long, so 2/3rds of the blocks have a
+ // successor of the first or last block.
+ for i := 0; i < size; i++ {
+ switch i % 3 {
+ case 0:
+ blocs = append(blocs, Bloc(blockn(i),
+ Valu("a", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ Goto(blockn(i+1))))
+ case 1:
+ blocs = append(blocs, Bloc(blockn(i),
+ Valu("a", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ If("p", blockn(i+1), blockn(0))))
+ case 2:
+ blocs = append(blocs, Bloc(blockn(i),
+ Valu("a", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ If("p", blockn(i+1), blockn(size))))
+ }
+ }
+
+ blocs = append(blocs,
+ Bloc(blockn(size), Goto("exit")),
+ Bloc("exit", Exit("mem")),
+ )
+
+ return blocs
+}
+
+// genMaxPred maximizes the size of the 'exit' predecessor list.
+func genMaxPred(size int) []bloc {
+ var blocs []bloc
+ blocs = append(blocs,
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ Goto(blockn(0)),
+ ),
+ )
+
+ for i := 0; i < size; i++ {
+ blocs = append(blocs, Bloc(blockn(i),
+ If("p", blockn(i+1), "exit")))
+ }
+
+ blocs = append(blocs,
+ Bloc(blockn(size), Goto("exit")),
+ Bloc("exit", Exit("mem")),
+ )
+
+ return blocs
+}
+
+// genMaxPredValue is identical to genMaxPred but contains an
+// additional value.
+func genMaxPredValue(size int) []bloc {
+ var blocs []bloc
+ blocs = append(blocs,
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ Goto(blockn(0)),
+ ),
+ )
+
+ for i := 0; i < size; i++ {
+ blocs = append(blocs, Bloc(blockn(i),
+ Valu("a", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ If("p", blockn(i+1), "exit")))
+ }
+
+ blocs = append(blocs,
+ Bloc(blockn(size), Goto("exit")),
+ Bloc("exit", Exit("mem")),
+ )
+
+ return blocs
+}
+
+// sink for benchmark
+var domBenchRes []*Block
+
+func benchmarkDominators(b *testing.B, size int, bg blockGen) {
+ c := testConfig(b)
+ fun := c.Fun("entry", bg(size)...)
+
+ CheckFunc(fun.f)
+ b.SetBytes(int64(size))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ domBenchRes = dominators(fun.f)
+ }
+}
+
+type domFunc func(f *Func) []*Block
+
+// verifyDominators verifies that the dominators of fut (function under test)
+// as determined by domFn, match the map node->dominator
+func verifyDominators(t *testing.T, fut fun, domFn domFunc, doms map[string]string) {
+ blockNames := map[*Block]string{}
+ for n, b := range fut.blocks {
+ blockNames[b] = n
+ }
+
+ calcDom := domFn(fut.f)
+
+ for n, d := range doms {
+ nblk, ok := fut.blocks[n]
+ if !ok {
+ t.Errorf("invalid block name %s", n)
+ }
+ dblk, ok := fut.blocks[d]
+ if !ok {
+ t.Errorf("invalid block name %s", d)
+ }
+
+ domNode := calcDom[nblk.ID]
+ switch {
+ case calcDom[nblk.ID] == dblk:
+ calcDom[nblk.ID] = nil
+ continue
+ case calcDom[nblk.ID] != dblk:
+ t.Errorf("expected %s as dominator of %s, found %s", d, n, blockNames[domNode])
+ default:
+ t.Fatal("unexpected dominator condition")
+ }
+ }
+
+ for id, d := range calcDom {
+ // If nil, we've already verified it
+ if d == nil {
+ continue
+ }
+ for _, b := range fut.blocks {
+ if int(b.ID) == id {
+ t.Errorf("unexpected dominator of %s for %s", blockNames[d], blockNames[b])
+ }
+ }
+ }
+
+}
+
+func TestDominatorsSingleBlock(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Exit("mem")))
+
+ doms := map[string]string{}
+
+ CheckFunc(fun.f)
+ verifyDominators(t, fun, dominators, doms)
+ verifyDominators(t, fun, dominatorsSimple, doms)
+
+}
+
+func TestDominatorsSimple(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Goto("a")),
+ Bloc("a",
+ Goto("b")),
+ Bloc("b",
+ Goto("c")),
+ Bloc("c",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ doms := map[string]string{
+ "a": "entry",
+ "b": "a",
+ "c": "b",
+ "exit": "c",
+ }
+
+ CheckFunc(fun.f)
+ verifyDominators(t, fun, dominators, doms)
+ verifyDominators(t, fun, dominatorsSimple, doms)
+
+}
+
+func TestDominatorsMultPredFwd(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ If("p", "a", "c")),
+ Bloc("a",
+ If("p", "b", "c")),
+ Bloc("b",
+ Goto("c")),
+ Bloc("c",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ doms := map[string]string{
+ "a": "entry",
+ "b": "a",
+ "c": "entry",
+ "exit": "c",
+ }
+
+ CheckFunc(fun.f)
+ verifyDominators(t, fun, dominators, doms)
+ verifyDominators(t, fun, dominatorsSimple, doms)
+}
+
+func TestDominatorsDeadCode(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 0, nil),
+ If("p", "b3", "b5")),
+ Bloc("b2", Exit("mem")),
+ Bloc("b3", Goto("b2")),
+ Bloc("b4", Goto("b2")),
+ Bloc("b5", Goto("b2")))
+
+ doms := map[string]string{
+ "b2": "entry",
+ "b3": "entry",
+ "b5": "entry",
+ }
+
+ CheckFunc(fun.f)
+ verifyDominators(t, fun, dominators, doms)
+ verifyDominators(t, fun, dominatorsSimple, doms)
+}
+
+func TestDominatorsMultPredRev(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Goto("first")),
+ Bloc("first",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ Goto("a")),
+ Bloc("a",
+ If("p", "b", "first")),
+ Bloc("b",
+ Goto("c")),
+ Bloc("c",
+ If("p", "exit", "b")),
+ Bloc("exit",
+ Exit("mem")))
+
+ doms := map[string]string{
+ "first": "entry",
+ "a": "first",
+ "b": "a",
+ "c": "b",
+ "exit": "c",
+ }
+
+ CheckFunc(fun.f)
+ verifyDominators(t, fun, dominators, doms)
+ verifyDominators(t, fun, dominatorsSimple, doms)
+}
+
+func TestDominatorsMultPred(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ If("p", "a", "c")),
+ Bloc("a",
+ If("p", "b", "c")),
+ Bloc("b",
+ Goto("c")),
+ Bloc("c",
+ If("p", "b", "exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ doms := map[string]string{
+ "a": "entry",
+ "b": "entry",
+ "c": "entry",
+ "exit": "c",
+ }
+
+ CheckFunc(fun.f)
+ verifyDominators(t, fun, dominators, doms)
+ verifyDominators(t, fun, dominatorsSimple, doms)
+}
+
+func TestInfiniteLoop(t *testing.T) {
+ c := testConfig(t)
+ // note lack of an exit block
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ Goto("a")),
+ Bloc("a",
+ Goto("b")),
+ Bloc("b",
+ Goto("a")))
+
+ CheckFunc(fun.f)
+ doms := map[string]string{"a": "entry",
+ "b": "a"}
+ verifyDominators(t, fun, dominators, doms)
+}
+
+func TestDomTricky(t *testing.T) {
+ doms := map[string]string{
+ "4": "1",
+ "2": "4",
+ "5": "4",
+ "11": "4",
+ "15": "4", // the incorrect answer is "5"
+ "10": "15",
+ "19": "15",
+ }
+
+ if4 := [2]string{"2", "5"}
+ if5 := [2]string{"15", "11"}
+ if15 := [2]string{"19", "10"}
+
+ for i := 0; i < 8; i++ {
+ a := 1 & i
+ b := 1 & i >> 1
+ c := 1 & i >> 2
+
+ cfg := testConfig(t)
+ fun := cfg.Fun("1",
+ Bloc("1",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ Goto("4")),
+ Bloc("2",
+ Goto("11")),
+ Bloc("4",
+ If("p", if4[a], if4[1-a])), // 2, 5
+ Bloc("5",
+ If("p", if5[b], if5[1-b])), //15, 11
+ Bloc("10",
+ Exit("mem")),
+ Bloc("11",
+ Goto("15")),
+ Bloc("15",
+ If("p", if15[c], if15[1-c])), //19, 10
+ Bloc("19",
+ Goto("10")))
+ CheckFunc(fun.f)
+ verifyDominators(t, fun, dominators, doms)
+ verifyDominators(t, fun, dominatorsSimple, doms)
+ }
+}
+
+// generateDominatorMap uses dominatorsSimple to obtain a
+// reference dominator tree for testing faster algorithms.
+func generateDominatorMap(fut fun) map[string]string {
+ blockNames := map[*Block]string{}
+ for n, b := range fut.blocks {
+ blockNames[b] = n
+ }
+ referenceDom := dominatorsSimple(fut.f)
+ doms := make(map[string]string)
+ for _, b := range fut.f.Blocks {
+ if d := referenceDom[b.ID]; d != nil {
+ doms[blockNames[b]] = blockNames[d]
+ }
+ }
+ return doms
+}
+
+func TestDominatorsPostTrickyA(t *testing.T) {
+ testDominatorsPostTricky(t, "b8", "b11", "b10", "b8", "b14", "b15")
+}
+
+func TestDominatorsPostTrickyB(t *testing.T) {
+ testDominatorsPostTricky(t, "b11", "b8", "b10", "b8", "b14", "b15")
+}
+
+func TestDominatorsPostTrickyC(t *testing.T) {
+ testDominatorsPostTricky(t, "b8", "b11", "b8", "b10", "b14", "b15")
+}
+
+func TestDominatorsPostTrickyD(t *testing.T) {
+ testDominatorsPostTricky(t, "b11", "b8", "b8", "b10", "b14", "b15")
+}
+
+func TestDominatorsPostTrickyE(t *testing.T) {
+ testDominatorsPostTricky(t, "b8", "b11", "b10", "b8", "b15", "b14")
+}
+
+func TestDominatorsPostTrickyF(t *testing.T) {
+ testDominatorsPostTricky(t, "b11", "b8", "b10", "b8", "b15", "b14")
+}
+
+func TestDominatorsPostTrickyG(t *testing.T) {
+ testDominatorsPostTricky(t, "b8", "b11", "b8", "b10", "b15", "b14")
+}
+
+func TestDominatorsPostTrickyH(t *testing.T) {
+ testDominatorsPostTricky(t, "b11", "b8", "b8", "b10", "b15", "b14")
+}
+
+func testDominatorsPostTricky(t *testing.T, b7then, b7else, b12then, b12else, b13then, b13else string) {
+ c := testConfig(t)
+ fun := c.Fun("b1",
+ Bloc("b1",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("p", OpConstBool, types.Types[types.TBOOL], 1, nil),
+ If("p", "b3", "b2")),
+ Bloc("b3",
+ If("p", "b5", "b6")),
+ Bloc("b5",
+ Goto("b7")),
+ Bloc("b7",
+ If("p", b7then, b7else)),
+ Bloc("b8",
+ Goto("b13")),
+ Bloc("b13",
+ If("p", b13then, b13else)),
+ Bloc("b14",
+ Goto("b10")),
+ Bloc("b15",
+ Goto("b16")),
+ Bloc("b16",
+ Goto("b9")),
+ Bloc("b9",
+ Goto("b7")),
+ Bloc("b11",
+ Goto("b12")),
+ Bloc("b12",
+ If("p", b12then, b12else)),
+ Bloc("b10",
+ Goto("b6")),
+ Bloc("b6",
+ Goto("b17")),
+ Bloc("b17",
+ Goto("b18")),
+ Bloc("b18",
+ If("p", "b22", "b19")),
+ Bloc("b22",
+ Goto("b23")),
+ Bloc("b23",
+ If("p", "b21", "b19")),
+ Bloc("b19",
+ If("p", "b24", "b25")),
+ Bloc("b24",
+ Goto("b26")),
+ Bloc("b26",
+ Goto("b25")),
+ Bloc("b25",
+ If("p", "b27", "b29")),
+ Bloc("b27",
+ Goto("b30")),
+ Bloc("b30",
+ Goto("b28")),
+ Bloc("b29",
+ Goto("b31")),
+ Bloc("b31",
+ Goto("b28")),
+ Bloc("b28",
+ If("p", "b32", "b33")),
+ Bloc("b32",
+ Goto("b21")),
+ Bloc("b21",
+ Goto("b47")),
+ Bloc("b47",
+ If("p", "b45", "b46")),
+ Bloc("b45",
+ Goto("b48")),
+ Bloc("b48",
+ Goto("b49")),
+ Bloc("b49",
+ If("p", "b50", "b51")),
+ Bloc("b50",
+ Goto("b52")),
+ Bloc("b52",
+ Goto("b53")),
+ Bloc("b53",
+ Goto("b51")),
+ Bloc("b51",
+ Goto("b54")),
+ Bloc("b54",
+ Goto("b46")),
+ Bloc("b46",
+ Exit("mem")),
+ Bloc("b33",
+ Goto("b34")),
+ Bloc("b34",
+ Goto("b37")),
+ Bloc("b37",
+ If("p", "b35", "b36")),
+ Bloc("b35",
+ Goto("b38")),
+ Bloc("b38",
+ Goto("b39")),
+ Bloc("b39",
+ If("p", "b40", "b41")),
+ Bloc("b40",
+ Goto("b42")),
+ Bloc("b42",
+ Goto("b43")),
+ Bloc("b43",
+ Goto("b41")),
+ Bloc("b41",
+ Goto("b44")),
+ Bloc("b44",
+ Goto("b36")),
+ Bloc("b36",
+ Goto("b20")),
+ Bloc("b20",
+ Goto("b18")),
+ Bloc("b2",
+ Goto("b4")),
+ Bloc("b4",
+ Exit("mem")))
+ CheckFunc(fun.f)
+ doms := generateDominatorMap(fun)
+ verifyDominators(t, fun, dominators, doms)
+}
diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go
new file mode 100644
index 0000000..679ee8a
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/expand_calls.go
@@ -0,0 +1,975 @@
+// Copyright 2020 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 (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "fmt"
+ "sort"
+)
+
+type selKey struct {
+ from *Value
+ offset int64
+ size int64
+ typ *types.Type
+}
+
+type offsetKey struct {
+ from *Value
+ offset int64
+ pt *types.Type
+}
+
+// expandCalls converts LE (Late Expansion) calls that act like they receive value args into a lower-level form
+// that is more oriented to a platform's ABI. The SelectN operations that extract results are rewritten into
+// more appropriate forms, and any StructMake or ArrayMake inputs are decomposed until non-struct values are
+// reached. On the callee side, OpArg nodes are not decomposed until this phase is run.
+// TODO results should not be lowered until this phase.
+func expandCalls(f *Func) {
+ // Calls that need lowering have some number of inputs, including a memory input,
+ // and produce a tuple of (value1, value2, ..., mem) where valueK may or may not be SSA-able.
+
+ // With the current ABI those inputs need to be converted into stores to memory,
+ // rethreading the call's memory input to the first, and the new call now receiving the last.
+
+ // With the current ABI, the outputs need to be converted to loads, which will all use the call's
+ // memory output as their input.
+ if !LateCallExpansionEnabledWithin(f) {
+ return
+ }
+ debug := f.pass.debug > 0
+
+ if debug {
+ fmt.Printf("\nexpandsCalls(%s)\n", f.Name)
+ }
+
+ canSSAType := f.fe.CanSSA
+ regSize := f.Config.RegSize
+ sp, _ := f.spSb()
+ typ := &f.Config.Types
+ ptrSize := f.Config.PtrSize
+
+ // For 32-bit, need to deal with decomposition of 64-bit integers, which depends on endianness.
+ var hiOffset, lowOffset int64
+ if f.Config.BigEndian {
+ lowOffset = 4
+ } else {
+ hiOffset = 4
+ }
+
+ namedSelects := make(map[*Value][]namedVal)
+
+ sdom := f.Sdom()
+
+ common := make(map[selKey]*Value)
+
+ // intPairTypes returns the pair of 32-bit int types needed to encode a 64-bit integer type on a target
+ // that has no 64-bit integer registers.
+ intPairTypes := func(et types.EType) (tHi, tLo *types.Type) {
+ tHi = typ.UInt32
+ if et == types.TINT64 {
+ tHi = typ.Int32
+ }
+ tLo = typ.UInt32
+ return
+ }
+
+ // isAlreadyExpandedAggregateType returns whether a type is an SSA-able "aggregate" (multiple register) type
+ // that was expanded in an earlier phase (currently, expand_calls is intended to run after decomposeBuiltin,
+ // so this is all aggregate types -- small struct and array, complex, interface, string, slice, and 64-bit
+ // integer on 32-bit).
+ isAlreadyExpandedAggregateType := func(t *types.Type) bool {
+ if !canSSAType(t) {
+ return false
+ }
+ return t.IsStruct() || t.IsArray() || t.IsComplex() || t.IsInterface() || t.IsString() || t.IsSlice() ||
+ t.Size() > regSize && t.IsInteger()
+ }
+
+ offsets := make(map[offsetKey]*Value)
+
+ // offsetFrom creates an offset from a pointer, simplifying chained offsets and offsets from SP
+ // TODO should also optimize offsets from SB?
+ offsetFrom := func(from *Value, offset int64, pt *types.Type) *Value {
+ if offset == 0 && from.Type == pt { // this is not actually likely
+ return from
+ }
+ // Simplify, canonicalize
+ for from.Op == OpOffPtr {
+ offset += from.AuxInt
+ from = from.Args[0]
+ }
+ if from == sp {
+ return f.ConstOffPtrSP(pt, offset, sp)
+ }
+ key := offsetKey{from, offset, pt}
+ v := offsets[key]
+ if v != nil {
+ return v
+ }
+ v = from.Block.NewValue1I(from.Pos.WithNotStmt(), OpOffPtr, pt, offset, from)
+ offsets[key] = v
+ return v
+ }
+
+ // splitSlots splits one "field" (specified by sfx, offset, and ty) out of the LocalSlots in ls and returns the new LocalSlots this generates.
+ splitSlots := func(ls []LocalSlot, sfx string, offset int64, ty *types.Type) []LocalSlot {
+ var locs []LocalSlot
+ for i := range ls {
+ locs = append(locs, f.fe.SplitSlot(&ls[i], sfx, offset, ty))
+ }
+ return locs
+ }
+
+ // removeTrivialWrapperTypes unwraps layers of
+ // struct { singleField SomeType } and [1]SomeType
+ // until a non-wrapper type is reached. This is useful
+ // for working with assignments to/from interface data
+ // fields (either second operand to OpIMake or OpIData)
+ // where the wrapping or type conversion can be elided
+ // because of type conversions/assertions in source code
+ // that do not appear in SSA.
+ removeTrivialWrapperTypes := func(t *types.Type) *types.Type {
+ for {
+ if t.IsStruct() && t.NumFields() == 1 {
+ t = t.Field(0).Type
+ continue
+ }
+ if t.IsArray() && t.NumElem() == 1 {
+ t = t.Elem()
+ continue
+ }
+ break
+ }
+ return t
+ }
+
+ // Calls that need lowering have some number of inputs, including a memory input,
+ // and produce a tuple of (value1, value2, ..., mem) where valueK may or may not be SSA-able.
+
+ // With the current ABI those inputs need to be converted into stores to memory,
+ // rethreading the call's memory input to the first, and the new call now receiving the last.
+
+ // With the current ABI, the outputs need to be converted to loads, which will all use the call's
+ // memory output as their input.
+
+ // rewriteSelect recursively walks from leaf selector to a root (OpSelectN, OpLoad, OpArg)
+ // through a chain of Struct/Array/builtin Select operations. If the chain of selectors does not
+ // end in an expected root, it does nothing (this can happen depending on compiler phase ordering).
+ // The "leaf" provides the type, the root supplies the container, and the leaf-to-root path
+ // accumulates the offset.
+ // It emits the code necessary to implement the leaf select operation that leads to the root.
+ //
+ // TODO when registers really arrive, must also decompose anything split across two registers or registers and memory.
+ var rewriteSelect func(leaf *Value, selector *Value, offset int64) []LocalSlot
+ rewriteSelect = func(leaf *Value, selector *Value, offset int64) []LocalSlot {
+ if debug {
+ fmt.Printf("rewriteSelect(%s, %s, %d)\n", leaf.LongString(), selector.LongString(), offset)
+ }
+ var locs []LocalSlot
+ leafType := leaf.Type
+ if len(selector.Args) > 0 {
+ w := selector.Args[0]
+ if w.Op == OpCopy {
+ for w.Op == OpCopy {
+ w = w.Args[0]
+ }
+ selector.SetArg(0, w)
+ }
+ }
+ switch selector.Op {
+ case OpArg:
+ if !isAlreadyExpandedAggregateType(selector.Type) {
+ if leafType == selector.Type { // OpIData leads us here, sometimes.
+ leaf.copyOf(selector)
+ } else {
+ f.Fatalf("Unexpected OpArg type, selector=%s, leaf=%s\n", selector.LongString(), leaf.LongString())
+ }
+ if debug {
+ fmt.Printf("\tOpArg, break\n")
+ }
+ break
+ }
+ switch leaf.Op {
+ case OpIData, OpStructSelect, OpArraySelect:
+ leafType = removeTrivialWrapperTypes(leaf.Type)
+ }
+ aux := selector.Aux
+ auxInt := selector.AuxInt + offset
+ if leaf.Block == selector.Block {
+ leaf.reset(OpArg)
+ leaf.Aux = aux
+ leaf.AuxInt = auxInt
+ leaf.Type = leafType
+ } else {
+ w := selector.Block.NewValue0IA(leaf.Pos, OpArg, leafType, auxInt, aux)
+ leaf.copyOf(w)
+ if debug {
+ fmt.Printf("\tnew %s\n", w.LongString())
+ }
+ }
+ for _, s := range namedSelects[selector] {
+ locs = append(locs, f.Names[s.locIndex])
+ }
+
+ case OpLoad: // We end up here because of IData of immediate structures.
+ // Failure case:
+ // (note the failure case is very rare; w/o this case, make.bash and run.bash both pass, as well as
+ // the hard cases of building {syscall,math,math/cmplx,math/bits,go/constant} on ppc64le and mips-softfloat).
+ //
+ // GOSSAFUNC='(*dumper).dump' go build -gcflags=-l -tags=math_big_pure_go cmd/compile/internal/gc
+ // cmd/compile/internal/gc/dump.go:136:14: internal compiler error: '(*dumper).dump': not lowered: v827, StructSelect PTR PTR
+ // b2: ← b1
+ // v20 (+142) = StaticLECall <interface {},mem> {AuxCall{reflect.Value.Interface([reflect.Value,0])[interface {},24]}} [40] v8 v1
+ // v21 (142) = SelectN <mem> [1] v20
+ // v22 (142) = SelectN <interface {}> [0] v20
+ // b15: ← b8
+ // v71 (+143) = IData <Nodes> v22 (v[Nodes])
+ // v73 (+146) = StaticLECall <[]*Node,mem> {AuxCall{"".Nodes.Slice([Nodes,0])[[]*Node,8]}} [32] v71 v21
+ //
+ // translates (w/o the "case OpLoad:" above) to:
+ //
+ // b2: ← b1
+ // v20 (+142) = StaticCall <mem> {AuxCall{reflect.Value.Interface([reflect.Value,0])[interface {},24]}} [40] v715
+ // v23 (142) = Load <*uintptr> v19 v20
+ // v823 (142) = IsNonNil <bool> v23
+ // v67 (+143) = Load <*[]*Node> v880 v20
+ // b15: ← b8
+ // v827 (146) = StructSelect <*[]*Node> [0] v67
+ // v846 (146) = Store <mem> {*[]*Node} v769 v827 v20
+ // v73 (+146) = StaticCall <mem> {AuxCall{"".Nodes.Slice([Nodes,0])[[]*Node,8]}} [32] v846
+ // i.e., the struct select is generated and remains in because it is not applied to an actual structure.
+ // The OpLoad was created to load the single field of the IData
+ // This case removes that StructSelect.
+ if leafType != selector.Type {
+ f.Fatalf("Unexpected Load as selector, leaf=%s, selector=%s\n", leaf.LongString(), selector.LongString())
+ }
+ leaf.copyOf(selector)
+ for _, s := range namedSelects[selector] {
+ locs = append(locs, f.Names[s.locIndex])
+ }
+
+ case OpSelectN:
+ // TODO these may be duplicated. Should memoize. Intermediate selectors will go dead, no worries there.
+ call := selector.Args[0]
+ aux := call.Aux.(*AuxCall)
+ which := selector.AuxInt
+ if which == aux.NResults() { // mem is after the results.
+ // rewrite v as a Copy of call -- the replacement call will produce a mem.
+ leaf.copyOf(call)
+ } else {
+ leafType := removeTrivialWrapperTypes(leaf.Type)
+ if canSSAType(leafType) {
+ pt := types.NewPtr(leafType)
+ off := offsetFrom(sp, offset+aux.OffsetOfResult(which), pt)
+ // Any selection right out of the arg area/registers has to be same Block as call, use call as mem input.
+ if leaf.Block == call.Block {
+ leaf.reset(OpLoad)
+ leaf.SetArgs2(off, call)
+ leaf.Type = leafType
+ } else {
+ w := call.Block.NewValue2(leaf.Pos, OpLoad, leafType, off, call)
+ leaf.copyOf(w)
+ if debug {
+ fmt.Printf("\tnew %s\n", w.LongString())
+ }
+ }
+ for _, s := range namedSelects[selector] {
+ locs = append(locs, f.Names[s.locIndex])
+ }
+ } else {
+ f.Fatalf("Should not have non-SSA-able OpSelectN, selector=%s", selector.LongString())
+ }
+ }
+
+ case OpStructSelect:
+ w := selector.Args[0]
+ var ls []LocalSlot
+ if w.Type.Etype != types.TSTRUCT { // IData artifact
+ ls = rewriteSelect(leaf, w, offset)
+ } else {
+ ls = rewriteSelect(leaf, w, offset+w.Type.FieldOff(int(selector.AuxInt)))
+ if w.Op != OpIData {
+ for _, l := range ls {
+ locs = append(locs, f.fe.SplitStruct(l, int(selector.AuxInt)))
+ }
+ }
+ }
+
+ case OpArraySelect:
+ w := selector.Args[0]
+ rewriteSelect(leaf, w, offset+selector.Type.Size()*selector.AuxInt)
+
+ case OpInt64Hi:
+ w := selector.Args[0]
+ ls := rewriteSelect(leaf, w, offset+hiOffset)
+ locs = splitSlots(ls, ".hi", hiOffset, leafType)
+
+ case OpInt64Lo:
+ w := selector.Args[0]
+ ls := rewriteSelect(leaf, w, offset+lowOffset)
+ locs = splitSlots(ls, ".lo", lowOffset, leafType)
+
+ case OpStringPtr:
+ ls := rewriteSelect(leaf, selector.Args[0], offset)
+ locs = splitSlots(ls, ".ptr", 0, typ.BytePtr)
+
+ case OpSlicePtr:
+ w := selector.Args[0]
+ ls := rewriteSelect(leaf, w, offset)
+ locs = splitSlots(ls, ".ptr", 0, types.NewPtr(w.Type.Elem()))
+
+ case OpITab:
+ w := selector.Args[0]
+ ls := rewriteSelect(leaf, w, offset)
+ sfx := ".itab"
+ if w.Type.IsEmptyInterface() {
+ sfx = ".type"
+ }
+ locs = splitSlots(ls, sfx, 0, typ.Uintptr)
+
+ case OpComplexReal:
+ ls := rewriteSelect(leaf, selector.Args[0], offset)
+ locs = splitSlots(ls, ".real", 0, leafType)
+
+ case OpComplexImag:
+ ls := rewriteSelect(leaf, selector.Args[0], offset+leafType.Width) // result is FloatNN, width of result is offset of imaginary part.
+ locs = splitSlots(ls, ".imag", leafType.Width, leafType)
+
+ case OpStringLen, OpSliceLen:
+ ls := rewriteSelect(leaf, selector.Args[0], offset+ptrSize)
+ locs = splitSlots(ls, ".len", ptrSize, leafType)
+
+ case OpIData:
+ ls := rewriteSelect(leaf, selector.Args[0], offset+ptrSize)
+ locs = splitSlots(ls, ".data", ptrSize, leafType)
+
+ case OpSliceCap:
+ ls := rewriteSelect(leaf, selector.Args[0], offset+2*ptrSize)
+ locs = splitSlots(ls, ".cap", 2*ptrSize, leafType)
+
+ case OpCopy: // If it's an intermediate result, recurse
+ locs = rewriteSelect(leaf, selector.Args[0], offset)
+ for _, s := range namedSelects[selector] {
+ // this copy may have had its own name, preserve that, too.
+ locs = append(locs, f.Names[s.locIndex])
+ }
+
+ default:
+ // Ignore dead ends. These can occur if this phase is run before decompose builtin (which is not intended, but allowed).
+ }
+
+ return locs
+ }
+
+ // storeArgOrLoad converts stores of SSA-able aggregate arguments (passed to a call) into a series of primitive-typed
+ // stores of non-aggregate types. It recursively walks up a chain of selectors until it reaches a Load or an Arg.
+ // If it does not reach a Load or an Arg, nothing happens; this allows a little freedom in phase ordering.
+ var storeArgOrLoad func(pos src.XPos, b *Block, base, source, mem *Value, t *types.Type, offset int64) *Value
+
+ // decomposeArgOrLoad is a helper for storeArgOrLoad.
+ // It decomposes a Load or an Arg into smaller parts, parameterized by the decomposeOne and decomposeTwo functions
+ // passed to it, and returns the new mem. If the type does not match one of the expected aggregate types, it returns nil instead.
+ decomposeArgOrLoad := func(pos src.XPos, b *Block, base, source, mem *Value, t *types.Type, offset int64,
+ decomposeOne func(pos src.XPos, b *Block, base, source, mem *Value, t1 *types.Type, offArg, offStore int64) *Value,
+ decomposeTwo func(pos src.XPos, b *Block, base, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64) *Value) *Value {
+ u := source.Type
+ switch u.Etype {
+ case types.TARRAY:
+ elem := u.Elem()
+ for i := int64(0); i < u.NumElem(); i++ {
+ elemOff := i * elem.Size()
+ mem = decomposeOne(pos, b, base, source, mem, elem, source.AuxInt+elemOff, offset+elemOff)
+ pos = pos.WithNotStmt()
+ }
+ return mem
+ case types.TSTRUCT:
+ for i := 0; i < u.NumFields(); i++ {
+ fld := u.Field(i)
+ mem = decomposeOne(pos, b, base, source, mem, fld.Type, source.AuxInt+fld.Offset, offset+fld.Offset)
+ pos = pos.WithNotStmt()
+ }
+ return mem
+ case types.TINT64, types.TUINT64:
+ if t.Width == regSize {
+ break
+ }
+ tHi, tLo := intPairTypes(t.Etype)
+ mem = decomposeOne(pos, b, base, source, mem, tHi, source.AuxInt+hiOffset, offset+hiOffset)
+ pos = pos.WithNotStmt()
+ return decomposeOne(pos, b, base, source, mem, tLo, source.AuxInt+lowOffset, offset+lowOffset)
+ case types.TINTER:
+ return decomposeTwo(pos, b, base, source, mem, typ.Uintptr, typ.BytePtr, source.AuxInt, offset)
+ case types.TSTRING:
+ return decomposeTwo(pos, b, base, source, mem, typ.BytePtr, typ.Int, source.AuxInt, offset)
+ case types.TCOMPLEX64:
+ return decomposeTwo(pos, b, base, source, mem, typ.Float32, typ.Float32, source.AuxInt, offset)
+ case types.TCOMPLEX128:
+ return decomposeTwo(pos, b, base, source, mem, typ.Float64, typ.Float64, source.AuxInt, offset)
+ case types.TSLICE:
+ mem = decomposeTwo(pos, b, base, source, mem, typ.BytePtr, typ.Int, source.AuxInt, offset)
+ return decomposeOne(pos, b, base, source, mem, typ.Int, source.AuxInt+2*ptrSize, offset+2*ptrSize)
+ }
+ return nil
+ }
+
+ // storeOneArg creates a decomposed (one step) arg that is then stored.
+ // pos and b locate the store instruction, base is the base of the store target, source is the "base" of the value input,
+ // mem is the input mem, t is the type in question, and offArg and offStore are the offsets from the respective bases.
+ storeOneArg := func(pos src.XPos, b *Block, base, source, mem *Value, t *types.Type, offArg, offStore int64) *Value {
+ w := common[selKey{source, offArg, t.Width, t}]
+ if w == nil {
+ w = source.Block.NewValue0IA(source.Pos, OpArg, t, offArg, source.Aux)
+ common[selKey{source, offArg, t.Width, t}] = w
+ }
+ return storeArgOrLoad(pos, b, base, w, mem, t, offStore)
+ }
+
+ // storeOneLoad creates a decomposed (one step) load that is then stored.
+ storeOneLoad := func(pos src.XPos, b *Block, base, source, mem *Value, t *types.Type, offArg, offStore int64) *Value {
+ from := offsetFrom(source.Args[0], offArg, types.NewPtr(t))
+ w := source.Block.NewValue2(source.Pos, OpLoad, t, from, mem)
+ return storeArgOrLoad(pos, b, base, w, mem, t, offStore)
+ }
+
+ storeTwoArg := func(pos src.XPos, b *Block, base, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64) *Value {
+ mem = storeOneArg(pos, b, base, source, mem, t1, offArg, offStore)
+ pos = pos.WithNotStmt()
+ t1Size := t1.Size()
+ return storeOneArg(pos, b, base, source, mem, t2, offArg+t1Size, offStore+t1Size)
+ }
+
+ storeTwoLoad := func(pos src.XPos, b *Block, base, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64) *Value {
+ mem = storeOneLoad(pos, b, base, source, mem, t1, offArg, offStore)
+ pos = pos.WithNotStmt()
+ t1Size := t1.Size()
+ return storeOneLoad(pos, b, base, source, mem, t2, offArg+t1Size, offStore+t1Size)
+ }
+
+ storeArgOrLoad = func(pos src.XPos, b *Block, base, source, mem *Value, t *types.Type, offset int64) *Value {
+ if debug {
+ fmt.Printf("\tstoreArgOrLoad(%s; %s; %s; %s; %d)\n", base.LongString(), source.LongString(), mem.String(), t.String(), offset)
+ }
+
+ switch source.Op {
+ case OpCopy:
+ return storeArgOrLoad(pos, b, base, source.Args[0], mem, t, offset)
+
+ case OpLoad:
+ ret := decomposeArgOrLoad(pos, b, base, source, mem, t, offset, storeOneLoad, storeTwoLoad)
+ if ret != nil {
+ return ret
+ }
+
+ case OpArg:
+ ret := decomposeArgOrLoad(pos, b, base, source, mem, t, offset, storeOneArg, storeTwoArg)
+ if ret != nil {
+ return ret
+ }
+
+ case OpArrayMake0, OpStructMake0:
+ return mem
+
+ case OpStructMake1, OpStructMake2, OpStructMake3, OpStructMake4:
+ for i := 0; i < t.NumFields(); i++ {
+ fld := t.Field(i)
+ mem = storeArgOrLoad(pos, b, base, source.Args[i], mem, fld.Type, offset+fld.Offset)
+ pos = pos.WithNotStmt()
+ }
+ return mem
+
+ case OpArrayMake1:
+ return storeArgOrLoad(pos, b, base, source.Args[0], mem, t.Elem(), offset)
+
+ case OpInt64Make:
+ tHi, tLo := intPairTypes(t.Etype)
+ mem = storeArgOrLoad(pos, b, base, source.Args[0], mem, tHi, offset+hiOffset)
+ pos = pos.WithNotStmt()
+ return storeArgOrLoad(pos, b, base, source.Args[1], mem, tLo, offset+lowOffset)
+
+ case OpComplexMake:
+ tPart := typ.Float32
+ wPart := t.Width / 2
+ if wPart == 8 {
+ tPart = typ.Float64
+ }
+ mem = storeArgOrLoad(pos, b, base, source.Args[0], mem, tPart, offset)
+ pos = pos.WithNotStmt()
+ return storeArgOrLoad(pos, b, base, source.Args[1], mem, tPart, offset+wPart)
+
+ case OpIMake:
+ mem = storeArgOrLoad(pos, b, base, source.Args[0], mem, typ.Uintptr, offset)
+ pos = pos.WithNotStmt()
+ return storeArgOrLoad(pos, b, base, source.Args[1], mem, typ.BytePtr, offset+ptrSize)
+
+ case OpStringMake:
+ mem = storeArgOrLoad(pos, b, base, source.Args[0], mem, typ.BytePtr, offset)
+ pos = pos.WithNotStmt()
+ return storeArgOrLoad(pos, b, base, source.Args[1], mem, typ.Int, offset+ptrSize)
+
+ case OpSliceMake:
+ mem = storeArgOrLoad(pos, b, base, source.Args[0], mem, typ.BytePtr, offset)
+ pos = pos.WithNotStmt()
+ mem = storeArgOrLoad(pos, b, base, source.Args[1], mem, typ.Int, offset+ptrSize)
+ return storeArgOrLoad(pos, b, base, source.Args[2], mem, typ.Int, offset+2*ptrSize)
+ }
+
+ // For nodes that cannot be taken apart -- OpSelectN, other structure selectors.
+ switch t.Etype {
+ case types.TARRAY:
+ elt := t.Elem()
+ if source.Type != t && t.NumElem() == 1 && elt.Width == t.Width && t.Width == regSize {
+ t = removeTrivialWrapperTypes(t)
+ // it could be a leaf type, but the "leaf" could be complex64 (for example)
+ return storeArgOrLoad(pos, b, base, source, mem, t, offset)
+ }
+ for i := int64(0); i < t.NumElem(); i++ {
+ sel := source.Block.NewValue1I(pos, OpArraySelect, elt, i, source)
+ mem = storeArgOrLoad(pos, b, base, sel, mem, elt, offset+i*elt.Width)
+ pos = pos.WithNotStmt()
+ }
+ return mem
+
+ case types.TSTRUCT:
+ if source.Type != t && t.NumFields() == 1 && t.Field(0).Type.Width == t.Width && t.Width == regSize {
+ // This peculiar test deals with accesses to immediate interface data.
+ // It works okay because everything is the same size.
+ // Example code that triggers this can be found in go/constant/value.go, function ToComplex
+ // v119 (+881) = IData <intVal> v6
+ // v121 (+882) = StaticLECall <floatVal,mem> {AuxCall{"".itof([intVal,0])[floatVal,8]}} [16] v119 v1
+ // This corresponds to the generic rewrite rule "(StructSelect [0] (IData x)) => (IData x)"
+ // Guard against "struct{struct{*foo}}"
+ // Other rewriting phases create minor glitches when they transform IData, for instance the
+ // interface-typed Arg "x" of ToFloat in go/constant/value.go
+ // v6 (858) = Arg <Value> {x} (x[Value], x[Value])
+ // is rewritten by decomposeArgs into
+ // v141 (858) = Arg <uintptr> {x}
+ // v139 (858) = Arg <*uint8> {x} [8]
+ // because of a type case clause on line 862 of go/constant/value.go
+ // case intVal:
+ // return itof(x)
+ // v139 is later stored as an intVal == struct{val *big.Int} which naively requires the fields of
+ // of a *uint8, which does not succeed.
+ t = removeTrivialWrapperTypes(t)
+ // it could be a leaf type, but the "leaf" could be complex64 (for example)
+ return storeArgOrLoad(pos, b, base, source, mem, t, offset)
+ }
+
+ for i := 0; i < t.NumFields(); i++ {
+ fld := t.Field(i)
+ sel := source.Block.NewValue1I(pos, OpStructSelect, fld.Type, int64(i), source)
+ mem = storeArgOrLoad(pos, b, base, sel, mem, fld.Type, offset+fld.Offset)
+ pos = pos.WithNotStmt()
+ }
+ return mem
+
+ case types.TINT64, types.TUINT64:
+ if t.Width == regSize {
+ break
+ }
+ tHi, tLo := intPairTypes(t.Etype)
+ sel := source.Block.NewValue1(pos, OpInt64Hi, tHi, source)
+ mem = storeArgOrLoad(pos, b, base, sel, mem, tHi, offset+hiOffset)
+ pos = pos.WithNotStmt()
+ sel = source.Block.NewValue1(pos, OpInt64Lo, tLo, source)
+ return storeArgOrLoad(pos, b, base, sel, mem, tLo, offset+lowOffset)
+
+ case types.TINTER:
+ sel := source.Block.NewValue1(pos, OpITab, typ.BytePtr, source)
+ mem = storeArgOrLoad(pos, b, base, sel, mem, typ.BytePtr, offset)
+ pos = pos.WithNotStmt()
+ sel = source.Block.NewValue1(pos, OpIData, typ.BytePtr, source)
+ return storeArgOrLoad(pos, b, base, sel, mem, typ.BytePtr, offset+ptrSize)
+
+ case types.TSTRING:
+ sel := source.Block.NewValue1(pos, OpStringPtr, typ.BytePtr, source)
+ mem = storeArgOrLoad(pos, b, base, sel, mem, typ.BytePtr, offset)
+ pos = pos.WithNotStmt()
+ sel = source.Block.NewValue1(pos, OpStringLen, typ.Int, source)
+ return storeArgOrLoad(pos, b, base, sel, mem, typ.Int, offset+ptrSize)
+
+ case types.TSLICE:
+ et := types.NewPtr(t.Elem())
+ sel := source.Block.NewValue1(pos, OpSlicePtr, et, source)
+ mem = storeArgOrLoad(pos, b, base, sel, mem, et, offset)
+ pos = pos.WithNotStmt()
+ sel = source.Block.NewValue1(pos, OpSliceLen, typ.Int, source)
+ mem = storeArgOrLoad(pos, b, base, sel, mem, typ.Int, offset+ptrSize)
+ sel = source.Block.NewValue1(pos, OpSliceCap, typ.Int, source)
+ return storeArgOrLoad(pos, b, base, sel, mem, typ.Int, offset+2*ptrSize)
+
+ case types.TCOMPLEX64:
+ sel := source.Block.NewValue1(pos, OpComplexReal, typ.Float32, source)
+ mem = storeArgOrLoad(pos, b, base, sel, mem, typ.Float32, offset)
+ pos = pos.WithNotStmt()
+ sel = source.Block.NewValue1(pos, OpComplexImag, typ.Float32, source)
+ return storeArgOrLoad(pos, b, base, sel, mem, typ.Float32, offset+4)
+
+ case types.TCOMPLEX128:
+ sel := source.Block.NewValue1(pos, OpComplexReal, typ.Float64, source)
+ mem = storeArgOrLoad(pos, b, base, sel, mem, typ.Float64, offset)
+ pos = pos.WithNotStmt()
+ sel = source.Block.NewValue1(pos, OpComplexImag, typ.Float64, source)
+ return storeArgOrLoad(pos, b, base, sel, mem, typ.Float64, offset+8)
+ }
+
+ dst := offsetFrom(base, offset, types.NewPtr(t))
+ x := b.NewValue3A(pos, OpStore, types.TypeMem, t, dst, source, mem)
+ if debug {
+ fmt.Printf("\t\tstoreArg returns %s\n", x.LongString())
+ }
+ return x
+ }
+
+ // rewriteArgs removes all the Args from a call and converts the call args into appropriate
+ // stores (or later, register movement). Extra args for interface and closure calls are ignored,
+ // but removed.
+ rewriteArgs := func(v *Value, firstArg int) *Value {
+ // Thread the stores on the memory arg
+ aux := v.Aux.(*AuxCall)
+ pos := v.Pos.WithNotStmt()
+ m0 := v.Args[len(v.Args)-1]
+ mem := m0
+ for i, a := range v.Args {
+ if i < firstArg {
+ continue
+ }
+ if a == m0 { // mem is last.
+ break
+ }
+ auxI := int64(i - firstArg)
+ if a.Op == OpDereference {
+ if a.MemoryArg() != m0 {
+ f.Fatalf("Op...LECall and OpDereference have mismatched mem, %s and %s", v.LongString(), a.LongString())
+ }
+ // "Dereference" of addressed (probably not-SSA-eligible) value becomes Move
+ // TODO this will be more complicated with registers in the picture.
+ source := a.Args[0]
+ dst := f.ConstOffPtrSP(source.Type, aux.OffsetOfArg(auxI), sp)
+ if a.Uses == 1 && a.Block == v.Block {
+ a.reset(OpMove)
+ a.Pos = pos
+ a.Type = types.TypeMem
+ a.Aux = aux.TypeOfArg(auxI)
+ a.AuxInt = aux.SizeOfArg(auxI)
+ a.SetArgs3(dst, source, mem)
+ mem = a
+ } else {
+ mem = v.Block.NewValue3A(pos, OpMove, types.TypeMem, aux.TypeOfArg(auxI), dst, source, mem)
+ mem.AuxInt = aux.SizeOfArg(auxI)
+ }
+ } else {
+ if debug {
+ fmt.Printf("storeArg %s, %v, %d\n", a.LongString(), aux.TypeOfArg(auxI), aux.OffsetOfArg(auxI))
+ }
+ mem = storeArgOrLoad(pos, v.Block, sp, a, mem, aux.TypeOfArg(auxI), aux.OffsetOfArg(auxI))
+ }
+ }
+ v.resetArgs()
+ return mem
+ }
+
+ // TODO if too slow, whole program iteration can be replaced w/ slices of appropriate values, accumulated in first loop here.
+
+ // Step 0: rewrite the calls to convert incoming args to stores.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ switch v.Op {
+ case OpStaticLECall:
+ mem := rewriteArgs(v, 0)
+ v.SetArgs1(mem)
+ case OpClosureLECall:
+ code := v.Args[0]
+ context := v.Args[1]
+ mem := rewriteArgs(v, 2)
+ v.SetArgs3(code, context, mem)
+ case OpInterLECall:
+ code := v.Args[0]
+ mem := rewriteArgs(v, 1)
+ v.SetArgs2(code, mem)
+ }
+ }
+ }
+
+ for i, name := range f.Names {
+ t := name.Type
+ if isAlreadyExpandedAggregateType(t) {
+ for j, v := range f.NamedValues[name] {
+ if v.Op == OpSelectN || v.Op == OpArg && isAlreadyExpandedAggregateType(v.Type) {
+ ns := namedSelects[v]
+ namedSelects[v] = append(ns, namedVal{locIndex: i, valIndex: j})
+ }
+ }
+ }
+ }
+
+ // Step 1: any stores of aggregates remaining are believed to be sourced from call results or args.
+ // Decompose those stores into a series of smaller stores, adding selection ops as necessary.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op == OpStore {
+ t := v.Aux.(*types.Type)
+ source := v.Args[1]
+ tSrc := source.Type
+ iAEATt := isAlreadyExpandedAggregateType(t)
+
+ if !iAEATt {
+ // guarding against store immediate struct into interface data field -- store type is *uint8
+ // TODO can this happen recursively?
+ iAEATt = isAlreadyExpandedAggregateType(tSrc)
+ if iAEATt {
+ t = tSrc
+ }
+ }
+ if iAEATt {
+ if debug {
+ fmt.Printf("Splitting store %s\n", v.LongString())
+ }
+ dst, mem := v.Args[0], v.Args[2]
+ mem = storeArgOrLoad(v.Pos, b, dst, source, mem, t, 0)
+ v.copyOf(mem)
+ }
+ }
+ }
+ }
+
+ val2Preds := make(map[*Value]int32) // Used to accumulate dependency graph of selection operations for topological ordering.
+
+ // Step 2: transform or accumulate selection operations for rewrite in topological order.
+ //
+ // Aggregate types that have already (in earlier phases) been transformed must be lowered comprehensively to finish
+ // the transformation (user-defined structs and arrays, slices, strings, interfaces, complex, 64-bit on 32-bit architectures),
+ //
+ // Any select-for-addressing applied to call results can be transformed directly.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ // Accumulate chains of selectors for processing in topological order
+ switch v.Op {
+ case OpStructSelect, OpArraySelect,
+ OpIData, OpITab,
+ OpStringPtr, OpStringLen,
+ OpSlicePtr, OpSliceLen, OpSliceCap,
+ OpComplexReal, OpComplexImag,
+ OpInt64Hi, OpInt64Lo:
+ w := v.Args[0]
+ switch w.Op {
+ case OpStructSelect, OpArraySelect, OpSelectN, OpArg:
+ val2Preds[w] += 1
+ if debug {
+ fmt.Printf("v2p[%s] = %d\n", w.LongString(), val2Preds[w])
+ }
+ }
+ fallthrough
+
+ case OpSelectN:
+ if _, ok := val2Preds[v]; !ok {
+ val2Preds[v] = 0
+ if debug {
+ fmt.Printf("v2p[%s] = %d\n", v.LongString(), val2Preds[v])
+ }
+ }
+
+ case OpArg:
+ if !isAlreadyExpandedAggregateType(v.Type) {
+ continue
+ }
+ if _, ok := val2Preds[v]; !ok {
+ val2Preds[v] = 0
+ if debug {
+ fmt.Printf("v2p[%s] = %d\n", v.LongString(), val2Preds[v])
+ }
+ }
+
+ case OpSelectNAddr:
+ // Do these directly, there are no chains of selectors.
+ call := v.Args[0]
+ which := v.AuxInt
+ aux := call.Aux.(*AuxCall)
+ pt := v.Type
+ off := offsetFrom(sp, aux.OffsetOfResult(which), pt)
+ v.copyOf(off)
+ }
+ }
+ }
+
+ // Step 3: Compute topological order of selectors,
+ // then process it in reverse to eliminate duplicates,
+ // then forwards to rewrite selectors.
+ //
+ // All chains of selectors end up in same block as the call.
+
+ // Compilation must be deterministic, so sort after extracting first zeroes from map.
+ // Sorting allows dominators-last order within each batch,
+ // so that the backwards scan for duplicates will most often find copies from dominating blocks (it is best-effort).
+ var toProcess []*Value
+ less := func(i, j int) bool {
+ vi, vj := toProcess[i], toProcess[j]
+ bi, bj := vi.Block, vj.Block
+ if bi == bj {
+ return vi.ID < vj.ID
+ }
+ return sdom.domorder(bi) > sdom.domorder(bj) // reverse the order to put dominators last.
+ }
+
+ // Accumulate order in allOrdered
+ var allOrdered []*Value
+ for v, n := range val2Preds {
+ if n == 0 {
+ allOrdered = append(allOrdered, v)
+ }
+ }
+ last := 0 // allOrdered[0:last] has been top-sorted and processed
+ for len(val2Preds) > 0 {
+ toProcess = allOrdered[last:]
+ last = len(allOrdered)
+ sort.SliceStable(toProcess, less)
+ for _, v := range toProcess {
+ delete(val2Preds, v)
+ if v.Op == OpArg {
+ continue // no Args[0], hence done.
+ }
+ w := v.Args[0]
+ n, ok := val2Preds[w]
+ if !ok {
+ continue
+ }
+ if n == 1 {
+ allOrdered = append(allOrdered, w)
+ delete(val2Preds, w)
+ continue
+ }
+ val2Preds[w] = n - 1
+ }
+ }
+
+ common = make(map[selKey]*Value)
+ // Rewrite duplicate selectors as copies where possible.
+ for i := len(allOrdered) - 1; i >= 0; i-- {
+ v := allOrdered[i]
+ if v.Op == OpArg {
+ continue
+ }
+ w := v.Args[0]
+ if w.Op == OpCopy {
+ for w.Op == OpCopy {
+ w = w.Args[0]
+ }
+ v.SetArg(0, w)
+ }
+ typ := v.Type
+ if typ.IsMemory() {
+ continue // handled elsewhere, not an indexable result
+ }
+ size := typ.Width
+ offset := int64(0)
+ switch v.Op {
+ case OpStructSelect:
+ if w.Type.Etype == types.TSTRUCT {
+ offset = w.Type.FieldOff(int(v.AuxInt))
+ } else { // Immediate interface data artifact, offset is zero.
+ f.Fatalf("Expand calls interface data problem, func %s, v=%s, w=%s\n", f.Name, v.LongString(), w.LongString())
+ }
+ case OpArraySelect:
+ offset = size * v.AuxInt
+ case OpSelectN:
+ offset = w.Aux.(*AuxCall).OffsetOfResult(v.AuxInt)
+ case OpInt64Hi:
+ offset = hiOffset
+ case OpInt64Lo:
+ offset = lowOffset
+ case OpStringLen, OpSliceLen, OpIData:
+ offset = ptrSize
+ case OpSliceCap:
+ offset = 2 * ptrSize
+ case OpComplexImag:
+ offset = size
+ }
+ sk := selKey{from: w, size: size, offset: offset, typ: typ}
+ dupe := common[sk]
+ if dupe == nil {
+ common[sk] = v
+ } else if sdom.IsAncestorEq(dupe.Block, v.Block) {
+ v.copyOf(dupe)
+ } else {
+ // Because values are processed in dominator order, the old common[s] will never dominate after a miss is seen.
+ // Installing the new value might match some future values.
+ common[sk] = v
+ }
+ }
+
+ // Indices of entries in f.Names that need to be deleted.
+ var toDelete []namedVal
+
+ // Rewrite selectors.
+ for i, v := range allOrdered {
+ if debug {
+ b := v.Block
+ fmt.Printf("allOrdered[%d] = b%d, %s, uses=%d\n", i, b.ID, v.LongString(), v.Uses)
+ }
+ if v.Uses == 0 {
+ v.reset(OpInvalid)
+ continue
+ }
+ if v.Op == OpCopy {
+ continue
+ }
+ locs := rewriteSelect(v, v, 0)
+ // Install new names.
+ if v.Type.IsMemory() {
+ continue
+ }
+ // Leaf types may have debug locations
+ if !isAlreadyExpandedAggregateType(v.Type) {
+ for _, l := range locs {
+ f.NamedValues[l] = append(f.NamedValues[l], v)
+ }
+ f.Names = append(f.Names, locs...)
+ continue
+ }
+ // Not-leaf types that had debug locations need to lose them.
+ if ns, ok := namedSelects[v]; ok {
+ toDelete = append(toDelete, ns...)
+ }
+ }
+
+ deleteNamedVals(f, toDelete)
+
+ // Step 4: rewrite the calls themselves, correcting the type
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ switch v.Op {
+ case OpStaticLECall:
+ v.Op = OpStaticCall
+ v.Type = types.TypeMem
+ case OpClosureLECall:
+ v.Op = OpClosureCall
+ v.Type = types.TypeMem
+ case OpInterLECall:
+ v.Op = OpInterCall
+ v.Type = types.TypeMem
+ }
+ }
+ }
+
+ // Step 5: elide any copies introduced.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ for i, a := range v.Args {
+ if a.Op != OpCopy {
+ continue
+ }
+ aa := copySource(a)
+ v.SetArg(i, aa)
+ for a.Uses == 0 {
+ b := a.Args[0]
+ a.reset(OpInvalid)
+ a = b
+ }
+ }
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go
new file mode 100644
index 0000000..b4c3e5c
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/export_test.go
@@ -0,0 +1,209 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "cmd/internal/obj"
+ "cmd/internal/obj/arm64"
+ "cmd/internal/obj/s390x"
+ "cmd/internal/obj/x86"
+ "cmd/internal/src"
+ "fmt"
+ "testing"
+)
+
+var CheckFunc = checkFunc
+var Opt = opt
+var Deadcode = deadcode
+var Copyelim = copyelim
+
+var testCtxts = map[string]*obj.Link{
+ "amd64": obj.Linknew(&x86.Linkamd64),
+ "s390x": obj.Linknew(&s390x.Links390x),
+ "arm64": obj.Linknew(&arm64.Linkarm64),
+}
+
+func testConfig(tb testing.TB) *Conf { return testConfigArch(tb, "amd64") }
+func testConfigS390X(tb testing.TB) *Conf { return testConfigArch(tb, "s390x") }
+func testConfigARM64(tb testing.TB) *Conf { return testConfigArch(tb, "arm64") }
+
+func testConfigArch(tb testing.TB, arch string) *Conf {
+ ctxt, ok := testCtxts[arch]
+ if !ok {
+ tb.Fatalf("unknown arch %s", arch)
+ }
+ if ctxt.Arch.PtrSize != 8 {
+ tb.Fatal("dummyTypes is 64-bit only")
+ }
+ c := &Conf{
+ config: NewConfig(arch, dummyTypes, ctxt, true),
+ tb: tb,
+ }
+ return c
+}
+
+type Conf struct {
+ config *Config
+ tb testing.TB
+ fe Frontend
+}
+
+func (c *Conf) Frontend() Frontend {
+ if c.fe == nil {
+ c.fe = DummyFrontend{t: c.tb, ctxt: c.config.ctxt}
+ }
+ return c.fe
+}
+
+// DummyFrontend is a test-only frontend.
+// It assumes 64 bit integers and pointers.
+type DummyFrontend struct {
+ t testing.TB
+ ctxt *obj.Link
+}
+
+type DummyAuto struct {
+ t *types.Type
+ s string
+}
+
+func (d *DummyAuto) Typ() *types.Type {
+ return d.t
+}
+
+func (d *DummyAuto) String() string {
+ return d.s
+}
+
+func (d *DummyAuto) StorageClass() StorageClass {
+ return ClassAuto
+}
+
+func (d *DummyAuto) IsSynthetic() bool {
+ return false
+}
+
+func (d *DummyAuto) IsAutoTmp() bool {
+ return true
+}
+
+func (DummyFrontend) StringData(s string) *obj.LSym {
+ return nil
+}
+func (DummyFrontend) Auto(pos src.XPos, t *types.Type) GCNode {
+ return &DummyAuto{t: t, s: "aDummyAuto"}
+}
+func (d DummyFrontend) SplitString(s LocalSlot) (LocalSlot, LocalSlot) {
+ return LocalSlot{N: s.N, Type: dummyTypes.BytePtr, Off: s.Off}, LocalSlot{N: s.N, Type: dummyTypes.Int, Off: s.Off + 8}
+}
+func (d DummyFrontend) SplitInterface(s LocalSlot) (LocalSlot, LocalSlot) {
+ return LocalSlot{N: s.N, Type: dummyTypes.BytePtr, Off: s.Off}, LocalSlot{N: s.N, Type: dummyTypes.BytePtr, Off: s.Off + 8}
+}
+func (d DummyFrontend) SplitSlice(s LocalSlot) (LocalSlot, LocalSlot, LocalSlot) {
+ return LocalSlot{N: s.N, Type: s.Type.Elem().PtrTo(), Off: s.Off},
+ LocalSlot{N: s.N, Type: dummyTypes.Int, Off: s.Off + 8},
+ LocalSlot{N: s.N, Type: dummyTypes.Int, Off: s.Off + 16}
+}
+func (d DummyFrontend) SplitComplex(s LocalSlot) (LocalSlot, LocalSlot) {
+ if s.Type.Size() == 16 {
+ return LocalSlot{N: s.N, Type: dummyTypes.Float64, Off: s.Off}, LocalSlot{N: s.N, Type: dummyTypes.Float64, Off: s.Off + 8}
+ }
+ return LocalSlot{N: s.N, Type: dummyTypes.Float32, Off: s.Off}, LocalSlot{N: s.N, Type: dummyTypes.Float32, Off: s.Off + 4}
+}
+func (d DummyFrontend) SplitInt64(s LocalSlot) (LocalSlot, LocalSlot) {
+ if s.Type.IsSigned() {
+ return LocalSlot{N: s.N, Type: dummyTypes.Int32, Off: s.Off + 4}, LocalSlot{N: s.N, Type: dummyTypes.UInt32, Off: s.Off}
+ }
+ return LocalSlot{N: s.N, Type: dummyTypes.UInt32, Off: s.Off + 4}, LocalSlot{N: s.N, Type: dummyTypes.UInt32, Off: s.Off}
+}
+func (d DummyFrontend) SplitStruct(s LocalSlot, i int) LocalSlot {
+ return LocalSlot{N: s.N, Type: s.Type.FieldType(i), Off: s.Off + s.Type.FieldOff(i)}
+}
+func (d DummyFrontend) SplitArray(s LocalSlot) LocalSlot {
+ return LocalSlot{N: s.N, Type: s.Type.Elem(), Off: s.Off}
+}
+
+func (d DummyFrontend) SplitSlot(parent *LocalSlot, suffix string, offset int64, t *types.Type) LocalSlot {
+ return LocalSlot{N: parent.N, Type: t, Off: offset}
+}
+func (DummyFrontend) Line(_ src.XPos) string {
+ return "unknown.go:0"
+}
+func (DummyFrontend) AllocFrame(f *Func) {
+}
+func (d DummyFrontend) Syslook(s string) *obj.LSym {
+ return d.ctxt.Lookup(s)
+}
+func (DummyFrontend) UseWriteBarrier() bool {
+ return true // only writebarrier_test cares
+}
+func (DummyFrontend) SetWBPos(pos src.XPos) {
+}
+
+func (d DummyFrontend) Logf(msg string, args ...interface{}) { d.t.Logf(msg, args...) }
+func (d DummyFrontend) Log() bool { return true }
+
+func (d DummyFrontend) Fatalf(_ src.XPos, msg string, args ...interface{}) { d.t.Fatalf(msg, args...) }
+func (d DummyFrontend) Warnl(_ src.XPos, msg string, args ...interface{}) { d.t.Logf(msg, args...) }
+func (d DummyFrontend) Debug_checknil() bool { return false }
+
+func (d DummyFrontend) MyImportPath() string {
+ return "my/import/path"
+}
+
+var dummyTypes Types
+
+func init() {
+ // Initialize just enough of the universe and the types package to make our tests function.
+ // TODO(josharian): move universe initialization to the types package,
+ // so this test setup can share it.
+
+ types.Tconv = func(t *types.Type, flag, mode int) string {
+ return t.Etype.String()
+ }
+ types.Sconv = func(s *types.Sym, flag, mode int) string {
+ return "sym"
+ }
+ types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) {
+ fmt.Fprintf(s, "sym")
+ }
+ types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) {
+ fmt.Fprintf(s, "%v", t.Etype)
+ }
+ types.Dowidth = func(t *types.Type) {}
+
+ for _, typ := range [...]struct {
+ width int64
+ et types.EType
+ }{
+ {1, types.TINT8},
+ {1, types.TUINT8},
+ {1, types.TBOOL},
+ {2, types.TINT16},
+ {2, types.TUINT16},
+ {4, types.TINT32},
+ {4, types.TUINT32},
+ {4, types.TFLOAT32},
+ {4, types.TFLOAT64},
+ {8, types.TUINT64},
+ {8, types.TINT64},
+ {8, types.TINT},
+ {8, types.TUINTPTR},
+ } {
+ t := types.New(typ.et)
+ t.Width = typ.width
+ t.Align = uint8(typ.width)
+ types.Types[typ.et] = t
+ }
+ dummyTypes.SetTypPtrs()
+}
+
+func (d DummyFrontend) DerefItab(sym *obj.LSym, off int64) *obj.LSym { return nil }
+
+func (d DummyFrontend) CanSSA(t *types.Type) bool {
+ // There are no un-SSAable types in dummy land.
+ return true
+}
diff --git a/src/cmd/compile/internal/ssa/flagalloc.go b/src/cmd/compile/internal/ssa/flagalloc.go
new file mode 100644
index 0000000..61c45a6
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/flagalloc.go
@@ -0,0 +1,269 @@
+// 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
+
+// flagalloc allocates the flag register among all the flag-generating
+// instructions. Flag values are recomputed if they need to be
+// spilled/restored.
+func flagalloc(f *Func) {
+ // Compute the in-register flag value we want at the end of
+ // each block. This is basically a best-effort live variable
+ // analysis, so it can be much simpler than a full analysis.
+ end := make([]*Value, f.NumBlocks())
+ po := f.postorder()
+ for n := 0; n < 2; n++ {
+ for _, b := range po {
+ // Walk values backwards to figure out what flag
+ // value we want in the flag register at the start
+ // of the block.
+ var flag *Value
+ for _, c := range b.ControlValues() {
+ if c.Type.IsFlags() {
+ if flag != nil {
+ panic("cannot have multiple controls using flags")
+ }
+ flag = c
+ }
+ }
+ if flag == nil {
+ flag = end[b.ID]
+ }
+ for j := len(b.Values) - 1; j >= 0; j-- {
+ v := b.Values[j]
+ if v == flag {
+ flag = nil
+ }
+ if v.clobbersFlags() {
+ flag = nil
+ }
+ for _, a := range v.Args {
+ if a.Type.IsFlags() {
+ flag = a
+ }
+ }
+ }
+ if flag != nil {
+ for _, e := range b.Preds {
+ p := e.b
+ end[p.ID] = flag
+ }
+ }
+ }
+ }
+
+ // For blocks which have a flags control value, that's the only value
+ // we can leave in the flags register at the end of the block. (There
+ // is no place to put a flag regeneration instruction.)
+ for _, b := range f.Blocks {
+ if b.Kind == BlockDefer {
+ // Defer blocks internally use/clobber the flags value.
+ end[b.ID] = nil
+ continue
+ }
+ for _, v := range b.ControlValues() {
+ if v.Type.IsFlags() && end[b.ID] != v {
+ end[b.ID] = nil
+ }
+ }
+ }
+
+ // Compute which flags values will need to be spilled.
+ spill := map[ID]bool{}
+ for _, b := range f.Blocks {
+ var flag *Value
+ if len(b.Preds) > 0 {
+ flag = end[b.Preds[0].b.ID]
+ }
+ for _, v := range b.Values {
+ for _, a := range v.Args {
+ if !a.Type.IsFlags() {
+ continue
+ }
+ if a == flag {
+ continue
+ }
+ // a will need to be restored here.
+ spill[a.ID] = true
+ flag = a
+ }
+ if v.clobbersFlags() {
+ flag = nil
+ }
+ if v.Type.IsFlags() {
+ flag = v
+ }
+ }
+ for _, v := range b.ControlValues() {
+ if v != flag && v.Type.IsFlags() {
+ spill[v.ID] = true
+ }
+ }
+ if v := end[b.ID]; v != nil && v != flag {
+ spill[v.ID] = true
+ }
+ }
+
+ // Add flag spill and recomputation where they are needed.
+ var remove []*Value // values that should be checked for possible removal
+ var oldSched []*Value
+ for _, b := range f.Blocks {
+ oldSched = append(oldSched[:0], b.Values...)
+ b.Values = b.Values[:0]
+ // The current live flag value (the pre-flagalloc copy).
+ var flag *Value
+ if len(b.Preds) > 0 {
+ flag = end[b.Preds[0].b.ID]
+ // Note: the following condition depends on the lack of critical edges.
+ for _, e := range b.Preds[1:] {
+ p := e.b
+ if end[p.ID] != flag {
+ f.Fatalf("live flag in %s's predecessors not consistent", b)
+ }
+ }
+ }
+ for _, v := range oldSched {
+ if v.Op == OpPhi && v.Type.IsFlags() {
+ f.Fatalf("phi of flags not supported: %s", v.LongString())
+ }
+
+ // If v will be spilled, and v uses memory, then we must split it
+ // into a load + a flag generator.
+ if spill[v.ID] && v.MemoryArg() != nil {
+ remove = append(remove, v)
+ if !f.Config.splitLoad(v) {
+ f.Fatalf("can't split flag generator: %s", v.LongString())
+ }
+ }
+
+ // Make sure any flag arg of v is in the flags register.
+ // If not, recompute it.
+ for i, a := range v.Args {
+ if !a.Type.IsFlags() {
+ continue
+ }
+ if a == flag {
+ continue
+ }
+ // Recalculate a
+ c := copyFlags(a, b)
+ // Update v.
+ v.SetArg(i, c)
+ // Remember the most-recently computed flag value.
+ flag = a
+ }
+ // Issue v.
+ b.Values = append(b.Values, v)
+ if v.clobbersFlags() {
+ flag = nil
+ }
+ if v.Type.IsFlags() {
+ flag = v
+ }
+ }
+ for i, v := range b.ControlValues() {
+ if v != flag && v.Type.IsFlags() {
+ // Recalculate control value.
+ remove = append(remove, v)
+ c := copyFlags(v, b)
+ b.ReplaceControl(i, c)
+ flag = v
+ }
+ }
+ if v := end[b.ID]; v != nil && v != flag {
+ // Need to reissue flag generator for use by
+ // subsequent blocks.
+ remove = append(remove, v)
+ copyFlags(v, b)
+ // Note: this flag generator is not properly linked up
+ // with the flag users. This breaks the SSA representation.
+ // We could fix up the users with another pass, but for now
+ // we'll just leave it. (Regalloc has the same issue for
+ // standard regs, and it runs next.)
+ // For this reason, take care not to add this flag
+ // generator to the remove list.
+ }
+ }
+
+ // Save live flag state for later.
+ for _, b := range f.Blocks {
+ b.FlagsLiveAtEnd = end[b.ID] != nil
+ }
+
+ // Remove any now-dead values.
+ // The number of values to remove is likely small,
+ // and removing them requires processing all values in a block,
+ // so minimize the number of blocks that we touch.
+
+ // Shrink remove to contain only dead values, and clobber those dead values.
+ for i := 0; i < len(remove); i++ {
+ v := remove[i]
+ if v.Uses == 0 {
+ v.reset(OpInvalid)
+ continue
+ }
+ // Remove v.
+ last := len(remove) - 1
+ remove[i] = remove[last]
+ remove[last] = nil
+ remove = remove[:last]
+ i-- // reprocess value at i
+ }
+
+ if len(remove) == 0 {
+ return
+ }
+
+ removeBlocks := f.newSparseSet(f.NumBlocks())
+ defer f.retSparseSet(removeBlocks)
+ for _, v := range remove {
+ removeBlocks.add(v.Block.ID)
+ }
+
+ // Process affected blocks, preserving value order.
+ for _, b := range f.Blocks {
+ if !removeBlocks.contains(b.ID) {
+ continue
+ }
+ i := 0
+ for j := 0; j < len(b.Values); j++ {
+ v := b.Values[j]
+ if v.Op == OpInvalid {
+ continue
+ }
+ b.Values[i] = v
+ i++
+ }
+ b.truncateValues(i)
+ }
+}
+
+func (v *Value) clobbersFlags() bool {
+ if opcodeTable[v.Op].clobberFlags {
+ return true
+ }
+ if v.Type.IsTuple() && (v.Type.FieldType(0).IsFlags() || v.Type.FieldType(1).IsFlags()) {
+ // This case handles the possibility where a flag value is generated but never used.
+ // In that case, there's no corresponding Select to overwrite the flags value,
+ // so we must consider flags clobbered by the tuple-generating instruction.
+ return true
+ }
+ return false
+}
+
+// copyFlags copies v (flag generator) into b, returns the copy.
+// If v's arg is also flags, copy recursively.
+func copyFlags(v *Value, b *Block) *Value {
+ flagsArgs := make(map[int]*Value)
+ for i, a := range v.Args {
+ if a.Type.IsFlags() || a.Type.IsTuple() {
+ flagsArgs[i] = copyFlags(a, b)
+ }
+ }
+ c := v.copyInto(b)
+ for i, a := range flagsArgs {
+ c.SetArg(i, a)
+ }
+ return c
+}
diff --git a/src/cmd/compile/internal/ssa/flags_amd64_test.s b/src/cmd/compile/internal/ssa/flags_amd64_test.s
new file mode 100644
index 0000000..8bd8701
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/flags_amd64_test.s
@@ -0,0 +1,31 @@
+// Copyright 2020 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.
+
+// +build amd64
+
+#include "textflag.h"
+
+TEXT ·asmAddFlags(SB),NOSPLIT,$0-24
+ MOVQ x+0(FP), AX
+ ADDQ y+8(FP), AX
+ PUSHFQ
+ POPQ AX
+ MOVQ AX, ret+16(FP)
+ RET
+
+TEXT ·asmSubFlags(SB),NOSPLIT,$0-24
+ MOVQ x+0(FP), AX
+ SUBQ y+8(FP), AX
+ PUSHFQ
+ POPQ AX
+ MOVQ AX, ret+16(FP)
+ RET
+
+TEXT ·asmAndFlags(SB),NOSPLIT,$0-24
+ MOVQ x+0(FP), AX
+ ANDQ y+8(FP), AX
+ PUSHFQ
+ POPQ AX
+ MOVQ AX, ret+16(FP)
+ RET
diff --git a/src/cmd/compile/internal/ssa/flags_arm64_test.s b/src/cmd/compile/internal/ssa/flags_arm64_test.s
new file mode 100644
index 0000000..f201bcc
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/flags_arm64_test.s
@@ -0,0 +1,32 @@
+// Copyright 2020 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.
+
+// +build arm64
+
+#include "textflag.h"
+
+TEXT ·asmAddFlags(SB),NOSPLIT,$0-24
+ MOVD x+0(FP), R0
+ MOVD y+8(FP), R1
+ CMN R0, R1
+ WORD $0xd53b4200 // MOVD NZCV, R0
+ MOVD R0, ret+16(FP)
+ RET
+
+TEXT ·asmSubFlags(SB),NOSPLIT,$0-24
+ MOVD x+0(FP), R0
+ MOVD y+8(FP), R1
+ CMP R1, R0
+ WORD $0xd53b4200 // MOVD NZCV, R0
+ MOVD R0, ret+16(FP)
+ RET
+
+TEXT ·asmAndFlags(SB),NOSPLIT,$0-24
+ MOVD x+0(FP), R0
+ MOVD y+8(FP), R1
+ TST R1, R0
+ WORD $0xd53b4200 // MOVD NZCV, R0
+ BIC $0x30000000, R0 // clear C, V bits, as TST does not change those flags
+ MOVD R0, ret+16(FP)
+ RET
diff --git a/src/cmd/compile/internal/ssa/flags_test.go b/src/cmd/compile/internal/ssa/flags_test.go
new file mode 100644
index 0000000..d64abf6
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/flags_test.go
@@ -0,0 +1,108 @@
+// Copyright 2020 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.
+
+// +build amd64 arm64
+
+package ssa
+
+// This file tests the functions addFlags64 and subFlags64 by comparing their
+// results to what the chip calculates.
+
+import (
+ "runtime"
+ "testing"
+)
+
+func TestAddFlagsNative(t *testing.T) {
+ var numbers = []int64{
+ 1, 0, -1,
+ 2, -2,
+ 1<<63 - 1, -1 << 63,
+ }
+ coverage := map[flagConstant]bool{}
+ for _, x := range numbers {
+ for _, y := range numbers {
+ a := addFlags64(x, y)
+ b := flagRegister2flagConstant(asmAddFlags(x, y), false)
+ if a != b {
+ t.Errorf("asmAdd diff: x=%x y=%x got=%s want=%s\n", x, y, a, b)
+ }
+ coverage[a] = true
+ }
+ }
+ if len(coverage) != 9 { // TODO: can we cover all outputs?
+ t.Errorf("coverage too small, got %d want 9", len(coverage))
+ }
+}
+
+func TestSubFlagsNative(t *testing.T) {
+ var numbers = []int64{
+ 1, 0, -1,
+ 2, -2,
+ 1<<63 - 1, -1 << 63,
+ }
+ coverage := map[flagConstant]bool{}
+ for _, x := range numbers {
+ for _, y := range numbers {
+ a := subFlags64(x, y)
+ b := flagRegister2flagConstant(asmSubFlags(x, y), true)
+ if a != b {
+ t.Errorf("asmSub diff: x=%x y=%x got=%s want=%s\n", x, y, a, b)
+ }
+ coverage[a] = true
+ }
+ }
+ if len(coverage) != 7 { // TODO: can we cover all outputs?
+ t.Errorf("coverage too small, got %d want 7", len(coverage))
+ }
+}
+
+func TestAndFlagsNative(t *testing.T) {
+ var numbers = []int64{
+ 1, 0, -1,
+ 2, -2,
+ 1<<63 - 1, -1 << 63,
+ }
+ coverage := map[flagConstant]bool{}
+ for _, x := range numbers {
+ for _, y := range numbers {
+ a := logicFlags64(x & y)
+ b := flagRegister2flagConstant(asmAndFlags(x, y), false)
+ if a != b {
+ t.Errorf("asmAnd diff: x=%x y=%x got=%s want=%s\n", x, y, a, b)
+ }
+ coverage[a] = true
+ }
+ }
+ if len(coverage) != 3 {
+ t.Errorf("coverage too small, got %d want 3", len(coverage))
+ }
+}
+
+func asmAddFlags(x, y int64) int
+func asmSubFlags(x, y int64) int
+func asmAndFlags(x, y int64) int
+
+func flagRegister2flagConstant(x int, sub bool) flagConstant {
+ var fcb flagConstantBuilder
+ switch runtime.GOARCH {
+ case "amd64":
+ fcb.Z = x>>6&1 != 0
+ fcb.N = x>>7&1 != 0
+ fcb.C = x>>0&1 != 0
+ if sub {
+ // Convert from amd64-sense to arm-sense
+ fcb.C = !fcb.C
+ }
+ fcb.V = x>>11&1 != 0
+ case "arm64":
+ fcb.Z = x>>30&1 != 0
+ fcb.N = x>>31&1 != 0
+ fcb.C = x>>29&1 != 0
+ fcb.V = x>>28&1 != 0
+ default:
+ panic("unsupported architecture: " + runtime.GOARCH)
+ }
+ return fcb.encode()
+}
diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go
new file mode 100644
index 0000000..e6f899a
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/func.go
@@ -0,0 +1,799 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "crypto/sha1"
+ "fmt"
+ "io"
+ "math"
+ "os"
+ "strings"
+)
+
+type writeSyncer interface {
+ io.Writer
+ Sync() error
+}
+
+// A Func represents a Go func declaration (or function literal) and its body.
+// This package compiles each Func independently.
+// Funcs are single-use; a new Func must be created for every compiled function.
+type Func struct {
+ Config *Config // architecture information
+ Cache *Cache // re-usable cache
+ fe Frontend // frontend state associated with this Func, callbacks into compiler frontend
+ pass *pass // current pass information (name, options, etc.)
+ Name string // e.g. NewFunc or (*Func).NumBlocks (no package prefix)
+ Type *types.Type // type signature of the function.
+ Blocks []*Block // unordered set of all basic blocks (note: not indexable by ID)
+ Entry *Block // the entry basic block
+
+ bid idAlloc // block ID allocator
+ vid idAlloc // value ID allocator
+
+ // Given an environment variable used for debug hash match,
+ // what file (if any) receives the yes/no logging?
+ logfiles map[string]writeSyncer
+ HTMLWriter *HTMLWriter // html writer, for debugging
+ DebugTest bool // default true unless $GOSSAHASH != ""; as a debugging aid, make new code conditional on this and use GOSSAHASH to binary search for failing cases
+ PrintOrHtmlSSA bool // true if GOSSAFUNC matches, true even if fe.Log() (spew phase results to stdout) is false.
+ ruleMatches map[string]int // number of times countRule was called during compilation for any given string
+
+ scheduled bool // Values in Blocks are in final order
+ laidout bool // Blocks are ordered
+ NoSplit bool // true if function is marked as nosplit. Used by schedule check pass.
+ dumpFileSeq uint8 // the sequence numbers of dump file. (%s_%02d__%s.dump", funcname, dumpFileSeq, phaseName)
+
+ // when register allocation is done, maps value ids to locations
+ RegAlloc []Location
+
+ // map from LocalSlot to set of Values that we want to store in that slot.
+ NamedValues map[LocalSlot][]*Value
+ // Names is a copy of NamedValues.Keys. We keep a separate list
+ // of keys to make iteration order deterministic.
+ Names []LocalSlot
+
+ // WBLoads is a list of Blocks that branch on the write
+ // barrier flag. Safe-points are disabled from the OpLoad that
+ // reads the write-barrier flag until the control flow rejoins
+ // below the two successors of this block.
+ WBLoads []*Block
+
+ freeValues *Value // free Values linked by argstorage[0]. All other fields except ID are 0/nil.
+ freeBlocks *Block // free Blocks linked by succstorage[0].b. All other fields except ID are 0/nil.
+
+ cachedPostorder []*Block // cached postorder traversal
+ cachedIdom []*Block // cached immediate dominators
+ cachedSdom SparseTree // cached dominator tree
+ cachedLoopnest *loopnest // cached loop nest information
+ cachedLineStarts *xposmap // cached map/set of xpos to integers
+
+ auxmap auxmap // map from aux values to opaque ids used by CSE
+ constants map[int64][]*Value // constants cache, keyed by constant value; users must check value's Op and Type
+}
+
+// NewFunc returns a new, empty function object.
+// Caller must set f.Config and f.Cache before using f.
+func NewFunc(fe Frontend) *Func {
+ return &Func{fe: fe, NamedValues: make(map[LocalSlot][]*Value)}
+}
+
+// NumBlocks returns an integer larger than the id of any Block in the Func.
+func (f *Func) NumBlocks() int {
+ return f.bid.num()
+}
+
+// NumValues returns an integer larger than the id of any Value in the Func.
+func (f *Func) NumValues() int {
+ return f.vid.num()
+}
+
+// newSparseSet returns a sparse set that can store at least up to n integers.
+func (f *Func) newSparseSet(n int) *sparseSet {
+ for i, scr := range f.Cache.scrSparseSet {
+ if scr != nil && scr.cap() >= n {
+ f.Cache.scrSparseSet[i] = nil
+ scr.clear()
+ return scr
+ }
+ }
+ return newSparseSet(n)
+}
+
+// retSparseSet returns a sparse set to the config's cache of sparse
+// sets to be reused by f.newSparseSet.
+func (f *Func) retSparseSet(ss *sparseSet) {
+ for i, scr := range f.Cache.scrSparseSet {
+ if scr == nil {
+ f.Cache.scrSparseSet[i] = ss
+ return
+ }
+ }
+ f.Cache.scrSparseSet = append(f.Cache.scrSparseSet, ss)
+}
+
+// newSparseMap returns a sparse map that can store at least up to n integers.
+func (f *Func) newSparseMap(n int) *sparseMap {
+ for i, scr := range f.Cache.scrSparseMap {
+ if scr != nil && scr.cap() >= n {
+ f.Cache.scrSparseMap[i] = nil
+ scr.clear()
+ return scr
+ }
+ }
+ return newSparseMap(n)
+}
+
+// retSparseMap returns a sparse map to the config's cache of sparse
+// sets to be reused by f.newSparseMap.
+func (f *Func) retSparseMap(ss *sparseMap) {
+ for i, scr := range f.Cache.scrSparseMap {
+ if scr == nil {
+ f.Cache.scrSparseMap[i] = ss
+ return
+ }
+ }
+ f.Cache.scrSparseMap = append(f.Cache.scrSparseMap, ss)
+}
+
+// newPoset returns a new poset from the internal cache
+func (f *Func) newPoset() *poset {
+ if len(f.Cache.scrPoset) > 0 {
+ po := f.Cache.scrPoset[len(f.Cache.scrPoset)-1]
+ f.Cache.scrPoset = f.Cache.scrPoset[:len(f.Cache.scrPoset)-1]
+ return po
+ }
+ return newPoset()
+}
+
+// retPoset returns a poset to the internal cache
+func (f *Func) retPoset(po *poset) {
+ f.Cache.scrPoset = append(f.Cache.scrPoset, po)
+}
+
+// newDeadcodeLive returns a slice for the
+// deadcode pass to use to indicate which values are live.
+func (f *Func) newDeadcodeLive() []bool {
+ r := f.Cache.deadcode.live
+ f.Cache.deadcode.live = nil
+ return r
+}
+
+// retDeadcodeLive returns a deadcode live value slice for re-use.
+func (f *Func) retDeadcodeLive(live []bool) {
+ f.Cache.deadcode.live = live
+}
+
+// newDeadcodeLiveOrderStmts returns a slice for the
+// deadcode pass to use to indicate which values
+// need special treatment for statement boundaries.
+func (f *Func) newDeadcodeLiveOrderStmts() []*Value {
+ r := f.Cache.deadcode.liveOrderStmts
+ f.Cache.deadcode.liveOrderStmts = nil
+ return r
+}
+
+// retDeadcodeLiveOrderStmts returns a deadcode liveOrderStmts slice for re-use.
+func (f *Func) retDeadcodeLiveOrderStmts(liveOrderStmts []*Value) {
+ f.Cache.deadcode.liveOrderStmts = liveOrderStmts
+}
+
+// newValue allocates a new Value with the given fields and places it at the end of b.Values.
+func (f *Func) newValue(op Op, t *types.Type, b *Block, pos src.XPos) *Value {
+ var v *Value
+ if f.freeValues != nil {
+ v = f.freeValues
+ f.freeValues = v.argstorage[0]
+ v.argstorage[0] = nil
+ } else {
+ ID := f.vid.get()
+ if int(ID) < len(f.Cache.values) {
+ v = &f.Cache.values[ID]
+ v.ID = ID
+ } else {
+ v = &Value{ID: ID}
+ }
+ }
+ v.Op = op
+ v.Type = t
+ v.Block = b
+ if notStmtBoundary(op) {
+ pos = pos.WithNotStmt()
+ }
+ v.Pos = pos
+ b.Values = append(b.Values, v)
+ return v
+}
+
+// newValueNoBlock allocates a new Value with the given fields.
+// The returned value is not placed in any block. Once the caller
+// decides on a block b, it must set b.Block and append
+// the returned value to b.Values.
+func (f *Func) newValueNoBlock(op Op, t *types.Type, pos src.XPos) *Value {
+ var v *Value
+ if f.freeValues != nil {
+ v = f.freeValues
+ f.freeValues = v.argstorage[0]
+ v.argstorage[0] = nil
+ } else {
+ ID := f.vid.get()
+ if int(ID) < len(f.Cache.values) {
+ v = &f.Cache.values[ID]
+ v.ID = ID
+ } else {
+ v = &Value{ID: ID}
+ }
+ }
+ v.Op = op
+ v.Type = t
+ v.Block = nil // caller must fix this.
+ if notStmtBoundary(op) {
+ pos = pos.WithNotStmt()
+ }
+ v.Pos = pos
+ return v
+}
+
+// logPassStat writes a string key and int value as a warning in a
+// tab-separated format easily handled by spreadsheets or awk.
+// file names, lines, and function names are included to provide enough (?)
+// context to allow item-by-item comparisons across runs.
+// For example:
+// awk 'BEGIN {FS="\t"} $3~/TIME/{sum+=$4} END{print "t(ns)=",sum}' t.log
+func (f *Func) LogStat(key string, args ...interface{}) {
+ value := ""
+ for _, a := range args {
+ value += fmt.Sprintf("\t%v", a)
+ }
+ n := "missing_pass"
+ if f.pass != nil {
+ n = strings.Replace(f.pass.name, " ", "_", -1)
+ }
+ f.Warnl(f.Entry.Pos, "\t%s\t%s%s\t%s", n, key, value, f.Name)
+}
+
+// unCacheLine removes v from f's constant cache "line" for aux,
+// resets v.InCache when it is found (and removed),
+// and returns whether v was found in that line.
+func (f *Func) unCacheLine(v *Value, aux int64) bool {
+ vv := f.constants[aux]
+ for i, cv := range vv {
+ if v == cv {
+ vv[i] = vv[len(vv)-1]
+ vv[len(vv)-1] = nil
+ f.constants[aux] = vv[0 : len(vv)-1]
+ v.InCache = false
+ return true
+ }
+ }
+ return false
+}
+
+// unCache removes v from f's constant cache.
+func (f *Func) unCache(v *Value) {
+ if v.InCache {
+ aux := v.AuxInt
+ if f.unCacheLine(v, aux) {
+ return
+ }
+ if aux == 0 {
+ switch v.Op {
+ case OpConstNil:
+ aux = constNilMagic
+ case OpConstSlice:
+ aux = constSliceMagic
+ case OpConstString:
+ aux = constEmptyStringMagic
+ case OpConstInterface:
+ aux = constInterfaceMagic
+ }
+ if aux != 0 && f.unCacheLine(v, aux) {
+ return
+ }
+ }
+ f.Fatalf("unCached value %s not found in cache, auxInt=0x%x, adjusted aux=0x%x", v.LongString(), v.AuxInt, aux)
+ }
+}
+
+// freeValue frees a value. It must no longer be referenced or have any args.
+func (f *Func) freeValue(v *Value) {
+ if v.Block == nil {
+ f.Fatalf("trying to free an already freed value")
+ }
+ if v.Uses != 0 {
+ f.Fatalf("value %s still has %d uses", v, v.Uses)
+ }
+ if len(v.Args) != 0 {
+ f.Fatalf("value %s still has %d args", v, len(v.Args))
+ }
+ // Clear everything but ID (which we reuse).
+ id := v.ID
+ if v.InCache {
+ f.unCache(v)
+ }
+ *v = Value{}
+ v.ID = id
+ v.argstorage[0] = f.freeValues
+ f.freeValues = v
+}
+
+// newBlock allocates a new Block of the given kind and places it at the end of f.Blocks.
+func (f *Func) NewBlock(kind BlockKind) *Block {
+ var b *Block
+ if f.freeBlocks != nil {
+ b = f.freeBlocks
+ f.freeBlocks = b.succstorage[0].b
+ b.succstorage[0].b = nil
+ } else {
+ ID := f.bid.get()
+ if int(ID) < len(f.Cache.blocks) {
+ b = &f.Cache.blocks[ID]
+ b.ID = ID
+ } else {
+ b = &Block{ID: ID}
+ }
+ }
+ b.Kind = kind
+ b.Func = f
+ b.Preds = b.predstorage[:0]
+ b.Succs = b.succstorage[:0]
+ b.Values = b.valstorage[:0]
+ f.Blocks = append(f.Blocks, b)
+ f.invalidateCFG()
+ return b
+}
+
+func (f *Func) freeBlock(b *Block) {
+ if b.Func == nil {
+ f.Fatalf("trying to free an already freed block")
+ }
+ // Clear everything but ID (which we reuse).
+ id := b.ID
+ *b = Block{}
+ b.ID = id
+ b.succstorage[0].b = f.freeBlocks
+ f.freeBlocks = b
+}
+
+// NewValue0 returns a new value in the block with no arguments and zero aux values.
+func (b *Block) NewValue0(pos src.XPos, op Op, t *types.Type) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = 0
+ v.Args = v.argstorage[:0]
+ return v
+}
+
+// NewValue returns a new value in the block with no arguments and an auxint value.
+func (b *Block) NewValue0I(pos src.XPos, op Op, t *types.Type, auxint int64) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = auxint
+ v.Args = v.argstorage[:0]
+ return v
+}
+
+// NewValue returns a new value in the block with no arguments and an aux value.
+func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux interface{}) *Value {
+ if _, ok := aux.(int64); ok {
+ // Disallow int64 aux values. They should be in the auxint field instead.
+ // Maybe we want to allow this at some point, but for now we disallow it
+ // to prevent errors like using NewValue1A instead of NewValue1I.
+ b.Fatalf("aux field has int64 type op=%s type=%s aux=%v", op, t, aux)
+ }
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = 0
+ v.Aux = aux
+ v.Args = v.argstorage[:0]
+ return v
+}
+
+// NewValue returns a new value in the block with no arguments and both an auxint and aux values.
+func (b *Block) NewValue0IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = auxint
+ v.Aux = aux
+ v.Args = v.argstorage[:0]
+ return v
+}
+
+// NewValue1 returns a new value in the block with one argument and zero aux values.
+func (b *Block) NewValue1(pos src.XPos, op Op, t *types.Type, arg *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = 0
+ v.Args = v.argstorage[:1]
+ v.argstorage[0] = arg
+ arg.Uses++
+ return v
+}
+
+// NewValue1I returns a new value in the block with one argument and an auxint value.
+func (b *Block) NewValue1I(pos src.XPos, op Op, t *types.Type, auxint int64, arg *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = auxint
+ v.Args = v.argstorage[:1]
+ v.argstorage[0] = arg
+ arg.Uses++
+ return v
+}
+
+// NewValue1A returns a new value in the block with one argument and an aux value.
+func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = 0
+ v.Aux = aux
+ v.Args = v.argstorage[:1]
+ v.argstorage[0] = arg
+ arg.Uses++
+ return v
+}
+
+// NewValue1IA returns a new value in the block with one argument and both an auxint and aux values.
+func (b *Block) NewValue1IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}, arg *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = auxint
+ v.Aux = aux
+ v.Args = v.argstorage[:1]
+ v.argstorage[0] = arg
+ arg.Uses++
+ return v
+}
+
+// NewValue2 returns a new value in the block with two arguments and zero aux values.
+func (b *Block) NewValue2(pos src.XPos, op Op, t *types.Type, arg0, arg1 *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = 0
+ v.Args = v.argstorage[:2]
+ v.argstorage[0] = arg0
+ v.argstorage[1] = arg1
+ arg0.Uses++
+ arg1.Uses++
+ return v
+}
+
+// NewValue2A returns a new value in the block with two arguments and one aux values.
+func (b *Block) NewValue2A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg0, arg1 *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = 0
+ v.Aux = aux
+ v.Args = v.argstorage[:2]
+ v.argstorage[0] = arg0
+ v.argstorage[1] = arg1
+ arg0.Uses++
+ arg1.Uses++
+ return v
+}
+
+// NewValue2I returns a new value in the block with two arguments and an auxint value.
+func (b *Block) NewValue2I(pos src.XPos, op Op, t *types.Type, auxint int64, arg0, arg1 *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = auxint
+ v.Args = v.argstorage[:2]
+ v.argstorage[0] = arg0
+ v.argstorage[1] = arg1
+ arg0.Uses++
+ arg1.Uses++
+ return v
+}
+
+// NewValue2IA returns a new value in the block with two arguments and both an auxint and aux values.
+func (b *Block) NewValue2IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}, arg0, arg1 *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = auxint
+ v.Aux = aux
+ v.Args = v.argstorage[:2]
+ v.argstorage[0] = arg0
+ v.argstorage[1] = arg1
+ arg0.Uses++
+ arg1.Uses++
+ return v
+}
+
+// NewValue3 returns a new value in the block with three arguments and zero aux values.
+func (b *Block) NewValue3(pos src.XPos, op Op, t *types.Type, arg0, arg1, arg2 *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = 0
+ v.Args = v.argstorage[:3]
+ v.argstorage[0] = arg0
+ v.argstorage[1] = arg1
+ v.argstorage[2] = arg2
+ arg0.Uses++
+ arg1.Uses++
+ arg2.Uses++
+ return v
+}
+
+// NewValue3I returns a new value in the block with three arguments and an auxint value.
+func (b *Block) NewValue3I(pos src.XPos, op Op, t *types.Type, auxint int64, arg0, arg1, arg2 *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = auxint
+ v.Args = v.argstorage[:3]
+ v.argstorage[0] = arg0
+ v.argstorage[1] = arg1
+ v.argstorage[2] = arg2
+ arg0.Uses++
+ arg1.Uses++
+ arg2.Uses++
+ return v
+}
+
+// NewValue3A returns a new value in the block with three argument and an aux value.
+func (b *Block) NewValue3A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = 0
+ v.Aux = aux
+ v.Args = v.argstorage[:3]
+ v.argstorage[0] = arg0
+ v.argstorage[1] = arg1
+ v.argstorage[2] = arg2
+ arg0.Uses++
+ arg1.Uses++
+ arg2.Uses++
+ return v
+}
+
+// NewValue4 returns a new value in the block with four arguments and zero aux values.
+func (b *Block) NewValue4(pos src.XPos, op Op, t *types.Type, arg0, arg1, arg2, arg3 *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = 0
+ v.Args = []*Value{arg0, arg1, arg2, arg3}
+ arg0.Uses++
+ arg1.Uses++
+ arg2.Uses++
+ arg3.Uses++
+ return v
+}
+
+// NewValue4I returns a new value in the block with four arguments and and auxint value.
+func (b *Block) NewValue4I(pos src.XPos, op Op, t *types.Type, auxint int64, arg0, arg1, arg2, arg3 *Value) *Value {
+ v := b.Func.newValue(op, t, b, pos)
+ v.AuxInt = auxint
+ v.Args = []*Value{arg0, arg1, arg2, arg3}
+ arg0.Uses++
+ arg1.Uses++
+ arg2.Uses++
+ arg3.Uses++
+ return v
+}
+
+// constVal returns a constant value for c.
+func (f *Func) constVal(op Op, t *types.Type, c int64, setAuxInt bool) *Value {
+ if f.constants == nil {
+ f.constants = make(map[int64][]*Value)
+ }
+ vv := f.constants[c]
+ for _, v := range vv {
+ if v.Op == op && v.Type.Compare(t) == types.CMPeq {
+ if setAuxInt && v.AuxInt != c {
+ panic(fmt.Sprintf("cached const %s should have AuxInt of %d", v.LongString(), c))
+ }
+ return v
+ }
+ }
+ var v *Value
+ if setAuxInt {
+ v = f.Entry.NewValue0I(src.NoXPos, op, t, c)
+ } else {
+ v = f.Entry.NewValue0(src.NoXPos, op, t)
+ }
+ f.constants[c] = append(vv, v)
+ v.InCache = true
+ return v
+}
+
+// These magic auxint values let us easily cache non-numeric constants
+// using the same constants map while making collisions unlikely.
+// These values are unlikely to occur in regular code and
+// are easy to grep for in case of bugs.
+const (
+ constSliceMagic = 1122334455
+ constInterfaceMagic = 2233445566
+ constNilMagic = 3344556677
+ constEmptyStringMagic = 4455667788
+)
+
+// ConstInt returns an int constant representing its argument.
+func (f *Func) ConstBool(t *types.Type, c bool) *Value {
+ i := int64(0)
+ if c {
+ i = 1
+ }
+ return f.constVal(OpConstBool, t, i, true)
+}
+func (f *Func) ConstInt8(t *types.Type, c int8) *Value {
+ return f.constVal(OpConst8, t, int64(c), true)
+}
+func (f *Func) ConstInt16(t *types.Type, c int16) *Value {
+ return f.constVal(OpConst16, t, int64(c), true)
+}
+func (f *Func) ConstInt32(t *types.Type, c int32) *Value {
+ return f.constVal(OpConst32, t, int64(c), true)
+}
+func (f *Func) ConstInt64(t *types.Type, c int64) *Value {
+ return f.constVal(OpConst64, t, c, true)
+}
+func (f *Func) ConstFloat32(t *types.Type, c float64) *Value {
+ return f.constVal(OpConst32F, t, int64(math.Float64bits(float64(float32(c)))), true)
+}
+func (f *Func) ConstFloat64(t *types.Type, c float64) *Value {
+ return f.constVal(OpConst64F, t, int64(math.Float64bits(c)), true)
+}
+
+func (f *Func) ConstSlice(t *types.Type) *Value {
+ return f.constVal(OpConstSlice, t, constSliceMagic, false)
+}
+func (f *Func) ConstInterface(t *types.Type) *Value {
+ return f.constVal(OpConstInterface, t, constInterfaceMagic, false)
+}
+func (f *Func) ConstNil(t *types.Type) *Value {
+ return f.constVal(OpConstNil, t, constNilMagic, false)
+}
+func (f *Func) ConstEmptyString(t *types.Type) *Value {
+ v := f.constVal(OpConstString, t, constEmptyStringMagic, false)
+ v.Aux = ""
+ return v
+}
+func (f *Func) ConstOffPtrSP(t *types.Type, c int64, sp *Value) *Value {
+ v := f.constVal(OpOffPtr, t, c, true)
+ if len(v.Args) == 0 {
+ v.AddArg(sp)
+ }
+ return v
+
+}
+
+func (f *Func) Frontend() Frontend { return f.fe }
+func (f *Func) Warnl(pos src.XPos, msg string, args ...interface{}) { f.fe.Warnl(pos, msg, args...) }
+func (f *Func) Logf(msg string, args ...interface{}) { f.fe.Logf(msg, args...) }
+func (f *Func) Log() bool { return f.fe.Log() }
+func (f *Func) Fatalf(msg string, args ...interface{}) { f.fe.Fatalf(f.Entry.Pos, msg, args...) }
+
+// postorder returns the reachable blocks in f in a postorder traversal.
+func (f *Func) postorder() []*Block {
+ if f.cachedPostorder == nil {
+ f.cachedPostorder = postorder(f)
+ }
+ return f.cachedPostorder
+}
+
+func (f *Func) Postorder() []*Block {
+ return f.postorder()
+}
+
+// Idom returns a map from block ID to the immediate dominator of that block.
+// f.Entry.ID maps to nil. Unreachable blocks map to nil as well.
+func (f *Func) Idom() []*Block {
+ if f.cachedIdom == nil {
+ f.cachedIdom = dominators(f)
+ }
+ return f.cachedIdom
+}
+
+// Sdom returns a sparse tree representing the dominator relationships
+// among the blocks of f.
+func (f *Func) Sdom() SparseTree {
+ if f.cachedSdom == nil {
+ f.cachedSdom = newSparseTree(f, f.Idom())
+ }
+ return f.cachedSdom
+}
+
+// loopnest returns the loop nest information for f.
+func (f *Func) loopnest() *loopnest {
+ if f.cachedLoopnest == nil {
+ f.cachedLoopnest = loopnestfor(f)
+ }
+ return f.cachedLoopnest
+}
+
+// invalidateCFG tells f that its CFG has changed.
+func (f *Func) invalidateCFG() {
+ f.cachedPostorder = nil
+ f.cachedIdom = nil
+ f.cachedSdom = nil
+ f.cachedLoopnest = nil
+}
+
+// DebugHashMatch reports whether environment variable evname
+// 1) is empty (this is a special more-quickly implemented case of 3)
+// 2) is "y" or "Y"
+// 3) is a suffix of the sha1 hash of name
+// 4) is a suffix of the environment variable
+// fmt.Sprintf("%s%d", evname, n)
+// provided that all such variables are nonempty for 0 <= i <= n
+// Otherwise it returns false.
+// When true is returned the message
+// "%s triggered %s\n", evname, name
+// is printed on the file named in environment variable
+// GSHS_LOGFILE
+// or standard out if that is empty or there is an error
+// opening the file.
+func (f *Func) DebugHashMatch(evname string) bool {
+ name := f.fe.MyImportPath() + "." + f.Name
+ evhash := os.Getenv(evname)
+ switch evhash {
+ case "":
+ return true // default behavior with no EV is "on"
+ case "y", "Y":
+ f.logDebugHashMatch(evname, name)
+ return true
+ case "n", "N":
+ return false
+ }
+ // Check the hash of the name against a partial input hash.
+ // We use this feature to do a binary search 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, evhash) {
+ f.logDebugHashMatch(evname, name)
+ return true
+ }
+
+ // Iteratively try additional hashes to allow tests for multi-point
+ // failure.
+ for i := 0; true; i++ {
+ ev := fmt.Sprintf("%s%d", evname, i)
+ evv := os.Getenv(ev)
+ if evv == "" {
+ break
+ }
+ if strings.HasSuffix(hstr, evv) {
+ f.logDebugHashMatch(ev, name)
+ return true
+ }
+ }
+ return false
+}
+
+func (f *Func) logDebugHashMatch(evname, name string) {
+ if f.logfiles == nil {
+ f.logfiles = make(map[string]writeSyncer)
+ }
+ file := f.logfiles[evname]
+ if file == nil {
+ file = os.Stdout
+ if tmpfile := os.Getenv("GSHS_LOGFILE"); tmpfile != "" {
+ var err error
+ file, err = os.OpenFile(tmpfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
+ if err != nil {
+ f.Fatalf("could not open hash-testing logfile %s", tmpfile)
+ }
+ }
+ f.logfiles[evname] = file
+ }
+ fmt.Fprintf(file, "%s triggered %s\n", evname, name)
+ file.Sync()
+}
+
+func DebugNameMatch(evname, name string) bool {
+ return os.Getenv(evname) == name
+}
+
+func (f *Func) spSb() (sp, sb *Value) {
+ initpos := f.Entry.Pos
+ for _, v := range f.Entry.Values {
+ if v.Op == OpSB {
+ sb = v
+ }
+ if v.Op == OpSP {
+ sp = v
+ }
+ if sb != nil && sp != nil {
+ break
+ }
+ }
+ if sb == nil {
+ sb = f.Entry.NewValue0(initpos.WithNotStmt(), OpSB, f.Config.Types.Uintptr)
+ }
+ if sp == nil {
+ sp = f.Entry.NewValue0(initpos.WithNotStmt(), OpSP, f.Config.Types.Uintptr)
+ }
+ return
+}
diff --git a/src/cmd/compile/internal/ssa/func_test.go b/src/cmd/compile/internal/ssa/func_test.go
new file mode 100644
index 0000000..568c643
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/func_test.go
@@ -0,0 +1,484 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains some utility functions to help define Funcs for testing.
+// As an example, the following func
+//
+// b1:
+// v1 = InitMem <mem>
+// Plain -> b2
+// b2:
+// Exit v1
+// b3:
+// v2 = Const <bool> [true]
+// If v2 -> b3 b2
+//
+// can be defined as
+//
+// fun := Fun("entry",
+// Bloc("entry",
+// Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+// Goto("exit")),
+// Bloc("exit",
+// Exit("mem")),
+// Bloc("deadblock",
+// Valu("deadval", OpConstBool, c.config.Types.Bool, 0, true),
+// If("deadval", "deadblock", "exit")))
+//
+// and the Blocks or Values used in the Func can be accessed
+// like this:
+// fun.blocks["entry"] or fun.values["deadval"]
+
+package ssa
+
+// TODO(matloob): Choose better names for Fun, Bloc, Goto, etc.
+// TODO(matloob): Write a parser for the Func disassembly. Maybe
+// the parser can be used instead of Fun.
+
+import (
+ "cmd/compile/internal/types"
+ "cmd/internal/obj"
+ "cmd/internal/src"
+ "fmt"
+ "reflect"
+ "testing"
+)
+
+// Compare two Funcs for equivalence. Their CFGs must be isomorphic,
+// and their values must correspond.
+// Requires that values and predecessors are in the same order, even
+// though Funcs could be equivalent when they are not.
+// TODO(matloob): Allow values and predecessors to be in different
+// orders if the CFG are otherwise equivalent.
+func Equiv(f, g *Func) bool {
+ valcor := make(map[*Value]*Value)
+ var checkVal func(fv, gv *Value) bool
+ checkVal = func(fv, gv *Value) bool {
+ if fv == nil && gv == nil {
+ return true
+ }
+ if valcor[fv] == nil && valcor[gv] == nil {
+ valcor[fv] = gv
+ valcor[gv] = fv
+ // Ignore ids. Ops and Types are compared for equality.
+ // TODO(matloob): Make sure types are canonical and can
+ // be compared for equality.
+ if fv.Op != gv.Op || fv.Type != gv.Type || fv.AuxInt != gv.AuxInt {
+ return false
+ }
+ if !reflect.DeepEqual(fv.Aux, gv.Aux) {
+ // This makes the assumption that aux values can be compared
+ // using DeepEqual.
+ // TODO(matloob): Aux values may be *gc.Sym pointers in the near
+ // future. Make sure they are canonical.
+ return false
+ }
+ if len(fv.Args) != len(gv.Args) {
+ return false
+ }
+ for i := range fv.Args {
+ if !checkVal(fv.Args[i], gv.Args[i]) {
+ return false
+ }
+ }
+ }
+ return valcor[fv] == gv && valcor[gv] == fv
+ }
+ blkcor := make(map[*Block]*Block)
+ var checkBlk func(fb, gb *Block) bool
+ checkBlk = func(fb, gb *Block) bool {
+ if blkcor[fb] == nil && blkcor[gb] == nil {
+ blkcor[fb] = gb
+ blkcor[gb] = fb
+ // ignore ids
+ if fb.Kind != gb.Kind {
+ return false
+ }
+ if len(fb.Values) != len(gb.Values) {
+ return false
+ }
+ for i := range fb.Values {
+ if !checkVal(fb.Values[i], gb.Values[i]) {
+ return false
+ }
+ }
+ if len(fb.Succs) != len(gb.Succs) {
+ return false
+ }
+ for i := range fb.Succs {
+ if !checkBlk(fb.Succs[i].b, gb.Succs[i].b) {
+ return false
+ }
+ }
+ if len(fb.Preds) != len(gb.Preds) {
+ return false
+ }
+ for i := range fb.Preds {
+ if !checkBlk(fb.Preds[i].b, gb.Preds[i].b) {
+ return false
+ }
+ }
+ return true
+
+ }
+ return blkcor[fb] == gb && blkcor[gb] == fb
+ }
+
+ return checkBlk(f.Entry, g.Entry)
+}
+
+// fun is the return type of Fun. It contains the created func
+// itself as well as indexes from block and value names into the
+// corresponding Blocks and Values.
+type fun struct {
+ f *Func
+ blocks map[string]*Block
+ values map[string]*Value
+}
+
+var emptyPass pass = pass{
+ name: "empty pass",
+}
+
+// AuxCallLSym returns an AuxCall initialized with an LSym that should pass "check"
+// as the Aux of a static call.
+func AuxCallLSym(name string) *AuxCall {
+ return &AuxCall{Fn: &obj.LSym{}}
+}
+
+// Fun takes the name of an entry bloc and a series of Bloc calls, and
+// returns a fun containing the composed Func. entry must be a name
+// supplied to one of the Bloc functions. Each of the bloc names and
+// valu names should be unique across the Fun.
+func (c *Conf) Fun(entry string, blocs ...bloc) fun {
+ f := NewFunc(c.Frontend())
+ f.Config = c.config
+ // TODO: Either mark some SSA tests as t.Parallel,
+ // or set up a shared Cache and Reset it between tests.
+ // But not both.
+ f.Cache = new(Cache)
+ f.pass = &emptyPass
+ f.cachedLineStarts = newXposmap(map[int]lineRange{0: {0, 100}, 1: {0, 100}, 2: {0, 100}, 3: {0, 100}, 4: {0, 100}})
+
+ blocks := make(map[string]*Block)
+ values := make(map[string]*Value)
+ // Create all the blocks and values.
+ for _, bloc := range blocs {
+ b := f.NewBlock(bloc.control.kind)
+ blocks[bloc.name] = b
+ for _, valu := range bloc.valus {
+ // args are filled in the second pass.
+ values[valu.name] = b.NewValue0IA(src.NoXPos, valu.op, valu.t, valu.auxint, valu.aux)
+ }
+ }
+ // Connect the blocks together and specify control values.
+ f.Entry = blocks[entry]
+ for _, bloc := range blocs {
+ b := blocks[bloc.name]
+ c := bloc.control
+ // Specify control values.
+ if c.control != "" {
+ cval, ok := values[c.control]
+ if !ok {
+ f.Fatalf("control value for block %s missing", bloc.name)
+ }
+ b.SetControl(cval)
+ }
+ // Fill in args.
+ for _, valu := range bloc.valus {
+ v := values[valu.name]
+ for _, arg := range valu.args {
+ a, ok := values[arg]
+ if !ok {
+ b.Fatalf("arg %s missing for value %s in block %s",
+ arg, valu.name, bloc.name)
+ }
+ v.AddArg(a)
+ }
+ }
+ // Connect to successors.
+ for _, succ := range c.succs {
+ b.AddEdgeTo(blocks[succ])
+ }
+ }
+ return fun{f, blocks, values}
+}
+
+// Bloc defines a block for Fun. The bloc name should be unique
+// across the containing Fun. entries should consist of calls to valu,
+// as well as one call to Goto, If, or Exit to specify the block kind.
+func Bloc(name string, entries ...interface{}) bloc {
+ b := bloc{}
+ b.name = name
+ seenCtrl := false
+ for _, e := range entries {
+ switch v := e.(type) {
+ case ctrl:
+ // there should be exactly one Ctrl entry.
+ if seenCtrl {
+ panic(fmt.Sprintf("already seen control for block %s", name))
+ }
+ b.control = v
+ seenCtrl = true
+ case valu:
+ b.valus = append(b.valus, v)
+ }
+ }
+ if !seenCtrl {
+ panic(fmt.Sprintf("block %s doesn't have control", b.name))
+ }
+ return b
+}
+
+// Valu defines a value in a block.
+func Valu(name string, op Op, t *types.Type, auxint int64, aux interface{}, args ...string) valu {
+ return valu{name, op, t, auxint, aux, args}
+}
+
+// Goto specifies that this is a BlockPlain and names the single successor.
+// TODO(matloob): choose a better name.
+func Goto(succ string) ctrl {
+ return ctrl{BlockPlain, "", []string{succ}}
+}
+
+// If specifies a BlockIf.
+func If(cond, sub, alt string) ctrl {
+ return ctrl{BlockIf, cond, []string{sub, alt}}
+}
+
+// Exit specifies a BlockExit.
+func Exit(arg string) ctrl {
+ return ctrl{BlockExit, arg, []string{}}
+}
+
+// Eq specifies a BlockAMD64EQ.
+func Eq(cond, sub, alt string) ctrl {
+ return ctrl{BlockAMD64EQ, cond, []string{sub, alt}}
+}
+
+// bloc, ctrl, and valu are internal structures used by Bloc, Valu, Goto,
+// If, and Exit to help define blocks.
+
+type bloc struct {
+ name string
+ control ctrl
+ valus []valu
+}
+
+type ctrl struct {
+ kind BlockKind
+ control string
+ succs []string
+}
+
+type valu struct {
+ name string
+ op Op
+ t *types.Type
+ auxint int64
+ aux interface{}
+ args []string
+}
+
+func TestArgs(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("a", OpConst64, c.config.Types.Int64, 14, nil),
+ Valu("b", OpConst64, c.config.Types.Int64, 26, nil),
+ Valu("sum", OpAdd64, c.config.Types.Int64, 0, nil, "a", "b"),
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+ sum := fun.values["sum"]
+ for i, name := range []string{"a", "b"} {
+ if sum.Args[i] != fun.values[name] {
+ t.Errorf("arg %d for sum is incorrect: want %s, got %s",
+ i, sum.Args[i], fun.values[name])
+ }
+ }
+}
+
+func TestEquiv(t *testing.T) {
+ cfg := testConfig(t)
+ equivalentCases := []struct{ f, g fun }{
+ // simple case
+ {
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("a", OpConst64, cfg.config.Types.Int64, 14, nil),
+ Valu("b", OpConst64, cfg.config.Types.Int64, 26, nil),
+ Valu("sum", OpAdd64, cfg.config.Types.Int64, 0, nil, "a", "b"),
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem"))),
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("a", OpConst64, cfg.config.Types.Int64, 14, nil),
+ Valu("b", OpConst64, cfg.config.Types.Int64, 26, nil),
+ Valu("sum", OpAdd64, cfg.config.Types.Int64, 0, nil, "a", "b"),
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem"))),
+ },
+ // block order changed
+ {
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("a", OpConst64, cfg.config.Types.Int64, 14, nil),
+ Valu("b", OpConst64, cfg.config.Types.Int64, 26, nil),
+ Valu("sum", OpAdd64, cfg.config.Types.Int64, 0, nil, "a", "b"),
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem"))),
+ cfg.Fun("entry",
+ Bloc("exit",
+ Exit("mem")),
+ Bloc("entry",
+ Valu("a", OpConst64, cfg.config.Types.Int64, 14, nil),
+ Valu("b", OpConst64, cfg.config.Types.Int64, 26, nil),
+ Valu("sum", OpAdd64, cfg.config.Types.Int64, 0, nil, "a", "b"),
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Goto("exit"))),
+ },
+ }
+ for _, c := range equivalentCases {
+ if !Equiv(c.f.f, c.g.f) {
+ t.Error("expected equivalence. Func definitions:")
+ t.Error(c.f.f)
+ t.Error(c.g.f)
+ }
+ }
+
+ differentCases := []struct{ f, g fun }{
+ // different shape
+ {
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem"))),
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Exit("mem"))),
+ },
+ // value order changed
+ {
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("b", OpConst64, cfg.config.Types.Int64, 26, nil),
+ Valu("a", OpConst64, cfg.config.Types.Int64, 14, nil),
+ Exit("mem"))),
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("a", OpConst64, cfg.config.Types.Int64, 14, nil),
+ Valu("b", OpConst64, cfg.config.Types.Int64, 26, nil),
+ Exit("mem"))),
+ },
+ // value auxint different
+ {
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("a", OpConst64, cfg.config.Types.Int64, 14, nil),
+ Exit("mem"))),
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("a", OpConst64, cfg.config.Types.Int64, 26, nil),
+ Exit("mem"))),
+ },
+ // value aux different
+ {
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("a", OpConst64, cfg.config.Types.Int64, 0, 14),
+ Exit("mem"))),
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("a", OpConst64, cfg.config.Types.Int64, 0, 26),
+ Exit("mem"))),
+ },
+ // value args different
+ {
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("a", OpConst64, cfg.config.Types.Int64, 14, nil),
+ Valu("b", OpConst64, cfg.config.Types.Int64, 26, nil),
+ Valu("sum", OpAdd64, cfg.config.Types.Int64, 0, nil, "a", "b"),
+ Exit("mem"))),
+ cfg.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("a", OpConst64, cfg.config.Types.Int64, 0, nil),
+ Valu("b", OpConst64, cfg.config.Types.Int64, 14, nil),
+ Valu("sum", OpAdd64, cfg.config.Types.Int64, 0, nil, "b", "a"),
+ Exit("mem"))),
+ },
+ }
+ for _, c := range differentCases {
+ if Equiv(c.f.f, c.g.f) {
+ t.Error("expected difference. Func definitions:")
+ t.Error(c.f.f)
+ t.Error(c.g.f)
+ }
+ }
+}
+
+// TestConstCache ensures that the cache will not return
+// reused free'd values with a non-matching AuxInt
+func TestConstCache(t *testing.T) {
+ c := testConfig(t)
+ f := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Exit("mem")))
+ v1 := f.f.ConstBool(c.config.Types.Bool, false)
+ v2 := f.f.ConstBool(c.config.Types.Bool, true)
+ f.f.freeValue(v1)
+ f.f.freeValue(v2)
+ v3 := f.f.ConstBool(c.config.Types.Bool, false)
+ v4 := f.f.ConstBool(c.config.Types.Bool, true)
+ if v3.AuxInt != 0 {
+ t.Errorf("expected %s to have auxint of 0\n", v3.LongString())
+ }
+ if v4.AuxInt != 1 {
+ t.Errorf("expected %s to have auxint of 1\n", v4.LongString())
+ }
+
+}
+
+// opcodeMap returns a map from opcode to the number of times that opcode
+// appears in the function.
+func opcodeMap(f *Func) map[Op]int {
+ m := map[Op]int{}
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ m[v.Op]++
+ }
+ }
+ return m
+}
+
+// opcodeCounts checks that the number of opcodes listed in m agree with the
+// number of opcodes that appear in the function.
+func checkOpcodeCounts(t *testing.T, f *Func, m map[Op]int) {
+ n := opcodeMap(f)
+ for op, cnt := range m {
+ if n[op] != cnt {
+ t.Errorf("%s appears %d times, want %d times", op, n[op], cnt)
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/fuse.go b/src/cmd/compile/internal/ssa/fuse.go
new file mode 100644
index 0000000..c51461c
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/fuse.go
@@ -0,0 +1,243 @@
+// 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 (
+ "cmd/internal/src"
+)
+
+// fuseEarly runs fuse(f, fuseTypePlain|fuseTypeIntInRange).
+func fuseEarly(f *Func) { fuse(f, fuseTypePlain|fuseTypeIntInRange) }
+
+// fuseLate runs fuse(f, fuseTypePlain|fuseTypeIf).
+func fuseLate(f *Func) { fuse(f, fuseTypePlain|fuseTypeIf) }
+
+type fuseType uint8
+
+const (
+ fuseTypePlain fuseType = 1 << iota
+ fuseTypeIf
+ fuseTypeIntInRange
+ fuseTypeShortCircuit
+)
+
+// fuse simplifies control flow by joining basic blocks.
+func fuse(f *Func, typ fuseType) {
+ for changed := true; changed; {
+ changed = false
+ // Fuse from end to beginning, to avoid quadratic behavior in fuseBlockPlain. See issue 13554.
+ for i := len(f.Blocks) - 1; i >= 0; i-- {
+ b := f.Blocks[i]
+ if typ&fuseTypeIf != 0 {
+ changed = fuseBlockIf(b) || changed
+ }
+ if typ&fuseTypeIntInRange != 0 {
+ changed = fuseIntegerComparisons(b) || changed
+ }
+ if typ&fuseTypePlain != 0 {
+ changed = fuseBlockPlain(b) || changed
+ }
+ if typ&fuseTypeShortCircuit != 0 {
+ changed = shortcircuitBlock(b) || changed
+ }
+ }
+ if changed {
+ f.invalidateCFG()
+ }
+ }
+}
+
+// fuseBlockIf handles the following cases where s0 and s1 are empty blocks.
+//
+// b b b b
+// / \ | \ / | | |
+// s0 s1 | s1 s0 | | |
+// \ / | / \ | | |
+// ss ss ss ss
+//
+// If all Phi ops in ss have identical variables for slots corresponding to
+// s0, s1 and b then the branch can be dropped.
+// This optimization often comes up in switch statements with multiple
+// expressions in a case clause:
+// switch n {
+// case 1,2,3: return 4
+// }
+// TODO: If ss doesn't contain any OpPhis, are s0 and s1 dead code anyway.
+func fuseBlockIf(b *Block) bool {
+ if b.Kind != BlockIf {
+ return false
+ }
+
+ var ss0, ss1 *Block
+ s0 := b.Succs[0].b
+ i0 := b.Succs[0].i
+ if s0.Kind != BlockPlain || len(s0.Preds) != 1 || !isEmpty(s0) {
+ s0, ss0 = b, s0
+ } else {
+ ss0 = s0.Succs[0].b
+ i0 = s0.Succs[0].i
+ }
+ s1 := b.Succs[1].b
+ i1 := b.Succs[1].i
+ if s1.Kind != BlockPlain || len(s1.Preds) != 1 || !isEmpty(s1) {
+ s1, ss1 = b, s1
+ } else {
+ ss1 = s1.Succs[0].b
+ i1 = s1.Succs[0].i
+ }
+
+ if ss0 != ss1 {
+ return false
+ }
+ ss := ss0
+
+ // s0 and s1 are equal with b if the corresponding block is missing
+ // (2nd, 3rd and 4th case in the figure).
+
+ for _, v := range ss.Values {
+ if v.Op == OpPhi && v.Uses > 0 && v.Args[i0] != v.Args[i1] {
+ return false
+ }
+ }
+
+ // Now we have two of following b->ss, b->s0->ss and b->s1->ss,
+ // with s0 and s1 empty if exist.
+ // We can replace it with b->ss without if all OpPhis in ss
+ // have identical predecessors (verified above).
+ // No critical edge is introduced because b will have one successor.
+ if s0 != b && s1 != b {
+ // Replace edge b->s0->ss with b->ss.
+ // We need to keep a slot for Phis corresponding to b.
+ b.Succs[0] = Edge{ss, i0}
+ ss.Preds[i0] = Edge{b, 0}
+ b.removeEdge(1)
+ s1.removeEdge(0)
+ } else if s0 != b {
+ b.removeEdge(0)
+ s0.removeEdge(0)
+ } else if s1 != b {
+ b.removeEdge(1)
+ s1.removeEdge(0)
+ } else {
+ b.removeEdge(1)
+ }
+ b.Kind = BlockPlain
+ b.Likely = BranchUnknown
+ b.ResetControls()
+
+ // Trash the empty blocks s0 and s1.
+ blocks := [...]*Block{s0, s1}
+ for _, s := range &blocks {
+ if s == b {
+ continue
+ }
+ // Move any (dead) values in s0 or s1 to b,
+ // where they will be eliminated by the next deadcode pass.
+ for _, v := range s.Values {
+ v.Block = b
+ }
+ b.Values = append(b.Values, s.Values...)
+ // Clear s.
+ s.Kind = BlockInvalid
+ s.Values = nil
+ s.Succs = nil
+ s.Preds = nil
+ }
+ return true
+}
+
+// isEmpty reports whether b contains any live values.
+// There may be false positives.
+func isEmpty(b *Block) bool {
+ for _, v := range b.Values {
+ if v.Uses > 0 || v.Op.IsCall() || v.Op.HasSideEffects() || v.Type.IsVoid() {
+ return false
+ }
+ }
+ return true
+}
+
+func fuseBlockPlain(b *Block) bool {
+ if b.Kind != BlockPlain {
+ return false
+ }
+
+ c := b.Succs[0].b
+ if len(c.Preds) != 1 {
+ return false
+ }
+
+ // If a block happened to end in a statement marker,
+ // try to preserve it.
+ if b.Pos.IsStmt() == src.PosIsStmt {
+ l := b.Pos.Line()
+ for _, v := range c.Values {
+ if v.Pos.IsStmt() == src.PosNotStmt {
+ continue
+ }
+ if l == v.Pos.Line() {
+ v.Pos = v.Pos.WithIsStmt()
+ l = 0
+ break
+ }
+ }
+ if l != 0 && c.Pos.Line() == l {
+ c.Pos = c.Pos.WithIsStmt()
+ }
+ }
+
+ // move all of b's values to c.
+ for _, v := range b.Values {
+ v.Block = c
+ }
+ // Use whichever value slice is larger, in the hopes of avoiding growth.
+ // However, take care to avoid c.Values pointing to b.valstorage.
+ // See golang.org/issue/18602.
+ // It's important to keep the elements in the same order; maintenance of
+ // debugging information depends on the order of *Values in Blocks.
+ // This can also cause changes in the order (which may affect other
+ // optimizations and possibly compiler output) for 32-vs-64 bit compilation
+ // platforms (word size affects allocation bucket size affects slice capacity).
+ if cap(c.Values) >= cap(b.Values) || len(b.Values) <= len(b.valstorage) {
+ bl := len(b.Values)
+ cl := len(c.Values)
+ var t []*Value // construct t = b.Values followed-by c.Values, but with attention to allocation.
+ if cap(c.Values) < bl+cl {
+ // reallocate
+ t = make([]*Value, bl+cl)
+ } else {
+ // in place.
+ t = c.Values[0 : bl+cl]
+ }
+ copy(t[bl:], c.Values) // possibly in-place
+ c.Values = t
+ copy(c.Values, b.Values)
+ } else {
+ c.Values = append(b.Values, c.Values...)
+ }
+
+ // replace b->c edge with preds(b) -> c
+ c.predstorage[0] = Edge{}
+ if len(b.Preds) > len(b.predstorage) {
+ c.Preds = b.Preds
+ } else {
+ c.Preds = append(c.predstorage[:0], b.Preds...)
+ }
+ for i, e := range c.Preds {
+ p := e.b
+ p.Succs[e.i] = Edge{c, i}
+ }
+ f := b.Func
+ if f.Entry == b {
+ f.Entry = c
+ }
+
+ // trash b, just in case
+ b.Kind = BlockInvalid
+ b.Values = nil
+ b.Preds = nil
+ b.Succs = nil
+ return true
+}
diff --git a/src/cmd/compile/internal/ssa/fuse_comparisons.go b/src/cmd/compile/internal/ssa/fuse_comparisons.go
new file mode 100644
index 0000000..d843fc3
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/fuse_comparisons.go
@@ -0,0 +1,157 @@
+// Copyright 2019 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
+
+// fuseIntegerComparisons optimizes inequalities such as '1 <= x && x < 5',
+// which can be optimized to 'unsigned(x-1) < 4'.
+//
+// Look for branch structure like:
+//
+// p
+// |\
+// | b
+// |/ \
+// s0 s1
+//
+// In our example, p has control '1 <= x', b has control 'x < 5',
+// and s0 and s1 are the if and else results of the comparison.
+//
+// This will be optimized into:
+//
+// p
+// \
+// b
+// / \
+// s0 s1
+//
+// where b has the combined control value 'unsigned(x-1) < 4'.
+// Later passes will then fuse p and b.
+func fuseIntegerComparisons(b *Block) bool {
+ if len(b.Preds) != 1 {
+ return false
+ }
+ p := b.Preds[0].Block()
+ if b.Kind != BlockIf || p.Kind != BlockIf {
+ return false
+ }
+
+ // Don't merge control values if b is likely to be bypassed anyway.
+ if p.Likely == BranchLikely && p.Succs[0].Block() != b {
+ return false
+ }
+ if p.Likely == BranchUnlikely && p.Succs[1].Block() != b {
+ return false
+ }
+
+ // Check if the control values combine to make an integer inequality that
+ // can be further optimized later.
+ bc := b.Controls[0]
+ pc := p.Controls[0]
+ if !areMergeableInequalities(bc, pc) {
+ return false
+ }
+
+ // If the first (true) successors match then we have a disjunction (||).
+ // If the second (false) successors match then we have a conjunction (&&).
+ for i, op := range [2]Op{OpOrB, OpAndB} {
+ if p.Succs[i].Block() != b.Succs[i].Block() {
+ continue
+ }
+
+ // TODO(mundaym): should we also check the cost of executing b?
+ // Currently we might speculatively execute b even if b contains
+ // a lot of instructions. We could just check that len(b.Values)
+ // is lower than a fixed amount. Bear in mind however that the
+ // other optimization passes might yet reduce the cost of b
+ // significantly so we shouldn't be overly conservative.
+ if !canSpeculativelyExecute(b) {
+ return false
+ }
+
+ // Logically combine the control values for p and b.
+ v := b.NewValue0(bc.Pos, op, bc.Type)
+ v.AddArg(pc)
+ v.AddArg(bc)
+
+ // Set the combined control value as the control value for b.
+ b.SetControl(v)
+
+ // Modify p so that it jumps directly to b.
+ p.removeEdge(i)
+ p.Kind = BlockPlain
+ p.Likely = BranchUnknown
+ p.ResetControls()
+
+ return true
+ }
+
+ // TODO: could negate condition(s) to merge controls.
+ return false
+}
+
+// getConstIntArgIndex returns the index of the first argument that is a
+// constant integer or -1 if no such argument exists.
+func getConstIntArgIndex(v *Value) int {
+ for i, a := range v.Args {
+ switch a.Op {
+ case OpConst8, OpConst16, OpConst32, OpConst64:
+ return i
+ }
+ }
+ return -1
+}
+
+// isSignedInequality reports whether op represents the inequality < or ≤
+// in the signed domain.
+func isSignedInequality(v *Value) bool {
+ switch v.Op {
+ case OpLess64, OpLess32, OpLess16, OpLess8,
+ OpLeq64, OpLeq32, OpLeq16, OpLeq8:
+ return true
+ }
+ return false
+}
+
+// isUnsignedInequality reports whether op represents the inequality < or ≤
+// in the unsigned domain.
+func isUnsignedInequality(v *Value) bool {
+ switch v.Op {
+ case OpLess64U, OpLess32U, OpLess16U, OpLess8U,
+ OpLeq64U, OpLeq32U, OpLeq16U, OpLeq8U:
+ return true
+ }
+ return false
+}
+
+func areMergeableInequalities(x, y *Value) bool {
+ // We need both inequalities to be either in the signed or unsigned domain.
+ // TODO(mundaym): it would also be good to merge when we have an Eq op that
+ // could be transformed into a Less/Leq. For example in the unsigned
+ // domain 'x == 0 || 3 < x' is equivalent to 'x <= 0 || 3 < x'
+ inequalityChecks := [...]func(*Value) bool{
+ isSignedInequality,
+ isUnsignedInequality,
+ }
+ for _, f := range inequalityChecks {
+ if !f(x) || !f(y) {
+ continue
+ }
+
+ // Check that both inequalities are comparisons with constants.
+ xi := getConstIntArgIndex(x)
+ if xi < 0 {
+ return false
+ }
+ yi := getConstIntArgIndex(y)
+ if yi < 0 {
+ return false
+ }
+
+ // Check that the non-constant arguments to the inequalities
+ // are the same.
+ return x.Args[xi^1] == y.Args[yi^1]
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/fuse_test.go b/src/cmd/compile/internal/ssa/fuse_test.go
new file mode 100644
index 0000000..1519099
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/fuse_test.go
@@ -0,0 +1,203 @@
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "fmt"
+ "strconv"
+ "testing"
+)
+
+func TestFuseEliminatesOneBranch(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
+ Valu("nilptr", OpConstNil, ptrType, 0, nil),
+ Valu("bool1", OpNeqPtr, c.config.Types.Bool, 0, nil, "ptr1", "nilptr"),
+ If("bool1", "then", "exit")),
+ Bloc("then",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ fuseLate(fun.f)
+
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["then"] && b.Kind != BlockInvalid {
+ t.Errorf("then was not eliminated, but should have")
+ }
+ }
+}
+
+func TestFuseEliminatesBothBranches(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
+ Valu("nilptr", OpConstNil, ptrType, 0, nil),
+ Valu("bool1", OpNeqPtr, c.config.Types.Bool, 0, nil, "ptr1", "nilptr"),
+ If("bool1", "then", "else")),
+ Bloc("then",
+ Goto("exit")),
+ Bloc("else",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ fuseLate(fun.f)
+
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["then"] && b.Kind != BlockInvalid {
+ t.Errorf("then was not eliminated, but should have")
+ }
+ if b == fun.blocks["else"] && b.Kind != BlockInvalid {
+ t.Errorf("else was not eliminated, but should have")
+ }
+ }
+}
+
+func TestFuseHandlesPhis(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
+ Valu("nilptr", OpConstNil, ptrType, 0, nil),
+ Valu("bool1", OpNeqPtr, c.config.Types.Bool, 0, nil, "ptr1", "nilptr"),
+ If("bool1", "then", "else")),
+ Bloc("then",
+ Goto("exit")),
+ Bloc("else",
+ Goto("exit")),
+ Bloc("exit",
+ Valu("phi", OpPhi, ptrType, 0, nil, "ptr1", "ptr1"),
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ fuseLate(fun.f)
+
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["then"] && b.Kind != BlockInvalid {
+ t.Errorf("then was not eliminated, but should have")
+ }
+ if b == fun.blocks["else"] && b.Kind != BlockInvalid {
+ t.Errorf("else was not eliminated, but should have")
+ }
+ }
+}
+
+func TestFuseEliminatesEmptyBlocks(t *testing.T) {
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("z0")),
+ Bloc("z1",
+ Goto("z2")),
+ Bloc("z3",
+ Goto("exit")),
+ Bloc("z2",
+ Goto("z3")),
+ Bloc("z0",
+ Goto("z1")),
+ Bloc("exit",
+ Exit("mem"),
+ ))
+
+ CheckFunc(fun.f)
+ fuseLate(fun.f)
+
+ for k, b := range fun.blocks {
+ if k[:1] == "z" && b.Kind != BlockInvalid {
+ t.Errorf("%s was not eliminated, but should have", k)
+ }
+ }
+}
+
+func TestFuseSideEffects(t *testing.T) {
+ // Test that we don't fuse branches that have side effects but
+ // have no use (e.g. followed by infinite loop).
+ // See issue #36005.
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("b", OpArg, c.config.Types.Bool, 0, nil),
+ If("b", "then", "else")),
+ Bloc("then",
+ Valu("call1", OpStaticCall, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
+ Goto("empty")),
+ Bloc("else",
+ Valu("call2", OpStaticCall, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
+ Goto("empty")),
+ Bloc("empty",
+ Goto("loop")),
+ Bloc("loop",
+ Goto("loop")))
+
+ CheckFunc(fun.f)
+ fuseLate(fun.f)
+
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["then"] && b.Kind == BlockInvalid {
+ t.Errorf("then is eliminated, but should not")
+ }
+ if b == fun.blocks["else"] && b.Kind == BlockInvalid {
+ t.Errorf("else is eliminated, but should not")
+ }
+ }
+}
+
+func BenchmarkFuse(b *testing.B) {
+ for _, n := range [...]int{1, 10, 100, 1000, 10000} {
+ b.Run(strconv.Itoa(n), func(b *testing.B) {
+ c := testConfig(b)
+
+ blocks := make([]bloc, 0, 2*n+3)
+ blocks = append(blocks,
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("cond", OpArg, c.config.Types.Bool, 0, nil),
+ Valu("x", OpArg, c.config.Types.Int64, 0, nil),
+ Goto("exit")))
+
+ phiArgs := make([]string, 0, 2*n)
+ for i := 0; i < n; i++ {
+ cname := fmt.Sprintf("c%d", i)
+ blocks = append(blocks,
+ Bloc(fmt.Sprintf("b%d", i), If("cond", cname, "merge")),
+ Bloc(cname, Goto("merge")))
+ phiArgs = append(phiArgs, "x", "x")
+ }
+ blocks = append(blocks,
+ Bloc("merge",
+ Valu("phi", OpPhi, types.TypeMem, 0, nil, phiArgs...),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ fun := c.Fun("entry", blocks...)
+ fuseLate(fun.f)
+ }
+ })
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/gen/386.rules b/src/cmd/compile/internal/ssa/gen/386.rules
new file mode 100644
index 0000000..fbc12fd
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/386.rules
@@ -0,0 +1,1111 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Lowering arithmetic
+(Add(Ptr|32|16|8) ...) => (ADDL ...)
+(Add(32|64)F ...) => (ADDS(S|D) ...)
+(Add32carry ...) => (ADDLcarry ...)
+(Add32withcarry ...) => (ADCL ...)
+
+(Sub(Ptr|32|16|8) ...) => (SUBL ...)
+(Sub(32|64)F ...) => (SUBS(S|D) ...)
+(Sub32carry ...) => (SUBLcarry ...)
+(Sub32withcarry ...) => (SBBL ...)
+
+(Mul(32|16|8) ...) => (MULL ...)
+(Mul(32|64)F ...) => (MULS(S|D) ...)
+(Mul32uhilo ...) => (MULLQU ...)
+
+(Select0 (Mul32uover x y)) => (Select0 <typ.UInt32> (MULLU x y))
+(Select1 (Mul32uover x y)) => (SETO (Select1 <types.TypeFlags> (MULLU x y)))
+
+(Avg32u ...) => (AVGLU ...)
+
+(Div(32|64)F ...) => (DIVS(S|D) ...)
+(Div(32|32u|16|16u) ...) => (DIV(L|LU|W|WU) ...)
+(Div8 x y) => (DIVW (SignExt8to16 x) (SignExt8to16 y))
+(Div8u x y) => (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y))
+
+(Hmul(32|32u) ...) => (HMUL(L|LU) ...)
+
+(Mod(32|32u|16|16u) ...) => (MOD(L|LU|W|WU) ...)
+(Mod8 x y) => (MODW (SignExt8to16 x) (SignExt8to16 y))
+(Mod8u x y) => (MODWU (ZeroExt8to16 x) (ZeroExt8to16 y))
+
+(And(32|16|8) ...) => (ANDL ...)
+(Or(32|16|8) ...) => (ORL ...)
+(Xor(32|16|8) ...) => (XORL ...)
+
+(Neg(32|16|8) ...) => (NEGL ...)
+(Neg32F x) => (PXOR x (MOVSSconst <typ.Float32> [float32(math.Copysign(0, -1))]))
+(Neg64F x) => (PXOR x (MOVSDconst <typ.Float64> [math.Copysign(0, -1)]))
+
+(Com(32|16|8) ...) => (NOTL ...)
+
+// Lowering boolean ops
+(AndB ...) => (ANDL ...)
+(OrB ...) => (ORL ...)
+(Not x) => (XORLconst [1] x)
+
+// Lowering pointer arithmetic
+(OffPtr [off] ptr) => (ADDLconst [int32(off)] ptr)
+
+(Bswap32 ...) => (BSWAPL ...)
+
+(Sqrt ...) => (SQRTSD ...)
+
+(Ctz16 x) => (BSFL (ORLconst <typ.UInt32> [0x10000] x))
+(Ctz16NonZero ...) => (BSFL ...)
+
+// Lowering extension
+(SignExt8to16 ...) => (MOVBLSX ...)
+(SignExt8to32 ...) => (MOVBLSX ...)
+(SignExt16to32 ...) => (MOVWLSX ...)
+
+(ZeroExt8to16 ...) => (MOVBLZX ...)
+(ZeroExt8to32 ...) => (MOVBLZX ...)
+(ZeroExt16to32 ...) => (MOVWLZX ...)
+
+(Signmask x) => (SARLconst x [31])
+(Zeromask <t> x) => (XORLconst [-1] (SBBLcarrymask <t> (CMPLconst x [1])))
+(Slicemask <t> x) => (SARLconst (NEGL <t> x) [31])
+
+// Lowering truncation
+// Because we ignore high parts of registers, truncates are just copies.
+(Trunc16to8 ...) => (Copy ...)
+(Trunc32to8 ...) => (Copy ...)
+(Trunc32to16 ...) => (Copy ...)
+
+// Lowering float-int conversions
+(Cvt32to32F ...) => (CVTSL2SS ...)
+(Cvt32to64F ...) => (CVTSL2SD ...)
+
+(Cvt32Fto32 ...) => (CVTTSS2SL ...)
+(Cvt64Fto32 ...) => (CVTTSD2SL ...)
+
+(Cvt32Fto64F ...) => (CVTSS2SD ...)
+(Cvt64Fto32F ...) => (CVTSD2SS ...)
+
+(Round32F ...) => (Copy ...)
+(Round64F ...) => (Copy ...)
+
+(CvtBoolToUint8 ...) => (Copy ...)
+
+// Lowering shifts
+// Unsigned shifts need to return 0 if shift amount is >= width of shifted value.
+// result = (arg << shift) & (shift >= argbits ? 0 : 0xffffffffffffffff)
+(Lsh32x(32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMP(L|W|B)const y [32])))
+(Lsh16x(32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMP(L|W|B)const y [32])))
+(Lsh8x(32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMP(L|W|B)const y [32])))
+
+(Lsh32x(32|16|8) <t> x y) && shiftIsBounded(v) => (SHLL <t> x y)
+(Lsh16x(32|16|8) <t> x y) && shiftIsBounded(v) => (SHLL <t> x y)
+(Lsh8x(32|16|8) <t> x y) && shiftIsBounded(v) => (SHLL <t> x y)
+
+(Rsh32Ux(32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMP(L|W|B)const y [32])))
+(Rsh16Ux(32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMP(L|W|B)const y [16])))
+(Rsh8Ux(32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMP(L|W|B)const y [8])))
+
+(Rsh32Ux(32|16|8) <t> x y) && shiftIsBounded(v) => (SHRL <t> x y)
+(Rsh16Ux(32|16|8) <t> x y) && shiftIsBounded(v) => (SHRW <t> x y)
+(Rsh8Ux(32|16|8) <t> x y) && shiftIsBounded(v) => (SHRB <t> x 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.
+
+(Rsh32x(32|16|8) <t> x y) && !shiftIsBounded(v) => (SARL <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMP(L|W|B)const y [32])))))
+(Rsh16x(32|16|8) <t> x y) && !shiftIsBounded(v) => (SARW <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMP(L|W|B)const y [16])))))
+(Rsh8x(32|16|8) <t> x y) && !shiftIsBounded(v) => (SARB <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMP(L|W|B)const y [8])))))
+
+(Rsh32x(32|16|8) <t> x y) && shiftIsBounded(v) => (SARL x y)
+(Rsh16x(32|16|8) <t> x y) && shiftIsBounded(v) => (SARW x y)
+(Rsh8x(32|16|8) <t> x y) && shiftIsBounded(v) => (SARB x y)
+
+// constant shifts
+// generic opt rewrites all constant shifts to shift by Const64
+(Lsh32x64 x (Const64 [c])) && uint64(c) < 32 => (SHLLconst x [int32(c)])
+(Rsh32x64 x (Const64 [c])) && uint64(c) < 32 => (SARLconst x [int32(c)])
+(Rsh32Ux64 x (Const64 [c])) && uint64(c) < 32 => (SHRLconst x [int32(c)])
+(Lsh16x64 x (Const64 [c])) && uint64(c) < 16 => (SHLLconst x [int32(c)])
+(Rsh16x64 x (Const64 [c])) && uint64(c) < 16 => (SARWconst x [int16(c)])
+(Rsh16Ux64 x (Const64 [c])) && uint64(c) < 16 => (SHRWconst x [int16(c)])
+(Lsh8x64 x (Const64 [c])) && uint64(c) < 8 => (SHLLconst x [int32(c)])
+(Rsh8x64 x (Const64 [c])) && uint64(c) < 8 => (SARBconst x [int8(c)])
+(Rsh8Ux64 x (Const64 [c])) && uint64(c) < 8 => (SHRBconst x [int8(c)])
+
+// large constant shifts
+(Lsh32x64 _ (Const64 [c])) && uint64(c) >= 32 => (Const32 [0])
+(Rsh32Ux64 _ (Const64 [c])) && uint64(c) >= 32 => (Const32 [0])
+(Lsh16x64 _ (Const64 [c])) && uint64(c) >= 16 => (Const16 [0])
+(Rsh16Ux64 _ (Const64 [c])) && uint64(c) >= 16 => (Const16 [0])
+(Lsh8x64 _ (Const64 [c])) && uint64(c) >= 8 => (Const8 [0])
+(Rsh8Ux64 _ (Const64 [c])) && uint64(c) >= 8 => (Const8 [0])
+
+// large constant signed right shift, we leave the sign bit
+(Rsh32x64 x (Const64 [c])) && uint64(c) >= 32 => (SARLconst x [31])
+(Rsh16x64 x (Const64 [c])) && uint64(c) >= 16 => (SARWconst x [15])
+(Rsh8x64 x (Const64 [c])) && uint64(c) >= 8 => (SARBconst x [7])
+
+// constant rotates
+(RotateLeft32 x (MOVLconst [c])) => (ROLLconst [c&31] x)
+(RotateLeft16 x (MOVLconst [c])) => (ROLWconst [int16(c&15)] x)
+(RotateLeft8 x (MOVLconst [c])) => (ROLBconst [int8(c&7)] x)
+
+// Lowering comparisons
+(Less32 x y) => (SETL (CMPL x y))
+(Less16 x y) => (SETL (CMPW x y))
+(Less8 x y) => (SETL (CMPB 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))
+
+(Leq32 x y) => (SETLE (CMPL x y))
+(Leq16 x y) => (SETLE (CMPW x y))
+(Leq8 x y) => (SETLE (CMPB 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))
+
+(Eq32 x y) => (SETEQ (CMPL x y))
+(Eq16 x y) => (SETEQ (CMPW x y))
+(Eq8 x y) => (SETEQ (CMPB x y))
+(EqB x y) => (SETEQ (CMPB x y))
+(EqPtr x y) => (SETEQ (CMPL x y))
+(Eq64F x y) => (SETEQF (UCOMISD x y))
+(Eq32F x y) => (SETEQF (UCOMISS x y))
+
+(Neq32 x y) => (SETNE (CMPL x y))
+(Neq16 x y) => (SETNE (CMPW x y))
+(Neq8 x y) => (SETNE (CMPB x y))
+(NeqB x y) => (SETNE (CMPB x y))
+(NeqPtr x y) => (SETNE (CMPL x y))
+(Neq64F x y) => (SETNEF (UCOMISD x y))
+(Neq32F x y) => (SETNEF (UCOMISS x y))
+
+// Lowering loads
+(Load <t> ptr mem) && (is32BitInt(t) || isPtr(t)) => (MOVLload ptr mem)
+(Load <t> ptr mem) && is16BitInt(t) => (MOVWload ptr mem)
+(Load <t> ptr mem) && (t.IsBoolean() || is8BitInt(t)) => (MOVBload ptr mem)
+(Load <t> ptr mem) && is32BitFloat(t) => (MOVSSload ptr mem)
+(Load <t> ptr mem) && is64BitFloat(t) => (MOVSDload ptr mem)
+
+// Lowering stores
+// These more-specific FP versions of Store pattern should come first.
+(Store {t} ptr val mem) && t.Size() == 8 && is64BitFloat(val.Type) => (MOVSDstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && is32BitFloat(val.Type) => (MOVSSstore ptr val mem)
+
+(Store {t} ptr val mem) && t.Size() == 4 => (MOVLstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 2 => (MOVWstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 1 => (MOVBstore ptr val mem)
+
+// Lowering moves
+(Move [0] _ _ mem) => mem
+(Move [1] dst src mem) => (MOVBstore dst (MOVBload src mem) mem)
+(Move [2] dst src mem) => (MOVWstore dst (MOVWload src mem) mem)
+(Move [4] dst src mem) => (MOVLstore dst (MOVLload src mem) mem)
+(Move [3] dst src mem) =>
+ (MOVBstore [2] dst (MOVBload [2] src mem)
+ (MOVWstore dst (MOVWload src mem) mem))
+(Move [5] dst src mem) =>
+ (MOVBstore [4] dst (MOVBload [4] src mem)
+ (MOVLstore dst (MOVLload src mem) mem))
+(Move [6] dst src mem) =>
+ (MOVWstore [4] dst (MOVWload [4] src mem)
+ (MOVLstore dst (MOVLload src mem) mem))
+(Move [7] dst src mem) =>
+ (MOVLstore [3] dst (MOVLload [3] src mem)
+ (MOVLstore dst (MOVLload src mem) mem))
+(Move [8] dst src mem) =>
+ (MOVLstore [4] dst (MOVLload [4] src mem)
+ (MOVLstore dst (MOVLload src mem) mem))
+
+// Adjust moves to be a multiple of 4 bytes.
+(Move [s] dst src mem)
+ && s > 8 && s%4 != 0 =>
+ (Move [s-s%4]
+ (ADDLconst <dst.Type> dst [int32(s%4)])
+ (ADDLconst <src.Type> src [int32(s%4)])
+ (MOVLstore dst (MOVLload src mem) mem))
+
+// Medium copying uses a duff device.
+(Move [s] dst src mem)
+ && s > 8 && s <= 4*128 && s%4 == 0
+ && !config.noDuffDevice && logLargeCopy(v, s) =>
+ (DUFFCOPY [10*(128-s/4)] dst src mem)
+// 10 and 128 are magic constants. 10 is the number of bytes to encode:
+// MOVL (SI), CX
+// ADDL $4, SI
+// MOVL CX, (DI)
+// ADDL $4, DI
+// and 128 is the number of such blocks. See src/runtime/duff_386.s:duffcopy.
+
+// Large copying uses REP MOVSL.
+(Move [s] dst src mem) && (s > 4*128 || config.noDuffDevice) && s%4 == 0 && logLargeCopy(v, s) =>
+ (REPMOVSL dst src (MOVLconst [int32(s/4)]) mem)
+
+// Lowering Zero instructions
+(Zero [0] _ mem) => mem
+(Zero [1] destptr mem) => (MOVBstoreconst [0] destptr mem)
+(Zero [2] destptr mem) => (MOVWstoreconst [0] destptr mem)
+(Zero [4] destptr mem) => (MOVLstoreconst [0] destptr mem)
+
+(Zero [3] destptr mem) =>
+ (MOVBstoreconst [makeValAndOff32(0,2)] destptr
+ (MOVWstoreconst [makeValAndOff32(0,0)] destptr mem))
+(Zero [5] destptr mem) =>
+ (MOVBstoreconst [makeValAndOff32(0,4)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+(Zero [6] destptr mem) =>
+ (MOVWstoreconst [makeValAndOff32(0,4)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+(Zero [7] destptr mem) =>
+ (MOVLstoreconst [makeValAndOff32(0,3)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+
+// Strip off any fractional word zeroing.
+(Zero [s] destptr mem) && s%4 != 0 && s > 4 =>
+ (Zero [s-s%4] (ADDLconst destptr [int32(s%4)])
+ (MOVLstoreconst [0] destptr mem))
+
+// Zero small numbers of words directly.
+(Zero [8] destptr mem) =>
+ (MOVLstoreconst [makeValAndOff32(0,4)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+(Zero [12] destptr mem) =>
+ (MOVLstoreconst [makeValAndOff32(0,8)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,4)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem)))
+(Zero [16] destptr mem) =>
+ (MOVLstoreconst [makeValAndOff32(0,12)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,8)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,4)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))))
+
+// Medium zeroing uses a duff device.
+(Zero [s] destptr mem)
+ && s > 16 && s <= 4*128 && s%4 == 0
+ && !config.noDuffDevice =>
+ (DUFFZERO [1*(128-s/4)] destptr (MOVLconst [0]) mem)
+// 1 and 128 are magic constants. 1 is the number of bytes to encode STOSL.
+// 128 is the number of STOSL instructions in duffzero.
+// See src/runtime/duff_386.s:duffzero.
+
+// Large zeroing uses REP STOSQ.
+(Zero [s] destptr mem)
+ && (s > 4*128 || (config.noDuffDevice && s > 16))
+ && s%4 == 0 =>
+ (REPSTOSL destptr (MOVLconst [int32(s/4)]) (MOVLconst [0]) mem)
+
+
+// Lowering constants
+(Const8 [c]) => (MOVLconst [int32(c)])
+(Const16 [c]) => (MOVLconst [int32(c)])
+(Const32 ...) => (MOVLconst ...)
+(Const(32|64)F ...) => (MOVS(S|D)const ...)
+(ConstNil) => (MOVLconst [0])
+(ConstBool [c]) => (MOVLconst [b2i32(c)])
+
+// Lowering calls
+(StaticCall ...) => (CALLstatic ...)
+(ClosureCall ...) => (CALLclosure ...)
+(InterCall ...) => (CALLinter ...)
+
+// Miscellaneous
+(IsNonNil p) => (SETNE (TESTL p p))
+(IsInBounds idx len) => (SETB (CMPL idx len))
+(IsSliceInBounds idx len) => (SETBE (CMPL idx len))
+(NilCheck ...) => (LoweredNilCheck ...)
+(GetG ...) => (LoweredGetG ...)
+(GetClosurePtr ...) => (LoweredGetClosurePtr ...)
+(GetCallerPC ...) => (LoweredGetCallerPC ...)
+(GetCallerSP ...) => (LoweredGetCallerSP ...)
+(Addr {sym} base) => (LEAL {sym} base)
+(LocalAddr {sym} base _) => (LEAL {sym} base)
+
+// 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)
+(If (SETO cmp) yes no) => (OS 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) => (NEF cmp yes no)
+
+(If cond yes no) => (NE (TESTB cond cond) yes no)
+
+// Write barrier.
+(WB ...) => (LoweredWB ...)
+
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
+
+(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 0 => (LoweredPanicExtendA [kind] hi lo y mem)
+(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 1 => (LoweredPanicExtendB [kind] hi lo y mem)
+(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 2 => (LoweredPanicExtendC [kind] hi lo y mem)
+
+// ***************************
+// Above: lowering rules
+// Below: optimizations
+// ***************************
+// TODO: Should the optimizations be a separate pass?
+
+// Fold boolean tests into blocks
+(NE (TESTB (SETL cmp) (SETL cmp)) yes no) => (LT cmp yes no)
+(NE (TESTB (SETLE cmp) (SETLE cmp)) yes no) => (LE cmp yes no)
+(NE (TESTB (SETG cmp) (SETG cmp)) yes no) => (GT cmp yes no)
+(NE (TESTB (SETGE cmp) (SETGE cmp)) yes no) => (GE cmp yes no)
+(NE (TESTB (SETEQ cmp) (SETEQ cmp)) yes no) => (EQ cmp yes no)
+(NE (TESTB (SETNE cmp) (SETNE cmp)) yes no) => (NE cmp yes no)
+(NE (TESTB (SETB cmp) (SETB cmp)) yes no) => (ULT cmp yes no)
+(NE (TESTB (SETBE cmp) (SETBE cmp)) yes no) => (ULE cmp yes no)
+(NE (TESTB (SETA cmp) (SETA cmp)) yes no) => (UGT cmp yes no)
+(NE (TESTB (SETAE cmp) (SETAE cmp)) yes no) => (UGE cmp yes no)
+(NE (TESTB (SETO cmp) (SETO cmp)) yes no) => (OS cmp yes no)
+
+// Special case for floating point - LF/LEF not generated
+(NE (TESTB (SETGF cmp) (SETGF cmp)) yes no) => (UGT cmp yes no)
+(NE (TESTB (SETGEF cmp) (SETGEF cmp)) yes no) => (UGE cmp yes no)
+(NE (TESTB (SETEQF cmp) (SETEQF cmp)) yes no) => (EQF cmp yes no)
+(NE (TESTB (SETNEF cmp) (SETNEF cmp)) yes no) => (NEF cmp yes no)
+
+// fold constants into instructions
+(ADDL x (MOVLconst [c])) => (ADDLconst [c] x)
+(ADDLcarry x (MOVLconst [c])) => (ADDLconstcarry [c] x)
+(ADCL x (MOVLconst [c]) f) => (ADCLconst [c] x f)
+
+(SUBL x (MOVLconst [c])) => (SUBLconst x [c])
+(SUBL (MOVLconst [c]) x) => (NEGL (SUBLconst <v.Type> x [c]))
+(SUBLcarry x (MOVLconst [c])) => (SUBLconstcarry [c] x)
+(SBBL x (MOVLconst [c]) f) => (SBBLconst [c] x f)
+
+(MULL x (MOVLconst [c])) => (MULLconst [c] x)
+(ANDL x (MOVLconst [c])) => (ANDLconst [c] x)
+
+(ANDLconst [c] (ANDLconst [d] x)) => (ANDLconst [c & d] x)
+(XORLconst [c] (XORLconst [d] x)) => (XORLconst [c ^ d] x)
+(MULLconst [c] (MULLconst [d] x)) => (MULLconst [c * d] x)
+
+(ORL x (MOVLconst [c])) => (ORLconst [c] x)
+(XORL x (MOVLconst [c])) => (XORLconst [c] x)
+
+(SHLL x (MOVLconst [c])) => (SHLLconst [c&31] x)
+(SHRL x (MOVLconst [c])) => (SHRLconst [c&31] x)
+(SHRW x (MOVLconst [c])) && c&31 < 16 => (SHRWconst [int16(c&31)] x)
+(SHRW _ (MOVLconst [c])) && c&31 >= 16 => (MOVLconst [0])
+(SHRB x (MOVLconst [c])) && c&31 < 8 => (SHRBconst [int8(c&31)] x)
+(SHRB _ (MOVLconst [c])) && c&31 >= 8 => (MOVLconst [0])
+
+(SARL x (MOVLconst [c])) => (SARLconst [c&31] x)
+(SARW x (MOVLconst [c])) => (SARWconst [int16(min(int64(c&31),15))] x)
+(SARB x (MOVLconst [c])) => (SARBconst [int8(min(int64(c&31),7))] x)
+
+(SARL x (ANDLconst [31] y)) => (SARL x y)
+(SHLL x (ANDLconst [31] y)) => (SHLL x y)
+(SHRL x (ANDLconst [31] y)) => (SHRL x y)
+
+// Rotate instructions
+
+(ADDL (SHLLconst [c] x) (SHRLconst [d] x)) && d == 32-c => (ROLLconst [c] x)
+( ORL (SHLLconst [c] x) (SHRLconst [d] x)) && d == 32-c => (ROLLconst [c] x)
+(XORL (SHLLconst [c] x) (SHRLconst [d] x)) && d == 32-c => (ROLLconst [c] x)
+
+(ADDL <t> (SHLLconst x [c]) (SHRWconst x [d])) && c < 16 && d == int16(16-c) && t.Size() == 2
+ => (ROLWconst x [int16(c)])
+( ORL <t> (SHLLconst x [c]) (SHRWconst x [d])) && c < 16 && d == int16(16-c) && t.Size() == 2
+ => (ROLWconst x [int16(c)])
+(XORL <t> (SHLLconst x [c]) (SHRWconst x [d])) && c < 16 && d == int16(16-c) && t.Size() == 2
+ => (ROLWconst x [int16(c)])
+
+(ADDL <t> (SHLLconst x [c]) (SHRBconst x [d])) && c < 8 && d == int8(8-c) && t.Size() == 1
+ => (ROLBconst x [int8(c)])
+( ORL <t> (SHLLconst x [c]) (SHRBconst x [d])) && c < 8 && d == int8(8-c) && t.Size() == 1
+ => (ROLBconst x [int8(c)])
+(XORL <t> (SHLLconst x [c]) (SHRBconst x [d])) && c < 8 && d == int8(8-c) && t.Size() == 1
+ => (ROLBconst x [int8(c)])
+
+(ROLLconst [c] (ROLLconst [d] x)) => (ROLLconst [(c+d)&31] x)
+(ROLWconst [c] (ROLWconst [d] x)) => (ROLWconst [(c+d)&15] x)
+(ROLBconst [c] (ROLBconst [d] x)) => (ROLBconst [(c+d)& 7] x)
+
+
+// Constant shift simplifications
+
+(SHLLconst x [0]) => x
+(SHRLconst x [0]) => x
+(SARLconst x [0]) => x
+
+(SHRWconst x [0]) => x
+(SARWconst x [0]) => x
+
+(SHRBconst x [0]) => x
+(SARBconst x [0]) => x
+
+(ROLLconst [0] x) => x
+(ROLWconst [0] x) => x
+(ROLBconst [0] x) => 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.
+// (SHRW x (MOVLconst [24])), but just in case.
+
+(CMPL x (MOVLconst [c])) => (CMPLconst x [c])
+(CMPL (MOVLconst [c]) x) => (InvertFlags (CMPLconst x [c]))
+(CMPW x (MOVLconst [c])) => (CMPWconst x [int16(c)])
+(CMPW (MOVLconst [c]) x) => (InvertFlags (CMPWconst x [int16(c)]))
+(CMPB x (MOVLconst [c])) => (CMPBconst x [int8(c)])
+(CMPB (MOVLconst [c]) x) => (InvertFlags (CMPBconst x [int8(c)]))
+
+// Canonicalize the order of arguments to comparisons - helps with CSE.
+(CMP(L|W|B) x y) && x.ID > y.ID => (InvertFlags (CMP(L|W|B) y x))
+
+// strength reduction
+// Assumes that the following costs from https://gmplib.org/~tege/x86-timing.pdf:
+// 1 - addl, shll, leal, negl, subl
+// 3 - imull
+// This limits the rewrites to two instructions.
+// Note that negl always operates in-place,
+// which can require a register-register move
+// to preserve the original value,
+// so it must be used with care.
+(MULLconst [-9] x) => (NEGL (LEAL8 <v.Type> x x))
+(MULLconst [-5] x) => (NEGL (LEAL4 <v.Type> x x))
+(MULLconst [-3] x) => (NEGL (LEAL2 <v.Type> x x))
+(MULLconst [-1] x) => (NEGL x)
+(MULLconst [0] _) => (MOVLconst [0])
+(MULLconst [1] x) => x
+(MULLconst [3] x) => (LEAL2 x x)
+(MULLconst [5] x) => (LEAL4 x x)
+(MULLconst [7] x) => (LEAL2 x (LEAL2 <v.Type> x x))
+(MULLconst [9] x) => (LEAL8 x x)
+(MULLconst [11] x) => (LEAL2 x (LEAL4 <v.Type> x x))
+(MULLconst [13] x) => (LEAL4 x (LEAL2 <v.Type> x x))
+(MULLconst [19] x) => (LEAL2 x (LEAL8 <v.Type> x x))
+(MULLconst [21] x) => (LEAL4 x (LEAL4 <v.Type> x x))
+(MULLconst [25] x) => (LEAL8 x (LEAL2 <v.Type> x x))
+(MULLconst [27] x) => (LEAL8 (LEAL2 <v.Type> x x) (LEAL2 <v.Type> x x))
+(MULLconst [37] x) => (LEAL4 x (LEAL8 <v.Type> x x))
+(MULLconst [41] x) => (LEAL8 x (LEAL4 <v.Type> x x))
+(MULLconst [45] x) => (LEAL8 (LEAL4 <v.Type> x x) (LEAL4 <v.Type> x x))
+(MULLconst [73] x) => (LEAL8 x (LEAL8 <v.Type> x x))
+(MULLconst [81] x) => (LEAL8 (LEAL8 <v.Type> x x) (LEAL8 <v.Type> x x))
+
+(MULLconst [c] x) && isPowerOfTwo32(c+1) && c >= 15 => (SUBL (SHLLconst <v.Type> [int32(log32(c+1))] x) x)
+(MULLconst [c] x) && isPowerOfTwo32(c-1) && c >= 17 => (LEAL1 (SHLLconst <v.Type> [int32(log32(c-1))] x) x)
+(MULLconst [c] x) && isPowerOfTwo32(c-2) && c >= 34 => (LEAL2 (SHLLconst <v.Type> [int32(log32(c-2))] x) x)
+(MULLconst [c] x) && isPowerOfTwo32(c-4) && c >= 68 => (LEAL4 (SHLLconst <v.Type> [int32(log32(c-4))] x) x)
+(MULLconst [c] x) && isPowerOfTwo32(c-8) && c >= 136 => (LEAL8 (SHLLconst <v.Type> [int32(log32(c-8))] x) x)
+(MULLconst [c] x) && c%3 == 0 && isPowerOfTwo32(c/3) => (SHLLconst [int32(log32(c/3))] (LEAL2 <v.Type> x x))
+(MULLconst [c] x) && c%5 == 0 && isPowerOfTwo32(c/5) => (SHLLconst [int32(log32(c/5))] (LEAL4 <v.Type> x x))
+(MULLconst [c] x) && c%9 == 0 && isPowerOfTwo32(c/9) => (SHLLconst [int32(log32(c/9))] (LEAL8 <v.Type> x x))
+
+// combine add/shift into LEAL
+(ADDL x (SHLLconst [3] y)) => (LEAL8 x y)
+(ADDL x (SHLLconst [2] y)) => (LEAL4 x y)
+(ADDL x (SHLLconst [1] y)) => (LEAL2 x y)
+(ADDL x (ADDL y y)) => (LEAL2 x y)
+(ADDL x (ADDL x y)) => (LEAL2 y x)
+
+// combine ADDL/ADDLconst into LEAL1
+(ADDLconst [c] (ADDL x y)) => (LEAL1 [c] x y)
+(ADDL (ADDLconst [c] x) y) => (LEAL1 [c] x y)
+
+// fold ADDL into LEAL
+(ADDLconst [c] (LEAL [d] {s} x)) && is32Bit(int64(c)+int64(d)) => (LEAL [c+d] {s} x)
+(LEAL [c] {s} (ADDLconst [d] x)) && is32Bit(int64(c)+int64(d)) => (LEAL [c+d] {s} x)
+(ADDLconst [c] x:(SP)) => (LEAL [c] x) // so it is rematerializeable
+(LEAL [c] {s} (ADDL x y)) && x.Op != OpSB && y.Op != OpSB => (LEAL1 [c] {s} x y)
+(ADDL x (LEAL [c] {s} y)) && x.Op != OpSB && y.Op != OpSB => (LEAL1 [c] {s} x y)
+
+// fold ADDLconst into LEALx
+(ADDLconst [c] (LEAL1 [d] {s} x y)) && is32Bit(int64(c)+int64(d)) => (LEAL1 [c+d] {s} x y)
+(ADDLconst [c] (LEAL2 [d] {s} x y)) && is32Bit(int64(c)+int64(d)) => (LEAL2 [c+d] {s} x y)
+(ADDLconst [c] (LEAL4 [d] {s} x y)) && is32Bit(int64(c)+int64(d)) => (LEAL4 [c+d] {s} x y)
+(ADDLconst [c] (LEAL8 [d] {s} x y)) && is32Bit(int64(c)+int64(d)) => (LEAL8 [c+d] {s} x y)
+(LEAL1 [c] {s} (ADDLconst [d] x) y) && is32Bit(int64(c)+int64(d)) && x.Op != OpSB => (LEAL1 [c+d] {s} x y)
+(LEAL2 [c] {s} (ADDLconst [d] x) y) && is32Bit(int64(c)+int64(d)) && x.Op != OpSB => (LEAL2 [c+d] {s} x y)
+(LEAL2 [c] {s} x (ADDLconst [d] y)) && is32Bit(int64(c)+2*int64(d)) && y.Op != OpSB => (LEAL2 [c+2*d] {s} x y)
+(LEAL4 [c] {s} (ADDLconst [d] x) y) && is32Bit(int64(c)+int64(d)) && x.Op != OpSB => (LEAL4 [c+d] {s} x y)
+(LEAL4 [c] {s} x (ADDLconst [d] y)) && is32Bit(int64(c)+4*int64(d)) && y.Op != OpSB => (LEAL4 [c+4*d] {s} x y)
+(LEAL8 [c] {s} (ADDLconst [d] x) y) && is32Bit(int64(c)+int64(d)) && x.Op != OpSB => (LEAL8 [c+d] {s} x y)
+(LEAL8 [c] {s} x (ADDLconst [d] y)) && is32Bit(int64(c)+8*int64(d)) && y.Op != OpSB => (LEAL8 [c+8*d] {s} x y)
+
+// fold shifts into LEALx
+(LEAL1 [c] {s} x (SHLLconst [1] y)) => (LEAL2 [c] {s} x y)
+(LEAL1 [c] {s} x (SHLLconst [2] y)) => (LEAL4 [c] {s} x y)
+(LEAL1 [c] {s} x (SHLLconst [3] y)) => (LEAL8 [c] {s} x y)
+(LEAL2 [c] {s} x (SHLLconst [1] y)) => (LEAL4 [c] {s} x y)
+(LEAL2 [c] {s} x (SHLLconst [2] y)) => (LEAL8 [c] {s} x y)
+(LEAL4 [c] {s} x (SHLLconst [1] y)) => (LEAL8 [c] {s} 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.
+// Make sure we don't combine these ops if the load has another use.
+// This prevents a single load from being split into multiple loads
+// which then might return different values. See test/atomicload.go.
+(MOVBLSX x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBLSXload <v.Type> [off] {sym} ptr mem)
+(MOVBLZX x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+(MOVWLSX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWLSXload <v.Type> [off] {sym} ptr mem)
+(MOVWLZX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWload <v.Type> [off] {sym} ptr mem)
+
+// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
+(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVBLZX x)
+(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVWLZX x)
+(MOVLload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => x
+(MOVBLSXload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVBLSX x)
+(MOVWLSXload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVWLSX x)
+
+// Fold extensions and ANDs together.
+(MOVBLZX (ANDLconst [c] x)) => (ANDLconst [c & 0xff] x)
+(MOVWLZX (ANDLconst [c] x)) => (ANDLconst [c & 0xffff] x)
+(MOVBLSX (ANDLconst [c] x)) && c & 0x80 == 0 => (ANDLconst [c & 0x7f] x)
+(MOVWLSX (ANDLconst [c] x)) && c & 0x8000 == 0 => (ANDLconst [c & 0x7fff] x)
+
+// Don't extend before storing
+(MOVWstore [off] {sym} ptr (MOVWL(S|Z)X x) mem) => (MOVWstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVBL(S|Z)X 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 ADDLconst get eliminated, we still have to compute the ADDLconst and we now
+// have potentially two live values (ptr and (ADDLconst [off] ptr)) instead of one.
+// Nevertheless, let's do it!
+(MOV(L|W|B|SS|SD)load [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOV(L|W|B|SS|SD)load [off1+off2] {sym} ptr mem)
+(MOV(L|W|B|SS|SD)store [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOV(L|W|B|SS|SD)store [off1+off2] {sym} ptr val mem)
+
+((ADD|SUB|MUL|AND|OR|XOR)Lload [off1] {sym} val (ADDLconst [off2] base) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ ((ADD|SUB|MUL|AND|OR|XOR)Lload [off1+off2] {sym} val base mem)
+((ADD|SUB|MUL|DIV)SSload [off1] {sym} val (ADDLconst [off2] base) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ ((ADD|SUB|MUL|DIV)SSload [off1+off2] {sym} val base mem)
+((ADD|SUB|MUL|DIV)SDload [off1] {sym} val (ADDLconst [off2] base) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ ((ADD|SUB|MUL|DIV)SDload [off1+off2] {sym} val base mem)
+((ADD|SUB|AND|OR|XOR)Lmodify [off1] {sym} (ADDLconst [off2] base) val mem) && is32Bit(int64(off1)+int64(off2)) =>
+ ((ADD|SUB|AND|OR|XOR)Lmodify [off1+off2] {sym} base val mem)
+((ADD|AND|OR|XOR)Lconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem) && valoff1.canAdd32(off2) =>
+ ((ADD|AND|OR|XOR)Lconstmodify [valoff1.addOffset32(off2)] {sym} base mem)
+
+// Fold constants into stores.
+(MOVLstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(int64(off)) =>
+ (MOVLstoreconst [makeValAndOff32(c,off)] {sym} ptr mem)
+(MOVWstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(int64(off)) =>
+ (MOVWstoreconst [makeValAndOff32(c,off)] {sym} ptr mem)
+(MOVBstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(int64(off)) =>
+ (MOVBstoreconst [makeValAndOff32(c,off)] {sym} ptr mem)
+
+// Fold address offsets into constant stores.
+(MOV(L|W|B)storeconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) =>
+ (MOV(L|W|B)storeconst [sc.addOffset32(off)] {s} ptr mem)
+
+// We need to fold LEAL into the MOVx ops so that the live variable analysis knows
+// what variables are being read/written by the ops.
+// Note: we turn off this merging for operations on globals when building
+// position-independent code (when Flag_shared is set).
+// PIC needs a spare register to load the PC into. Having the LEAL be
+// a separate instruction gives us that register. Having the LEAL be
+// a separate instruction also allows it to be CSEd (which is good because
+// it compiles to a thunk call).
+(MOV(L|W|B|SS|SD|BLSX|WLSX)load [off1] {sym1} (LEAL [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ && (base.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOV(L|W|B|SS|SD|BLSX|WLSX)load [off1+off2] {mergeSym(sym1,sym2)} base mem)
+
+(MOV(L|W|B|SS|SD)store [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ && (base.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOV(L|W|B|SS|SD)store [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+
+(MOV(L|W|B)storeconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOV(L|W|B)storeconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+
+((ADD|SUB|MUL|AND|OR|XOR)Lload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) =>
+ ((ADD|SUB|MUL|AND|OR|XOR)Lload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+((ADD|SUB|MUL|DIV)SSload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) =>
+ ((ADD|SUB|MUL|DIV)SSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+((ADD|SUB|MUL|DIV)SDload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) =>
+ ((ADD|SUB|MUL|DIV)SDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+((ADD|SUB|AND|OR|XOR)Lmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) =>
+ ((ADD|SUB|AND|OR|XOR)Lmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+((ADD|AND|OR|XOR)Lconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem)
+ && valoff1.canAdd32(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) =>
+ ((ADD|AND|OR|XOR)Lconstmodify [valoff1.addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+
+// Merge load/store to op
+((ADD|AND|OR|XOR|SUB|MUL)L x l:(MOVLload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|AND|OR|XOR|SUB|MUL)Lload x [off] {sym} ptr mem)
+((ADD|SUB|MUL|DIV)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|MUL|DIV)SDload x [off] {sym} ptr mem)
+((ADD|SUB|MUL|DIV)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|MUL|DIV)SSload x [off] {sym} ptr mem)
+(MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) => ((ADD|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
+(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
+ ((ADD|SUB|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
+(MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lconst [c] l:(MOVLload [off] {sym} ptr mem)) mem)
+ && y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(int64(c),int64(off)) =>
+ ((ADD|AND|OR|XOR)Lconstmodify [makeValAndOff32(c,off)] {sym} ptr mem)
+
+// fold LEALs together
+(LEAL [off1] {sym1} (LEAL [off2] {sym2} x)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAL [off1+off2] {mergeSym(sym1,sym2)} x)
+
+// LEAL into LEAL1
+(LEAL1 [off1] {sym1} (LEAL [off2] {sym2} x) y) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB =>
+ (LEAL1 [off1+off2] {mergeSym(sym1,sym2)} x y)
+
+// LEAL1 into LEAL
+(LEAL [off1] {sym1} (LEAL1 [off2] {sym2} x y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAL1 [off1+off2] {mergeSym(sym1,sym2)} x y)
+
+// LEAL into LEAL[248]
+(LEAL2 [off1] {sym1} (LEAL [off2] {sym2} x) y) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB =>
+ (LEAL2 [off1+off2] {mergeSym(sym1,sym2)} x y)
+(LEAL4 [off1] {sym1} (LEAL [off2] {sym2} x) y) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB =>
+ (LEAL4 [off1+off2] {mergeSym(sym1,sym2)} x y)
+(LEAL8 [off1] {sym1} (LEAL [off2] {sym2} x) y) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB =>
+ (LEAL8 [off1+off2] {mergeSym(sym1,sym2)} x y)
+
+// LEAL[248] into LEAL
+(LEAL [off1] {sym1} (LEAL2 [off2] {sym2} x y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAL2 [off1+off2] {mergeSym(sym1,sym2)} x y)
+(LEAL [off1] {sym1} (LEAL4 [off2] {sym2} x y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAL4 [off1+off2] {mergeSym(sym1,sym2)} x y)
+(LEAL [off1] {sym1} (LEAL8 [off2] {sym2} x y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAL8 [off1+off2] {mergeSym(sym1,sym2)} x y)
+
+// LEAL[1248] into LEAL[1248]. Only some such merges are possible.
+(LEAL1 [off1] {sym1} x (LEAL1 [off2] {sym2} y y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAL2 [off1+off2] {mergeSym(sym1, sym2)} x y)
+(LEAL1 [off1] {sym1} x (LEAL1 [off2] {sym2} x y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAL2 [off1+off2] {mergeSym(sym1, sym2)} y x)
+(LEAL2 [off1] {sym} x (LEAL1 [off2] {nil} y y)) && is32Bit(int64(off1)+2*int64(off2)) =>
+ (LEAL4 [off1+2*off2] {sym} x y)
+(LEAL4 [off1] {sym} x (LEAL1 [off2] {nil} y y)) && is32Bit(int64(off1)+4*int64(off2)) =>
+ (LEAL8 [off1+4*off2] {sym} x y)
+
+// 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)
+
+// Constant comparisons.
+(CMPLconst (MOVLconst [x]) [y]) && x==y => (FlagEQ)
+(CMPLconst (MOVLconst [x]) [y]) && x<y && uint32(x)<uint32(y) => (FlagLT_ULT)
+(CMPLconst (MOVLconst [x]) [y]) && x<y && uint32(x)>uint32(y) => (FlagLT_UGT)
+(CMPLconst (MOVLconst [x]) [y]) && x>y && uint32(x)<uint32(y) => (FlagGT_ULT)
+(CMPLconst (MOVLconst [x]) [y]) && x>y && uint32(x)>uint32(y) => (FlagGT_UGT)
+
+(CMPWconst (MOVLconst [x]) [y]) && int16(x)==y => (FlagEQ)
+(CMPWconst (MOVLconst [x]) [y]) && int16(x)<y && uint16(x)<uint16(y) => (FlagLT_ULT)
+(CMPWconst (MOVLconst [x]) [y]) && int16(x)<y && uint16(x)>uint16(y) => (FlagLT_UGT)
+(CMPWconst (MOVLconst [x]) [y]) && int16(x)>y && uint16(x)<uint16(y) => (FlagGT_ULT)
+(CMPWconst (MOVLconst [x]) [y]) && int16(x)>y && uint16(x)>uint16(y) => (FlagGT_UGT)
+
+(CMPBconst (MOVLconst [x]) [y]) && int8(x)==y => (FlagEQ)
+(CMPBconst (MOVLconst [x]) [y]) && int8(x)<y && uint8(x)<uint8(y) => (FlagLT_ULT)
+(CMPBconst (MOVLconst [x]) [y]) && int8(x)<y && uint8(x)>uint8(y) => (FlagLT_UGT)
+(CMPBconst (MOVLconst [x]) [y]) && int8(x)>y && uint8(x)<uint8(y) => (FlagGT_ULT)
+(CMPBconst (MOVLconst [x]) [y]) && int8(x)>y && uint8(x)>uint8(y) => (FlagGT_UGT)
+
+// Other known comparisons.
+(CMPLconst (SHRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 32 && (1<<uint64(32-c)) <= uint64(n) => (FlagLT_ULT)
+(CMPLconst (ANDLconst _ [m]) [n]) && 0 <= m && m < n => (FlagLT_ULT)
+(CMPWconst (ANDLconst _ [m]) [n]) && 0 <= int16(m) && int16(m) < n => (FlagLT_ULT)
+(CMPBconst (ANDLconst _ [m]) [n]) && 0 <= int8(m) && int8(m) < n => (FlagLT_ULT)
+// TODO: DIVxU also.
+
+// Absorb flag constants into SBB ops.
+(SBBLcarrymask (FlagEQ)) => (MOVLconst [0])
+(SBBLcarrymask (FlagLT_ULT)) => (MOVLconst [-1])
+(SBBLcarrymask (FlagLT_UGT)) => (MOVLconst [0])
+(SBBLcarrymask (FlagGT_ULT)) => (MOVLconst [-1])
+(SBBLcarrymask (FlagGT_UGT)) => (MOVLconst [0])
+
+// Absorb flag constants into branches.
+(EQ (FlagEQ) yes no) => (First yes no)
+(EQ (FlagLT_ULT) yes no) => (First no yes)
+(EQ (FlagLT_UGT) yes no) => (First no yes)
+(EQ (FlagGT_ULT) yes no) => (First no yes)
+(EQ (FlagGT_UGT) yes no) => (First no yes)
+
+(NE (FlagEQ) yes no) => (First no yes)
+(NE (FlagLT_ULT) yes no) => (First yes no)
+(NE (FlagLT_UGT) yes no) => (First yes no)
+(NE (FlagGT_ULT) yes no) => (First yes no)
+(NE (FlagGT_UGT) yes no) => (First yes no)
+
+(LT (FlagEQ) yes no) => (First no yes)
+(LT (FlagLT_ULT) yes no) => (First yes no)
+(LT (FlagLT_UGT) yes no) => (First yes no)
+(LT (FlagGT_ULT) yes no) => (First no yes)
+(LT (FlagGT_UGT) yes no) => (First no yes)
+
+(LE (FlagEQ) yes no) => (First yes no)
+(LE (FlagLT_ULT) yes no) => (First yes no)
+(LE (FlagLT_UGT) yes no) => (First yes no)
+(LE (FlagGT_ULT) yes no) => (First no yes)
+(LE (FlagGT_UGT) yes no) => (First no yes)
+
+(GT (FlagEQ) yes no) => (First no yes)
+(GT (FlagLT_ULT) yes no) => (First no yes)
+(GT (FlagLT_UGT) yes no) => (First no yes)
+(GT (FlagGT_ULT) yes no) => (First yes no)
+(GT (FlagGT_UGT) yes no) => (First yes no)
+
+(GE (FlagEQ) yes no) => (First yes no)
+(GE (FlagLT_ULT) yes no) => (First no yes)
+(GE (FlagLT_UGT) yes no) => (First no yes)
+(GE (FlagGT_ULT) yes no) => (First yes no)
+(GE (FlagGT_UGT) yes no) => (First yes no)
+
+(ULT (FlagEQ) yes no) => (First no yes)
+(ULT (FlagLT_ULT) yes no) => (First yes no)
+(ULT (FlagLT_UGT) yes no) => (First no yes)
+(ULT (FlagGT_ULT) yes no) => (First yes no)
+(ULT (FlagGT_UGT) yes no) => (First no yes)
+
+(ULE (FlagEQ) yes no) => (First yes no)
+(ULE (FlagLT_ULT) yes no) => (First yes no)
+(ULE (FlagLT_UGT) yes no) => (First no yes)
+(ULE (FlagGT_ULT) yes no) => (First yes no)
+(ULE (FlagGT_UGT) yes no) => (First no yes)
+
+(UGT (FlagEQ) yes no) => (First no yes)
+(UGT (FlagLT_ULT) yes no) => (First no yes)
+(UGT (FlagLT_UGT) yes no) => (First yes no)
+(UGT (FlagGT_ULT) yes no) => (First no yes)
+(UGT (FlagGT_UGT) yes no) => (First yes no)
+
+(UGE (FlagEQ) yes no) => (First yes no)
+(UGE (FlagLT_ULT) yes no) => (First no yes)
+(UGE (FlagLT_UGT) yes no) => (First yes no)
+(UGE (FlagGT_ULT) yes no) => (First no yes)
+(UGE (FlagGT_UGT) yes no) => (First yes no)
+
+// Absorb flag constants into SETxx ops.
+(SETEQ (FlagEQ)) => (MOVLconst [1])
+(SETEQ (FlagLT_ULT)) => (MOVLconst [0])
+(SETEQ (FlagLT_UGT)) => (MOVLconst [0])
+(SETEQ (FlagGT_ULT)) => (MOVLconst [0])
+(SETEQ (FlagGT_UGT)) => (MOVLconst [0])
+
+(SETNE (FlagEQ)) => (MOVLconst [0])
+(SETNE (FlagLT_ULT)) => (MOVLconst [1])
+(SETNE (FlagLT_UGT)) => (MOVLconst [1])
+(SETNE (FlagGT_ULT)) => (MOVLconst [1])
+(SETNE (FlagGT_UGT)) => (MOVLconst [1])
+
+(SETL (FlagEQ)) => (MOVLconst [0])
+(SETL (FlagLT_ULT)) => (MOVLconst [1])
+(SETL (FlagLT_UGT)) => (MOVLconst [1])
+(SETL (FlagGT_ULT)) => (MOVLconst [0])
+(SETL (FlagGT_UGT)) => (MOVLconst [0])
+
+(SETLE (FlagEQ)) => (MOVLconst [1])
+(SETLE (FlagLT_ULT)) => (MOVLconst [1])
+(SETLE (FlagLT_UGT)) => (MOVLconst [1])
+(SETLE (FlagGT_ULT)) => (MOVLconst [0])
+(SETLE (FlagGT_UGT)) => (MOVLconst [0])
+
+(SETG (FlagEQ)) => (MOVLconst [0])
+(SETG (FlagLT_ULT)) => (MOVLconst [0])
+(SETG (FlagLT_UGT)) => (MOVLconst [0])
+(SETG (FlagGT_ULT)) => (MOVLconst [1])
+(SETG (FlagGT_UGT)) => (MOVLconst [1])
+
+(SETGE (FlagEQ)) => (MOVLconst [1])
+(SETGE (FlagLT_ULT)) => (MOVLconst [0])
+(SETGE (FlagLT_UGT)) => (MOVLconst [0])
+(SETGE (FlagGT_ULT)) => (MOVLconst [1])
+(SETGE (FlagGT_UGT)) => (MOVLconst [1])
+
+(SETB (FlagEQ)) => (MOVLconst [0])
+(SETB (FlagLT_ULT)) => (MOVLconst [1])
+(SETB (FlagLT_UGT)) => (MOVLconst [0])
+(SETB (FlagGT_ULT)) => (MOVLconst [1])
+(SETB (FlagGT_UGT)) => (MOVLconst [0])
+
+(SETBE (FlagEQ)) => (MOVLconst [1])
+(SETBE (FlagLT_ULT)) => (MOVLconst [1])
+(SETBE (FlagLT_UGT)) => (MOVLconst [0])
+(SETBE (FlagGT_ULT)) => (MOVLconst [1])
+(SETBE (FlagGT_UGT)) => (MOVLconst [0])
+
+(SETA (FlagEQ)) => (MOVLconst [0])
+(SETA (FlagLT_ULT)) => (MOVLconst [0])
+(SETA (FlagLT_UGT)) => (MOVLconst [1])
+(SETA (FlagGT_ULT)) => (MOVLconst [0])
+(SETA (FlagGT_UGT)) => (MOVLconst [1])
+
+(SETAE (FlagEQ)) => (MOVLconst [1])
+(SETAE (FlagLT_ULT)) => (MOVLconst [0])
+(SETAE (FlagLT_UGT)) => (MOVLconst [1])
+(SETAE (FlagGT_ULT)) => (MOVLconst [0])
+(SETAE (FlagGT_UGT)) => (MOVLconst [1])
+
+// Remove redundant *const ops
+(ADDLconst [c] x) && c==0 => x
+(SUBLconst [c] x) && c==0 => x
+(ANDLconst [c] _) && c==0 => (MOVLconst [0])
+(ANDLconst [c] x) && c==-1 => x
+(ORLconst [c] x) && c==0 => x
+(ORLconst [c] _) && c==-1 => (MOVLconst [-1])
+(XORLconst [c] x) && c==0 => x
+// TODO: since we got rid of the W/B versions, we might miss
+// things like (ANDLconst [0x100] x) which were formerly
+// (ANDBconst [0] x). Probably doesn't happen very often.
+// If we cared, we might do:
+// (ANDLconst <t> [c] x) && t.Size()==1 && int8(x)==0 => (MOVLconst [0])
+
+// Convert constant subtracts to constant adds
+(SUBLconst [c] x) => (ADDLconst [-c] x)
+
+// generic constant folding
+// TODO: more of this
+(ADDLconst [c] (MOVLconst [d])) => (MOVLconst [c+d])
+(ADDLconst [c] (ADDLconst [d] x)) => (ADDLconst [c+d] x)
+(SARLconst [c] (MOVLconst [d])) => (MOVLconst [d>>uint64(c)])
+(SARWconst [c] (MOVLconst [d])) => (MOVLconst [d>>uint64(c)])
+(SARBconst [c] (MOVLconst [d])) => (MOVLconst [d>>uint64(c)])
+(NEGL (MOVLconst [c])) => (MOVLconst [-c])
+(MULLconst [c] (MOVLconst [d])) => (MOVLconst [c*d])
+(ANDLconst [c] (MOVLconst [d])) => (MOVLconst [c&d])
+(ORLconst [c] (MOVLconst [d])) => (MOVLconst [c|d])
+(XORLconst [c] (MOVLconst [d])) => (MOVLconst [c^d])
+(NOTL (MOVLconst [c])) => (MOVLconst [^c])
+
+// generic simplifications
+// TODO: more of this
+(ADDL x (NEGL y)) => (SUBL x y)
+(SUBL x x) => (MOVLconst [0])
+(ANDL x x) => x
+(ORL x x) => x
+(XORL x x) => (MOVLconst [0])
+
+// checking AND against 0.
+(CMP(L|W|B)const l:(ANDL x y) [0]) && l.Uses==1 => (TEST(L|W|B) x y)
+(CMPLconst l:(ANDLconst [c] x) [0]) && l.Uses==1 => (TESTLconst [c] x)
+(CMPWconst l:(ANDLconst [c] x) [0]) && l.Uses==1 => (TESTWconst [int16(c)] x)
+(CMPBconst l:(ANDLconst [c] x) [0]) && l.Uses==1 => (TESTBconst [int8(c)] x)
+
+// TEST %reg,%reg is shorter than CMP
+(CMP(L|W|B)const x [0]) => (TEST(L|W|B) x x)
+
+// Convert LEAL1 back to ADDL if we can
+(LEAL1 [0] {nil} x y) => (ADDL x y)
+
+// Combining byte loads into larger (unaligned) loads.
+// There are many ways these combinations could occur. This is
+// designed to match the way encoding/binary.LittleEndian does it.
+(ORL x0:(MOVBload [i0] {s} p mem)
+ s0:(SHLLconst [8] x1:(MOVBload [i1] {s} p mem)))
+ && i1 == i0+1
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, s0)
+ => @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem)
+
+(ORL x0:(MOVBload [i] {s} p0 mem)
+ s0:(SHLLconst [8] x1:(MOVBload [i] {s} p1 mem)))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, s0)
+ => @mergePoint(b,x0,x1) (MOVWload [i] {s} p0 mem)
+
+(ORL o0:(ORL
+ x0:(MOVWload [i0] {s} p mem)
+ s0:(SHLLconst [16] x1:(MOVBload [i2] {s} p mem)))
+ s1:(SHLLconst [24] x2:(MOVBload [i3] {s} p mem)))
+ && i2 == i0+2
+ && i3 == i0+3
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && o0.Uses == 1
+ && mergePoint(b,x0,x1,x2) != nil
+ && clobber(x0, x1, x2, s0, s1, o0)
+ => @mergePoint(b,x0,x1,x2) (MOVLload [i0] {s} p mem)
+
+(ORL o0:(ORL
+ x0:(MOVWload [i] {s} p0 mem)
+ s0:(SHLLconst [16] x1:(MOVBload [i] {s} p1 mem)))
+ s1:(SHLLconst [24] x2:(MOVBload [i] {s} p2 mem)))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && o0.Uses == 1
+ && sequentialAddresses(p0, p1, 2)
+ && sequentialAddresses(p1, p2, 1)
+ && mergePoint(b,x0,x1,x2) != nil
+ && clobber(x0, x1, x2, s0, s1, o0)
+ => @mergePoint(b,x0,x1,x2) (MOVLload [i] {s} p0 mem)
+
+// Combine constant stores into larger (unaligned) stores.
+(MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem))
+ && x.Uses == 1
+ && a.Off() + 1 == c.Off()
+ && clobber(x)
+ => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p mem)
+(MOVBstoreconst [a] {s} p x:(MOVBstoreconst [c] {s} p mem))
+ && x.Uses == 1
+ && a.Off() + 1 == c.Off()
+ && clobber(x)
+ => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p mem)
+
+(MOVBstoreconst [c] {s} p1 x:(MOVBstoreconst [a] {s} p0 mem))
+ && x.Uses == 1
+ && a.Off() == c.Off()
+ && sequentialAddresses(p0, p1, 1)
+ && clobber(x)
+ => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p0 mem)
+(MOVBstoreconst [a] {s} p0 x:(MOVBstoreconst [c] {s} p1 mem))
+ && x.Uses == 1
+ && a.Off() == c.Off()
+ && sequentialAddresses(p0, p1, 1)
+ && clobber(x)
+ => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p0 mem)
+
+(MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem))
+ && x.Uses == 1
+ && a.Off() + 2 == c.Off()
+ && clobber(x)
+ => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p mem)
+(MOVWstoreconst [a] {s} p x:(MOVWstoreconst [c] {s} p mem))
+ && x.Uses == 1
+ && ValAndOff(a).Off() + 2 == ValAndOff(c).Off()
+ && clobber(x)
+ => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p mem)
+
+(MOVWstoreconst [c] {s} p1 x:(MOVWstoreconst [a] {s} p0 mem))
+ && x.Uses == 1
+ && a.Off() == c.Off()
+ && sequentialAddresses(p0, p1, 2)
+ && clobber(x)
+ => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p0 mem)
+(MOVWstoreconst [a] {s} p0 x:(MOVWstoreconst [c] {s} p1 mem))
+ && x.Uses == 1
+ && a.Off() == c.Off()
+ && sequentialAddresses(p0, p1, 2)
+ && clobber(x)
+ => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p0 mem)
+
+// Combine stores into larger (unaligned) stores.
+(MOVBstore [i] {s} p (SHR(W|L)const [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstore [i-1] {s} p w mem)
+(MOVBstore [i] {s} p w x:(MOVBstore {s} [i+1] p (SHR(W|L)const [8] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstore [i] {s} p w mem)
+(MOVBstore [i] {s} p (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SHRLconst [j-8] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstore [i-1] {s} p w0 mem)
+
+(MOVBstore [i] {s} p1 (SHR(W|L)const [8] w) x:(MOVBstore [i] {s} p0 w mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && clobber(x)
+ => (MOVWstore [i] {s} p0 w mem)
+(MOVBstore [i] {s} p0 w x:(MOVBstore {s} [i] p1 (SHR(W|L)const [8] w) mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && clobber(x)
+ => (MOVWstore [i] {s} p0 w mem)
+(MOVBstore [i] {s} p1 (SHRLconst [j] w) x:(MOVBstore [i] {s} p0 w0:(SHRLconst [j-8] w) mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && clobber(x)
+ => (MOVWstore [i] {s} p0 w0 mem)
+
+(MOVWstore [i] {s} p (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVLstore [i-2] {s} p w mem)
+(MOVWstore [i] {s} p (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p w0:(SHRLconst [j-16] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVLstore [i-2] {s} p w0 mem)
+
+(MOVWstore [i] {s} p1 (SHRLconst [16] w) x:(MOVWstore [i] {s} p0 w mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 2)
+ && clobber(x)
+ => (MOVLstore [i] {s} p0 w mem)
+(MOVWstore [i] {s} p1 (SHRLconst [j] w) x:(MOVWstore [i] {s} p0 w0:(SHRLconst [j-16] w) mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 2)
+ && clobber(x)
+ => (MOVLstore [i] {s} p0 w0 mem)
+
+// For PIC, break floating-point constant loading into two instructions so we have
+// a register to use for holding the address of the constant pool entry.
+(MOVSSconst [c]) && config.ctxt.Flag_shared => (MOVSSconst2 (MOVSSconst1 [c]))
+(MOVSDconst [c]) && config.ctxt.Flag_shared => (MOVSDconst2 (MOVSDconst1 [c]))
+
+(CMP(L|W|B) l:(MOV(L|W|B)load {sym} [off] ptr mem) x) && canMergeLoad(v, l) && clobber(l) => (CMP(L|W|B)load {sym} [off] ptr x mem)
+(CMP(L|W|B) x l:(MOV(L|W|B)load {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (InvertFlags (CMP(L|W|B)load {sym} [off] ptr x mem))
+
+(CMP(L|W|B)const l:(MOV(L|W|B)load {sym} [off] ptr mem) [c])
+ && l.Uses == 1
+ && validValAndOff(int64(c), int64(off))
+ && clobber(l) =>
+ @l.Block (CMP(L|W|B)constload {sym} [makeValAndOff32(int32(c),int32(off))] ptr mem)
+
+(CMPLload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(c),int64(off)) => (CMPLconstload {sym} [makeValAndOff32(c,off)] ptr mem)
+(CMPWload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(int16(c)),int64(off)) => (CMPWconstload {sym} [makeValAndOff32(int32(int16(c)),off)] ptr mem)
+(CMPBload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(int8(c)),int64(off)) => (CMPBconstload {sym} [makeValAndOff32(int32(int8(c)),off)] ptr mem)
+
+(MOVBload [off] {sym} (SB) _) && symIsRO(sym) => (MOVLconst [int32(read8(sym, int64(off)))])
+(MOVWload [off] {sym} (SB) _) && symIsRO(sym) => (MOVLconst [int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+(MOVLload [off] {sym} (SB) _) && symIsRO(sym) => (MOVLconst [int32(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
diff --git a/src/cmd/compile/internal/ssa/gen/386Ops.go b/src/cmd/compile/internal/ssa/gen/386Ops.go
new file mode 100644
index 0000000..737b99c
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/386Ops.go
@@ -0,0 +1,585 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import "strings"
+
+// Notes:
+// - Integer types live in the low portion of registers. Upper portions are junk.
+// - Boolean types use the low-order byte of a register. 0=false, 1=true.
+// Upper bytes are junk.
+// - Floating-point types live in the low natural slot of an sse2 register.
+// Unused portions are junk.
+// - We do not use AH,BH,CH,DH registers.
+// - When doing sub-register operations, we try to write the whole
+// destination register to avoid a partial-register write.
+// - Unused portions of AuxInt (or the Val portion of ValAndOff) are
+// filled by sign-extending the used portion. Users of AuxInt which interpret
+// AuxInt as unsigned (e.g. shifts) must be careful.
+
+// Suffixes encode the bit width of various instructions.
+// L (long word) = 32 bit
+// W (word) = 16 bit
+// B (byte) = 8 bit
+
+// copied from ../../x86/reg.go
+var regNames386 = []string{
+ "AX",
+ "CX",
+ "DX",
+ "BX",
+ "SP",
+ "BP",
+ "SI",
+ "DI",
+ "X0",
+ "X1",
+ "X2",
+ "X3",
+ "X4",
+ "X5",
+ "X6",
+ "X7",
+
+ // If you add registers, update asyncPreempt in runtime
+
+ // pseudo-registers
+ "SB",
+}
+
+func init() {
+ // Make map from reg names to reg integers.
+ if len(regNames386) > 64 {
+ panic("too many registers")
+ }
+ num := map[string]int{}
+ for i, name := range regNames386 {
+ num[name] = 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")
+ bx = buildReg("BX")
+ si = buildReg("SI")
+ gp = buildReg("AX CX DX BX BP SI DI")
+ fp = buildReg("X0 X1 X2 X3 X4 X5 X6 X7")
+ gpsp = gp | buildReg("SP")
+ gpspsb = gpsp | buildReg("SB")
+ callerSave = gp | fp
+ )
+ // Common slices of register masks
+ var (
+ gponly = []regMask{gp}
+ fponly = []regMask{fp}
+ )
+
+ // Common regInfo
+ var (
+ gp01 = regInfo{inputs: nil, outputs: gponly}
+ gp11 = regInfo{inputs: []regMask{gp}, outputs: gponly}
+ gp11sp = regInfo{inputs: []regMask{gpsp}, outputs: gponly}
+ gp11sb = regInfo{inputs: []regMask{gpspsb}, outputs: gponly}
+ gp21 = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
+ gp11carry = regInfo{inputs: []regMask{gp}, outputs: []regMask{gp, 0}}
+ gp21carry = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp, 0}}
+ gp1carry1 = regInfo{inputs: []regMask{gp}, outputs: gponly}
+ gp2carry1 = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
+ gp21sp = regInfo{inputs: []regMask{gpsp, gp}, outputs: gponly}
+ gp21sb = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly}
+ gp21shift = regInfo{inputs: []regMask{gp, cx}, outputs: []regMask{gp}}
+ gp11div = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{ax}, clobbers: dx}
+ gp21hmul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx}, clobbers: ax}
+ gp11mod = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{dx}, clobbers: ax}
+ gp21mul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx, ax}}
+
+ gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}}
+ gp1flags = regInfo{inputs: []regMask{gpsp}}
+ gp0flagsLoad = regInfo{inputs: []regMask{gpspsb, 0}}
+ gp1flagsLoad = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
+ flagsgp = regInfo{inputs: nil, outputs: gponly}
+
+ readflags = regInfo{inputs: nil, outputs: gponly}
+ flagsgpax = regInfo{inputs: nil, clobbers: ax, outputs: []regMask{gp &^ ax}}
+
+ gpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: gponly}
+ gp21load = regInfo{inputs: []regMask{gp, gpspsb, 0}, outputs: gponly}
+ gploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: gponly}
+ gp21loadidx = regInfo{inputs: []regMask{gp, gpspsb, gpsp, 0}, outputs: gponly}
+
+ gpstore = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
+ gpstoreconst = regInfo{inputs: []regMask{gpspsb, 0}}
+ gpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, gpsp, 0}}
+ gpstoreconstidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
+
+ fp01 = regInfo{inputs: nil, outputs: fponly}
+ fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly}
+ fp21load = regInfo{inputs: []regMask{fp, gpspsb, 0}, outputs: fponly}
+ fpgp = regInfo{inputs: fponly, outputs: gponly}
+ gpfp = regInfo{inputs: gponly, outputs: fponly}
+ fp11 = regInfo{inputs: fponly, outputs: fponly}
+ fp2flags = regInfo{inputs: []regMask{fp, fp}}
+
+ 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}}
+ )
+
+ var _386ops = []opData{
+ // fp ops
+ {name: "ADDSS", argLength: 2, reg: fp21, asm: "ADDSS", commutative: true, resultInArg0: true, usesScratch: true}, // fp32 add
+ {name: "ADDSD", argLength: 2, reg: fp21, asm: "ADDSD", commutative: true, resultInArg0: true}, // fp64 add
+ {name: "SUBSS", argLength: 2, reg: fp21, asm: "SUBSS", resultInArg0: true, usesScratch: true}, // fp32 sub
+ {name: "SUBSD", argLength: 2, reg: fp21, asm: "SUBSD", resultInArg0: true}, // fp64 sub
+ {name: "MULSS", argLength: 2, reg: fp21, asm: "MULSS", commutative: true, resultInArg0: true, usesScratch: true}, // fp32 mul
+ {name: "MULSD", argLength: 2, reg: fp21, asm: "MULSD", commutative: true, resultInArg0: true}, // fp64 mul
+ {name: "DIVSS", argLength: 2, reg: fp21, asm: "DIVSS", resultInArg0: true, usesScratch: true}, // fp32 div
+ {name: "DIVSD", argLength: 2, reg: fp21, asm: "DIVSD", resultInArg0: true}, // fp64 div
+
+ {name: "MOVSSload", argLength: 2, reg: fpload, asm: "MOVSS", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // fp32 load
+ {name: "MOVSDload", argLength: 2, reg: fpload, asm: "MOVSD", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // fp64 load
+ {name: "MOVSSconst", reg: fp01, asm: "MOVSS", aux: "Float32", rematerializeable: true}, // fp32 constant
+ {name: "MOVSDconst", reg: fp01, asm: "MOVSD", aux: "Float64", rematerializeable: true}, // fp64 constant
+ {name: "MOVSSloadidx1", argLength: 3, reg: fploadidx, asm: "MOVSS", aux: "SymOff", symEffect: "Read"}, // fp32 load indexed by i
+ {name: "MOVSSloadidx4", argLength: 3, reg: fploadidx, asm: "MOVSS", aux: "SymOff", symEffect: "Read"}, // fp32 load indexed by 4*i
+ {name: "MOVSDloadidx1", argLength: 3, reg: fploadidx, asm: "MOVSD", aux: "SymOff", symEffect: "Read"}, // fp64 load indexed by i
+ {name: "MOVSDloadidx8", argLength: 3, reg: fploadidx, asm: "MOVSD", aux: "SymOff", symEffect: "Read"}, // fp64 load indexed by 8*i
+
+ {name: "MOVSSstore", argLength: 3, reg: fpstore, asm: "MOVSS", aux: "SymOff", faultOnNilArg0: true, symEffect: "Write"}, // fp32 store
+ {name: "MOVSDstore", argLength: 3, reg: fpstore, asm: "MOVSD", aux: "SymOff", faultOnNilArg0: true, symEffect: "Write"}, // fp64 store
+ {name: "MOVSSstoreidx1", argLength: 4, reg: fpstoreidx, asm: "MOVSS", aux: "SymOff", symEffect: "Write"}, // fp32 indexed by i store
+ {name: "MOVSSstoreidx4", argLength: 4, reg: fpstoreidx, asm: "MOVSS", aux: "SymOff", symEffect: "Write"}, // fp32 indexed by 4i store
+ {name: "MOVSDstoreidx1", argLength: 4, reg: fpstoreidx, asm: "MOVSD", aux: "SymOff", symEffect: "Write"}, // fp64 indexed by i store
+ {name: "MOVSDstoreidx8", argLength: 4, reg: fpstoreidx, asm: "MOVSD", aux: "SymOff", symEffect: "Write"}, // fp64 indexed by 8i store
+
+ {name: "ADDSSload", argLength: 3, reg: fp21load, asm: "ADDSS", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp32 arg0 + tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "ADDSDload", argLength: 3, reg: fp21load, asm: "ADDSD", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp64 arg0 + tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "SUBSSload", argLength: 3, reg: fp21load, asm: "SUBSS", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp32 arg0 - tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "SUBSDload", argLength: 3, reg: fp21load, asm: "SUBSD", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp64 arg0 - tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "MULSSload", argLength: 3, reg: fp21load, asm: "MULSS", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp32 arg0 * tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "MULSDload", argLength: 3, reg: fp21load, asm: "MULSD", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp64 arg0 * tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "DIVSSload", argLength: 3, reg: fp21load, asm: "DIVSS", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp32 arg0 / tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "DIVSDload", argLength: 3, reg: fp21load, asm: "DIVSD", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp64 arg0 / tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+
+ // binary ops
+ {name: "ADDL", argLength: 2, reg: gp21sp, asm: "ADDL", commutative: true, clobberFlags: true}, // arg0 + arg1
+ {name: "ADDLconst", argLength: 1, reg: gp11sp, asm: "ADDL", aux: "Int32", typ: "UInt32", clobberFlags: true}, // arg0 + auxint
+
+ {name: "ADDLcarry", argLength: 2, reg: gp21carry, asm: "ADDL", commutative: true, resultInArg0: true}, // arg0 + arg1, generates <carry,result> pair
+ {name: "ADDLconstcarry", argLength: 1, reg: gp11carry, asm: "ADDL", aux: "Int32", resultInArg0: true}, // arg0 + auxint, generates <carry,result> pair
+ {name: "ADCL", argLength: 3, reg: gp2carry1, asm: "ADCL", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0+arg1+carry(arg2), where arg2 is flags
+ {name: "ADCLconst", argLength: 2, reg: gp1carry1, asm: "ADCL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0+auxint+carry(arg1), where arg1 is flags
+
+ {name: "SUBL", argLength: 2, reg: gp21, asm: "SUBL", resultInArg0: true, clobberFlags: true}, // arg0 - arg1
+ {name: "SUBLconst", argLength: 1, reg: gp11, asm: "SUBL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 - auxint
+
+ {name: "SUBLcarry", argLength: 2, reg: gp21carry, asm: "SUBL", resultInArg0: true}, // arg0-arg1, generates <borrow,result> pair
+ {name: "SUBLconstcarry", argLength: 1, reg: gp11carry, asm: "SUBL", aux: "Int32", resultInArg0: true}, // arg0-auxint, generates <borrow,result> pair
+ {name: "SBBL", argLength: 3, reg: gp2carry1, asm: "SBBL", resultInArg0: true, clobberFlags: true}, // arg0-arg1-borrow(arg2), where arg2 is flags
+ {name: "SBBLconst", argLength: 2, reg: gp1carry1, asm: "SBBL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0-auxint-borrow(arg1), where arg1 is flags
+
+ {name: "MULL", argLength: 2, reg: gp21, asm: "IMULL", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 * arg1
+ {name: "MULLconst", argLength: 1, reg: gp11, asm: "IMUL3L", aux: "Int32", clobberFlags: true}, // arg0 * auxint
+
+ {name: "MULLU", argLength: 2, reg: regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{ax, 0}, clobbers: dx}, typ: "(UInt32,Flags)", asm: "MULL", commutative: true, clobberFlags: true}, // Let x = arg0*arg1 (full 32x32->64 unsigned multiply). Returns uint32(x), and flags set to overflow if uint32(x) != x.
+
+ {name: "HMULL", argLength: 2, reg: gp21hmul, commutative: true, asm: "IMULL", clobberFlags: true}, // (arg0 * arg1) >> width
+ {name: "HMULLU", argLength: 2, reg: gp21hmul, commutative: true, asm: "MULL", clobberFlags: true}, // (arg0 * arg1) >> width
+
+ {name: "MULLQU", argLength: 2, reg: gp21mul, commutative: true, asm: "MULL", clobberFlags: true}, // arg0 * arg1, high 32 in result[0], low 32 in result[1]
+
+ {name: "AVGLU", argLength: 2, reg: gp21, commutative: true, resultInArg0: true, clobberFlags: true}, // (arg0 + arg1) / 2 as unsigned, all 32 result bits
+
+ // For DIVL, DIVW, MODL and MODW, AuxInt non-zero means that the divisor has been proved to be not -1.
+ {name: "DIVL", argLength: 2, reg: gp11div, asm: "IDIVL", aux: "Bool", clobberFlags: true}, // arg0 / arg1
+ {name: "DIVW", argLength: 2, reg: gp11div, asm: "IDIVW", aux: "Bool", clobberFlags: true}, // arg0 / arg1
+ {name: "DIVLU", argLength: 2, reg: gp11div, asm: "DIVL", clobberFlags: true}, // arg0 / arg1
+ {name: "DIVWU", argLength: 2, reg: gp11div, asm: "DIVW", clobberFlags: true}, // arg0 / arg1
+
+ {name: "MODL", argLength: 2, reg: gp11mod, asm: "IDIVL", aux: "Bool", clobberFlags: true}, // arg0 % arg1
+ {name: "MODW", argLength: 2, reg: gp11mod, asm: "IDIVW", aux: "Bool", clobberFlags: true}, // arg0 % arg1
+ {name: "MODLU", argLength: 2, reg: gp11mod, asm: "DIVL", clobberFlags: true}, // arg0 % arg1
+ {name: "MODWU", argLength: 2, reg: gp11mod, asm: "DIVW", clobberFlags: true}, // arg0 % arg1
+
+ {name: "ANDL", argLength: 2, reg: gp21, asm: "ANDL", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 & arg1
+ {name: "ANDLconst", argLength: 1, reg: gp11, asm: "ANDL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 & auxint
+
+ {name: "ORL", argLength: 2, reg: gp21, asm: "ORL", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 | arg1
+ {name: "ORLconst", argLength: 1, reg: gp11, asm: "ORL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 | auxint
+
+ {name: "XORL", argLength: 2, reg: gp21, asm: "XORL", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 ^ arg1
+ {name: "XORLconst", argLength: 1, reg: gp11, asm: "XORL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 ^ auxint
+
+ {name: "CMPL", argLength: 2, reg: gp2flags, asm: "CMPL", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPB", argLength: 2, reg: gp2flags, asm: "CMPB", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPLconst", argLength: 1, reg: gp1flags, asm: "CMPL", typ: "Flags", aux: "Int32"}, // arg0 compare to auxint
+ {name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", typ: "Flags", aux: "Int16"}, // arg0 compare to auxint
+ {name: "CMPBconst", argLength: 1, reg: gp1flags, asm: "CMPB", typ: "Flags", aux: "Int8"}, // arg0 compare to auxint
+
+ // compare *(arg0+auxint+aux) to arg1 (in that order). arg2=mem.
+ {name: "CMPLload", argLength: 3, reg: gp1flagsLoad, asm: "CMPL", aux: "SymOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPWload", argLength: 3, reg: gp1flagsLoad, asm: "CMPW", aux: "SymOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPBload", argLength: 3, reg: gp1flagsLoad, asm: "CMPB", aux: "SymOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+
+ // compare *(arg0+ValAndOff(AuxInt).Off()+aux) to ValAndOff(AuxInt).Val() (in that order). arg1=mem.
+ {name: "CMPLconstload", argLength: 2, reg: gp0flagsLoad, asm: "CMPL", aux: "SymValAndOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPWconstload", argLength: 2, reg: gp0flagsLoad, asm: "CMPW", aux: "SymValAndOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPBconstload", argLength: 2, reg: gp0flagsLoad, asm: "CMPB", aux: "SymValAndOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+
+ {name: "UCOMISS", argLength: 2, reg: fp2flags, asm: "UCOMISS", typ: "Flags", usesScratch: true}, // arg0 compare to arg1, f32
+ {name: "UCOMISD", argLength: 2, reg: fp2flags, asm: "UCOMISD", typ: "Flags", usesScratch: true}, // arg0 compare to arg1, f64
+
+ {name: "TESTL", argLength: 2, reg: gp2flags, commutative: true, asm: "TESTL", typ: "Flags"}, // (arg0 & arg1) compare to 0
+ {name: "TESTW", argLength: 2, reg: gp2flags, commutative: true, asm: "TESTW", typ: "Flags"}, // (arg0 & arg1) compare to 0
+ {name: "TESTB", argLength: 2, reg: gp2flags, commutative: true, asm: "TESTB", typ: "Flags"}, // (arg0 & arg1) compare to 0
+ {name: "TESTLconst", argLength: 1, reg: gp1flags, asm: "TESTL", typ: "Flags", aux: "Int32"}, // (arg0 & auxint) compare to 0
+ {name: "TESTWconst", argLength: 1, reg: gp1flags, asm: "TESTW", typ: "Flags", aux: "Int16"}, // (arg0 & auxint) compare to 0
+ {name: "TESTBconst", argLength: 1, reg: gp1flags, asm: "TESTB", typ: "Flags", aux: "Int8"}, // (arg0 & auxint) compare to 0
+
+ {name: "SHLL", argLength: 2, reg: gp21shift, asm: "SHLL", resultInArg0: true, clobberFlags: true}, // arg0 << arg1, shift amount is mod 32
+ {name: "SHLLconst", argLength: 1, reg: gp11, asm: "SHLL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // 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: "SHRL", argLength: 2, reg: gp21shift, asm: "SHRL", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> arg1, shift amount is mod 32
+ {name: "SHRW", argLength: 2, reg: gp21shift, asm: "SHRW", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> arg1, shift amount is mod 32
+ {name: "SHRB", argLength: 2, reg: gp21shift, asm: "SHRB", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> arg1, shift amount is mod 32
+ {name: "SHRLconst", argLength: 1, reg: gp11, asm: "SHRL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-31
+ {name: "SHRWconst", argLength: 1, reg: gp11, asm: "SHRW", aux: "Int16", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-15
+ {name: "SHRBconst", argLength: 1, reg: gp11, asm: "SHRB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-7
+
+ {name: "SARL", argLength: 2, reg: gp21shift, asm: "SARL", resultInArg0: true, clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 32
+ {name: "SARW", argLength: 2, reg: gp21shift, asm: "SARW", resultInArg0: true, clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 32
+ {name: "SARB", argLength: 2, reg: gp21shift, asm: "SARB", resultInArg0: true, clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 32
+ {name: "SARLconst", argLength: 1, reg: gp11, asm: "SARL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-31
+ {name: "SARWconst", argLength: 1, reg: gp11, asm: "SARW", aux: "Int16", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-15
+ {name: "SARBconst", argLength: 1, reg: gp11, asm: "SARB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-7
+
+ {name: "ROLLconst", argLength: 1, reg: gp11, asm: "ROLL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 rotate left auxint, rotate amount 0-31
+ {name: "ROLWconst", argLength: 1, reg: gp11, asm: "ROLW", aux: "Int16", resultInArg0: true, clobberFlags: true}, // arg0 rotate left auxint, rotate amount 0-15
+ {name: "ROLBconst", argLength: 1, reg: gp11, asm: "ROLB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // arg0 rotate left auxint, rotate amount 0-7
+
+ // binary-op with a memory source operand
+ {name: "ADDLload", argLength: 3, reg: gp21load, asm: "ADDL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 + tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "SUBLload", argLength: 3, reg: gp21load, asm: "SUBL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 - tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "MULLload", argLength: 3, reg: gp21load, asm: "IMULL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 * tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "ANDLload", argLength: 3, reg: gp21load, asm: "ANDL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 & tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "ORLload", argLength: 3, reg: gp21load, asm: "ORL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 | tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "XORLload", argLength: 3, reg: gp21load, asm: "XORL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 ^ tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+
+ // binary-op with an indexed memory source operand
+ {name: "ADDLloadidx4", argLength: 4, reg: gp21loadidx, asm: "ADDL", aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 + tmp, tmp loaded from arg1+arg2*4+auxint+aux, arg3 = mem
+ {name: "SUBLloadidx4", argLength: 4, reg: gp21loadidx, asm: "SUBL", aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 - tmp, tmp loaded from arg1+arg2*4+auxint+aux, arg3 = mem
+ {name: "MULLloadidx4", argLength: 4, reg: gp21loadidx, asm: "IMULL", aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 * tmp, tmp loaded from arg1+arg2*4+auxint+aux, arg3 = mem
+ {name: "ANDLloadidx4", argLength: 4, reg: gp21loadidx, asm: "ANDL", aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 & tmp, tmp loaded from arg1+arg2*4+auxint+aux, arg3 = mem
+ {name: "ORLloadidx4", argLength: 4, reg: gp21loadidx, asm: "ORL", aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 | tmp, tmp loaded from arg1+arg2*4+auxint+aux, arg3 = mem
+ {name: "XORLloadidx4", argLength: 4, reg: gp21loadidx, asm: "XORL", aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 ^ tmp, tmp loaded from arg1+arg2*4+auxint+aux, arg3 = mem
+
+ // unary ops
+ {name: "NEGL", argLength: 1, reg: gp11, asm: "NEGL", resultInArg0: true, clobberFlags: true}, // -arg0
+
+ {name: "NOTL", argLength: 1, reg: gp11, asm: "NOTL", resultInArg0: true, clobberFlags: true}, // ^arg0
+
+ {name: "BSFL", argLength: 1, reg: gp11, asm: "BSFL", clobberFlags: true}, // arg0 # of low-order zeroes ; undef if zero
+ {name: "BSFW", argLength: 1, reg: gp11, asm: "BSFW", clobberFlags: true}, // arg0 # of low-order zeroes ; undef if zero
+
+ {name: "BSRL", argLength: 1, reg: gp11, asm: "BSRL", clobberFlags: true}, // arg0 # of high-order zeroes ; undef if zero
+ {name: "BSRW", argLength: 1, reg: gp11, asm: "BSRW", clobberFlags: true}, // arg0 # of high-order zeroes ; undef if zero
+
+ {name: "BSWAPL", argLength: 1, reg: gp11, asm: "BSWAPL", resultInArg0: true, clobberFlags: true}, // arg0 swap bytes
+
+ {name: "SQRTSD", argLength: 1, reg: fp11, asm: "SQRTSD"}, // sqrt(arg0)
+
+ {name: "SBBLcarrymask", argLength: 1, 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", argLength: 1, reg: readflags, asm: "SETEQ"}, // extract == condition from arg0
+ {name: "SETNE", argLength: 1, reg: readflags, asm: "SETNE"}, // extract != condition from arg0
+ {name: "SETL", argLength: 1, reg: readflags, asm: "SETLT"}, // extract signed < condition from arg0
+ {name: "SETLE", argLength: 1, reg: readflags, asm: "SETLE"}, // extract signed <= condition from arg0
+ {name: "SETG", argLength: 1, reg: readflags, asm: "SETGT"}, // extract signed > condition from arg0
+ {name: "SETGE", argLength: 1, reg: readflags, asm: "SETGE"}, // extract signed >= condition from arg0
+ {name: "SETB", argLength: 1, reg: readflags, asm: "SETCS"}, // extract unsigned < condition from arg0
+ {name: "SETBE", argLength: 1, reg: readflags, asm: "SETLS"}, // extract unsigned <= condition from arg0
+ {name: "SETA", argLength: 1, reg: readflags, asm: "SETHI"}, // extract unsigned > condition from arg0
+ {name: "SETAE", argLength: 1, reg: readflags, asm: "SETCC"}, // extract unsigned >= condition from arg0
+ {name: "SETO", argLength: 1, reg: readflags, asm: "SETOS"}, // extract if overflow flag is set 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", argLength: 1, reg: flagsgpax, asm: "SETEQ", clobberFlags: true}, // extract == condition from arg0
+ {name: "SETNEF", argLength: 1, reg: flagsgpax, asm: "SETNE", clobberFlags: true}, // extract != condition from arg0
+ {name: "SETORD", argLength: 1, reg: flagsgp, asm: "SETPC"}, // extract "ordered" (No Nan present) condition from arg0
+ {name: "SETNAN", argLength: 1, reg: flagsgp, asm: "SETPS"}, // extract "unordered" (Nan present) condition from arg0
+
+ {name: "SETGF", argLength: 1, reg: flagsgp, asm: "SETHI"}, // extract floating > condition from arg0
+ {name: "SETGEF", argLength: 1, reg: flagsgp, asm: "SETCC"}, // extract floating >= condition from arg0
+
+ {name: "MOVBLSX", argLength: 1, reg: gp11, asm: "MOVBLSX"}, // sign extend arg0 from int8 to int32
+ {name: "MOVBLZX", argLength: 1, reg: gp11, asm: "MOVBLZX"}, // zero extend arg0 from int8 to int32
+ {name: "MOVWLSX", argLength: 1, reg: gp11, asm: "MOVWLSX"}, // sign extend arg0 from int16 to int32
+ {name: "MOVWLZX", argLength: 1, reg: gp11, asm: "MOVWLZX"}, // zero extend arg0 from int16 to int32
+
+ {name: "MOVLconst", reg: gp01, asm: "MOVL", typ: "UInt32", aux: "Int32", rematerializeable: true}, // 32 low bits of auxint
+
+ {name: "CVTTSD2SL", argLength: 1, reg: fpgp, asm: "CVTTSD2SL", usesScratch: true}, // convert float64 to int32
+ {name: "CVTTSS2SL", argLength: 1, reg: fpgp, asm: "CVTTSS2SL", usesScratch: true}, // convert float32 to int32
+ {name: "CVTSL2SS", argLength: 1, reg: gpfp, asm: "CVTSL2SS", usesScratch: true}, // convert int32 to float32
+ {name: "CVTSL2SD", argLength: 1, reg: gpfp, asm: "CVTSL2SD", usesScratch: true}, // convert int32 to float64
+ {name: "CVTSD2SS", argLength: 1, reg: fp11, asm: "CVTSD2SS", usesScratch: true}, // convert float64 to float32
+ {name: "CVTSS2SD", argLength: 1, reg: fp11, asm: "CVTSS2SD"}, // convert float32 to float64
+
+ {name: "PXOR", argLength: 2, reg: fp21, asm: "PXOR", commutative: true, resultInArg0: true}, // exclusive or, applied to X regs for float negation.
+
+ {name: "LEAL", argLength: 1, reg: gp11sb, aux: "SymOff", rematerializeable: true, symEffect: "Addr"}, // arg0 + auxint + offset encoded in aux
+ {name: "LEAL1", argLength: 2, reg: gp21sb, commutative: true, aux: "SymOff", symEffect: "Addr"}, // arg0 + arg1 + auxint + aux
+ {name: "LEAL2", argLength: 2, reg: gp21sb, aux: "SymOff", symEffect: "Addr"}, // arg0 + 2*arg1 + auxint + aux
+ {name: "LEAL4", argLength: 2, reg: gp21sb, aux: "SymOff", symEffect: "Addr"}, // arg0 + 4*arg1 + auxint + aux
+ {name: "LEAL8", argLength: 2, reg: gp21sb, aux: "SymOff", symEffect: "Addr"}, // arg0 + 8*arg1 + auxint + aux
+ // Note: LEAL{1,2,4,8} must not have OpSB as either argument.
+
+ // auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
+ {name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVBLZX", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load byte from arg0+auxint+aux. arg1=mem. Zero extend.
+ {name: "MOVBLSXload", argLength: 2, reg: gpload, asm: "MOVBLSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int32
+ {name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVWLZX", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
+ {name: "MOVWLSXload", argLength: 2, reg: gpload, asm: "MOVWLSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int32
+ {name: "MOVLload", argLength: 2, reg: gpload, asm: "MOVL", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
+ {name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem
+ {name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
+ {name: "MOVLstore", argLength: 3, reg: gpstore, asm: "MOVL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
+
+ // direct binary-op on memory (read-modify-write)
+ {name: "ADDLmodify", argLength: 3, reg: gpstore, asm: "ADDL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) += arg1, arg2=mem
+ {name: "SUBLmodify", argLength: 3, reg: gpstore, asm: "SUBL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) -= arg1, arg2=mem
+ {name: "ANDLmodify", argLength: 3, reg: gpstore, asm: "ANDL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) &= arg1, arg2=mem
+ {name: "ORLmodify", argLength: 3, reg: gpstore, asm: "ORL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) |= arg1, arg2=mem
+ {name: "XORLmodify", argLength: 3, reg: gpstore, asm: "XORL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) ^= arg1, arg2=mem
+
+ // direct binary-op on indexed memory (read-modify-write)
+ {name: "ADDLmodifyidx4", argLength: 4, reg: gpstoreidx, asm: "ADDL", aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+arg1*4+auxint+aux) += arg2, arg3=mem
+ {name: "SUBLmodifyidx4", argLength: 4, reg: gpstoreidx, asm: "SUBL", aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+arg1*4+auxint+aux) -= arg2, arg3=mem
+ {name: "ANDLmodifyidx4", argLength: 4, reg: gpstoreidx, asm: "ANDL", aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+arg1*4+auxint+aux) &= arg2, arg3=mem
+ {name: "ORLmodifyidx4", argLength: 4, reg: gpstoreidx, asm: "ORL", aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+arg1*4+auxint+aux) |= arg2, arg3=mem
+ {name: "XORLmodifyidx4", argLength: 4, reg: gpstoreidx, asm: "XORL", aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+arg1*4+auxint+aux) ^= arg2, arg3=mem
+
+ // direct binary-op on memory with a constant (read-modify-write)
+ {name: "ADDLconstmodify", argLength: 2, reg: gpstoreconst, asm: "ADDL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // add ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "ANDLconstmodify", argLength: 2, reg: gpstoreconst, asm: "ANDL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // and ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "ORLconstmodify", argLength: 2, reg: gpstoreconst, asm: "ORL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // or ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "XORLconstmodify", argLength: 2, reg: gpstoreconst, asm: "XORL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // xor ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+
+ // direct binary-op on indexed memory with a constant (read-modify-write)
+ {name: "ADDLconstmodifyidx4", argLength: 3, reg: gpstoreconstidx, asm: "ADDL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // add ValAndOff(AuxInt).Val() to arg0+arg1*4+ValAndOff(AuxInt).Off()+aux, arg2=mem
+ {name: "ANDLconstmodifyidx4", argLength: 3, reg: gpstoreconstidx, asm: "ANDL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // and ValAndOff(AuxInt).Val() to arg0+arg1*4+ValAndOff(AuxInt).Off()+aux, arg2=mem
+ {name: "ORLconstmodifyidx4", argLength: 3, reg: gpstoreconstidx, asm: "ORL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // or ValAndOff(AuxInt).Val() to arg0+arg1*4+ValAndOff(AuxInt).Off()+aux, arg2=mem
+ {name: "XORLconstmodifyidx4", argLength: 3, reg: gpstoreconstidx, asm: "XORL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // xor ValAndOff(AuxInt).Val() to arg0+arg1*4+ValAndOff(AuxInt).Off()+aux, arg2=mem
+
+ // indexed loads/stores
+ {name: "MOVBloadidx1", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVBLZX", aux: "SymOff", symEffect: "Read"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem
+ {name: "MOVWloadidx1", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWLZX", aux: "SymOff", symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem
+ {name: "MOVWloadidx2", argLength: 3, reg: gploadidx, asm: "MOVWLZX", aux: "SymOff", symEffect: "Read"}, // load 2 bytes from arg0+2*arg1+auxint+aux. arg2=mem
+ {name: "MOVLloadidx1", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVL", aux: "SymOff", symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem
+ {name: "MOVLloadidx4", argLength: 3, reg: gploadidx, asm: "MOVL", aux: "SymOff", symEffect: "Read"}, // load 4 bytes from arg0+4*arg1+auxint+aux. arg2=mem
+ // TODO: sign-extending indexed loads
+ {name: "MOVBstoreidx1", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVB", aux: "SymOff", symEffect: "Write"}, // store byte in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVWstoreidx1", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVW", aux: "SymOff", symEffect: "Write"}, // store 2 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVWstoreidx2", argLength: 4, reg: gpstoreidx, asm: "MOVW", aux: "SymOff", symEffect: "Write"}, // store 2 bytes in arg2 to arg0+2*arg1+auxint+aux. arg3=mem
+ {name: "MOVLstoreidx1", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVL", aux: "SymOff", symEffect: "Write"}, // store 4 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVLstoreidx4", argLength: 4, reg: gpstoreidx, asm: "MOVL", aux: "SymOff", symEffect: "Write"}, // store 4 bytes in arg2 to arg0+4*arg1+auxint+aux. arg3=mem
+ // TODO: add size-mismatched indexed loads, like MOVBstoreidx4.
+
+ // For storeconst ops, the AuxInt field encodes both
+ // the value to store and an address offset of the store.
+ // Cast AuxInt to a ValAndOff to extract Val and Off fields.
+ {name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem
+ {name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 2 bytes of ...
+ {name: "MOVLstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVL", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 4 bytes of ...
+
+ {name: "MOVBstoreconstidx1", argLength: 3, reg: gpstoreconstidx, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+1*arg1+ValAndOff(AuxInt).Off()+aux. arg2=mem
+ {name: "MOVWstoreconstidx1", argLength: 3, reg: gpstoreconstidx, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low 2 bytes of ... arg1 ...
+ {name: "MOVWstoreconstidx2", argLength: 3, reg: gpstoreconstidx, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low 2 bytes of ... 2*arg1 ...
+ {name: "MOVLstoreconstidx1", argLength: 3, reg: gpstoreconstidx, asm: "MOVL", aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low 4 bytes of ... arg1 ...
+ {name: "MOVLstoreconstidx4", argLength: 3, reg: gpstoreconstidx, asm: "MOVL", aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low 4 bytes of ... 4*arg1 ...
+
+ // arg0 = 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",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("DI"), buildReg("AX")},
+ clobbers: buildReg("DI CX"),
+ // Note: CX is only clobbered when dynamic linking.
+ },
+ faultOnNilArg0: true,
+ },
+
+ // arg0 = address of memory to zero
+ // arg1 = # of 4-byte words to zero
+ // arg2 = value to store (will always be zero)
+ // arg3 = mem
+ // returns mem
+ {
+ name: "REPSTOSL",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{buildReg("DI"), buildReg("CX"), buildReg("AX")},
+ clobbers: buildReg("DI CX"),
+ },
+ faultOnNilArg0: true,
+ },
+
+ {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
+ {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
+ {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
+
+ // arg0 = destination pointer
+ // arg1 = source pointer
+ // arg2 = mem
+ // auxint = offset from duffcopy symbol to call
+ // returns memory
+ {
+ name: "DUFFCOPY",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("DI"), buildReg("SI")},
+ clobbers: buildReg("DI SI CX"), // uses CX as a temporary
+ },
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // arg0 = destination pointer
+ // arg1 = source pointer
+ // arg2 = # of 8-byte words to copy
+ // arg3 = mem
+ // returns memory
+ {
+ name: "REPMOVSL",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{buildReg("DI"), buildReg("SI"), buildReg("CX")},
+ clobbers: buildReg("DI SI CX"),
+ },
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // (InvertFlags (CMPL a b)) == (CMPL b a)
+ // So if we want (SETL (CMPL a b)) but we can't do that because a is a constant,
+ // then we do (SETL (InvertFlags (CMPL b a))) instead.
+ // Rewrites will convert this to (SETG (CMPL b a)).
+ // InvertFlags is a pseudo-op which can't appear in assembly output.
+ {name: "InvertFlags", argLength: 1}, // reverse direction of arg0
+
+ // Pseudo-ops
+ {name: "LoweredGetG", argLength: 1, reg: gp01}, // arg0=mem
+ // 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")}}, zeroWidth: true},
+ // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+ // I.e., if f calls g "calls" getcallerpc,
+ // the result should be the PC within f that g will return to.
+ // See runtime/stubs.go for a more detailed discussion.
+ {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
+ // LoweredGetCallerSP returns the SP of the caller of the current function.
+ {name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
+ //arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
+ {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
+
+ // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+ // It saves all GP registers if necessary, but may clobber others.
+ {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("DI"), ax}, clobbers: callerSave &^ gp}, clobberFlags: true, aux: "Sym", symEffect: "None"},
+
+ // There are three of these functions so that they can have three different register inputs.
+ // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
+ // default registers to match so we don't need to copy registers around unnecessarily.
+ {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{dx, bx}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{cx, dx}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{ax, cx}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ // Extend ops are the same as Bounds ops except the indexes are 64-bit.
+ {name: "LoweredPanicExtendA", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{si, dx, bx}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
+ {name: "LoweredPanicExtendB", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{si, cx, dx}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
+ {name: "LoweredPanicExtendC", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{si, ax, cx}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
+
+ // Constant flag values. For any comparison, there are 5 possible
+ // outcomes: the three from the signed total order (<,==,>) and the
+ // three from the unsigned total order. The == cases overlap.
+ // Note: there's a sixth "unordered" outcome for floating-point
+ // comparisons, but we don't use such a beast yet.
+ // These ops are for temporary use by rewrite rules. They
+ // cannot appear in the generated assembly.
+ {name: "FlagEQ"}, // equal
+ {name: "FlagLT_ULT"}, // signed < and unsigned <
+ {name: "FlagLT_UGT"}, // signed < and unsigned >
+ {name: "FlagGT_UGT"}, // signed > and unsigned <
+ {name: "FlagGT_ULT"}, // signed > and unsigned >
+
+ // Special ops for PIC floating-point constants.
+ // MOVSXconst1 loads the address of the constant-pool entry into a register.
+ // MOVSXconst2 loads the constant from that address.
+ // MOVSXconst1 returns a pointer, but we type it as uint32 because it can never point to the Go heap.
+ {name: "MOVSSconst1", reg: gp01, typ: "UInt32", aux: "Float32"},
+ {name: "MOVSDconst1", reg: gp01, typ: "UInt32", aux: "Float64"},
+ {name: "MOVSSconst2", argLength: 1, reg: gpfp, asm: "MOVSS"},
+ {name: "MOVSDconst2", argLength: 1, reg: gpfp, asm: "MOVSD"},
+ }
+
+ var _386blocks = []blockData{
+ {name: "EQ", controls: 1},
+ {name: "NE", controls: 1},
+ {name: "LT", controls: 1},
+ {name: "LE", controls: 1},
+ {name: "GT", controls: 1},
+ {name: "GE", controls: 1},
+ {name: "OS", controls: 1},
+ {name: "OC", controls: 1},
+ {name: "ULT", controls: 1},
+ {name: "ULE", controls: 1},
+ {name: "UGT", controls: 1},
+ {name: "UGE", controls: 1},
+ {name: "EQF", controls: 1},
+ {name: "NEF", controls: 1},
+ {name: "ORD", controls: 1}, // FP, ordered comparison (parity zero)
+ {name: "NAN", controls: 1}, // FP, unordered comparison (parity one)
+ }
+
+ archs = append(archs, arch{
+ name: "386",
+ pkg: "cmd/internal/obj/x86",
+ genfile: "../../x86/ssa.go",
+ ops: _386ops,
+ blocks: _386blocks,
+ regnames: regNames386,
+ gpregmask: gp,
+ fpregmask: fp,
+ framepointerreg: int8(num["BP"]),
+ linkreg: -1, // not used
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/386splitload.rules b/src/cmd/compile/internal/ssa/gen/386splitload.rules
new file mode 100644
index 0000000..ed93b90
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/386splitload.rules
@@ -0,0 +1,11 @@
+// Copyright 2019 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.
+
+// See the top of AMD64splitload.rules for discussion of these rules.
+
+(CMP(L|W|B)load {sym} [off] ptr x mem) => (CMP(L|W|B) (MOV(L|W|B)load {sym} [off] ptr mem) x)
+
+(CMPLconstload {sym} [vo] ptr mem) => (CMPLconst (MOVLload {sym} [vo.Off32()] ptr mem) [vo.Val32()])
+(CMPWconstload {sym} [vo] ptr mem) => (CMPWconst (MOVWload {sym} [vo.Off32()] ptr mem) [vo.Val16()])
+(CMPBconstload {sym} [vo] ptr mem) => (CMPBconst (MOVBload {sym} [vo.Off32()] ptr mem) [vo.Val8()])
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules
new file mode 100644
index 0000000..5de1e1e
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules
@@ -0,0 +1,2216 @@
+// 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.
+
+// Lowering arithmetic
+(Add(64|32|16|8) ...) => (ADD(Q|L|L|L) ...)
+(AddPtr ...) => (ADDQ ...)
+(Add(32|64)F ...) => (ADDS(S|D) ...)
+
+(Sub(64|32|16|8) ...) => (SUB(Q|L|L|L) ...)
+(SubPtr ...) => (SUBQ ...)
+(Sub(32|64)F ...) => (SUBS(S|D) ...)
+
+(Mul(64|32|16|8) ...) => (MUL(Q|L|L|L) ...)
+(Mul(32|64)F ...) => (MULS(S|D) ...)
+
+(Select0 (Mul64uover x y)) => (Select0 <typ.UInt64> (MULQU x y))
+(Select0 (Mul32uover x y)) => (Select0 <typ.UInt32> (MULLU x y))
+(Select1 (Mul(64|32)uover x y)) => (SETO (Select1 <types.TypeFlags> (MUL(Q|L)U x y)))
+
+(Hmul(64|32) ...) => (HMUL(Q|L) ...)
+(Hmul(64|32)u ...) => (HMUL(Q|L)U ...)
+
+(Div(64|32|16) [a] x y) => (Select0 (DIV(Q|L|W) [a] x y))
+(Div8 x y) => (Select0 (DIVW (SignExt8to16 x) (SignExt8to16 y)))
+(Div(64|32|16)u x y) => (Select0 (DIV(Q|L|W)U x y))
+(Div8u x y) => (Select0 (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y)))
+(Div(32|64)F ...) => (DIVS(S|D) ...)
+
+(Select0 (Add64carry x y c)) =>
+ (Select0 <typ.UInt64> (ADCQ x y (Select1 <types.TypeFlags> (NEGLflags c))))
+(Select1 (Add64carry x y c)) =>
+ (NEGQ <typ.UInt64> (SBBQcarrymask <typ.UInt64> (Select1 <types.TypeFlags> (ADCQ x y (Select1 <types.TypeFlags> (NEGLflags c))))))
+(Select0 (Sub64borrow x y c)) =>
+ (Select0 <typ.UInt64> (SBBQ x y (Select1 <types.TypeFlags> (NEGLflags c))))
+(Select1 (Sub64borrow x y c)) =>
+ (NEGQ <typ.UInt64> (SBBQcarrymask <typ.UInt64> (Select1 <types.TypeFlags> (SBBQ x y (Select1 <types.TypeFlags> (NEGLflags c))))))
+
+// Optimize ADCQ and friends
+(ADCQ x (MOVQconst [c]) carry) && is32Bit(c) => (ADCQconst x [int32(c)] carry)
+(ADCQ x y (FlagEQ)) => (ADDQcarry x y)
+(ADCQconst x [c] (FlagEQ)) => (ADDQconstcarry x [c])
+(ADDQcarry x (MOVQconst [c])) && is32Bit(c) => (ADDQconstcarry x [int32(c)])
+(SBBQ x (MOVQconst [c]) borrow) && is32Bit(c) => (SBBQconst x [int32(c)] borrow)
+(SBBQ x y (FlagEQ)) => (SUBQborrow x y)
+(SBBQconst x [c] (FlagEQ)) => (SUBQconstborrow x [c])
+(SUBQborrow x (MOVQconst [c])) && is32Bit(c) => (SUBQconstborrow x [int32(c)])
+(Select1 (NEGLflags (MOVQconst [0]))) => (FlagEQ)
+(Select1 (NEGLflags (NEGQ (SBBQcarrymask x)))) => x
+
+
+(Mul64uhilo ...) => (MULQU2 ...)
+(Div128u ...) => (DIVQU2 ...)
+
+(Avg64u ...) => (AVGQU ...)
+
+(Mod(64|32|16) [a] x y) => (Select1 (DIV(Q|L|W) [a] x y))
+(Mod8 x y) => (Select1 (DIVW (SignExt8to16 x) (SignExt8to16 y)))
+(Mod(64|32|16)u x y) => (Select1 (DIV(Q|L|W)U x y))
+(Mod8u x y) => (Select1 (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y)))
+
+(And(64|32|16|8) ...) => (AND(Q|L|L|L) ...)
+(Or(64|32|16|8) ...) => (OR(Q|L|L|L) ...)
+(Xor(64|32|16|8) ...) => (XOR(Q|L|L|L) ...)
+(Com(64|32|16|8) ...) => (NOT(Q|L|L|L) ...)
+
+(Neg(64|32|16|8) ...) => (NEG(Q|L|L|L) ...)
+(Neg32F x) => (PXOR x (MOVSSconst <typ.Float32> [float32(math.Copysign(0, -1))]))
+(Neg64F x) => (PXOR x (MOVSDconst <typ.Float64> [math.Copysign(0, -1)]))
+
+// Lowering boolean ops
+(AndB ...) => (ANDL ...)
+(OrB ...) => (ORL ...)
+(Not x) => (XORLconst [1] x)
+
+// Lowering pointer arithmetic
+(OffPtr [off] ptr) && is32Bit(off) => (ADDQconst [int32(off)] ptr)
+(OffPtr [off] ptr) => (ADDQ (MOVQconst [off]) ptr)
+
+// Lowering other arithmetic
+(Ctz64 <t> x) => (CMOVQEQ (Select0 <t> (BSFQ x)) (MOVQconst <t> [64]) (Select1 <types.TypeFlags> (BSFQ x)))
+(Ctz32 x) => (Select0 (BSFQ (BTSQconst <typ.UInt64> [32] x)))
+(Ctz16 x) => (BSFL (BTSLconst <typ.UInt32> [16] x))
+(Ctz8 x) => (BSFL (BTSLconst <typ.UInt32> [ 8] x))
+
+(Ctz64NonZero x) => (Select0 (BSFQ x))
+(Ctz32NonZero ...) => (BSFL ...)
+(Ctz16NonZero ...) => (BSFL ...)
+(Ctz8NonZero ...) => (BSFL ...)
+
+// BitLen64 of a 64 bit value x requires checking whether x == 0, since BSRQ is undefined when x == 0.
+// However, for zero-extended values, we can cheat a bit, and calculate
+// BSR(x<<1 + 1), which is guaranteed to be non-zero, and which conveniently
+// places the index of the highest set bit where we want it.
+(BitLen64 <t> x) => (ADDQconst [1] (CMOVQEQ <t> (Select0 <t> (BSRQ x)) (MOVQconst <t> [-1]) (Select1 <types.TypeFlags> (BSRQ x))))
+(BitLen32 x) => (Select0 (BSRQ (LEAQ1 <typ.UInt64> [1] (MOVLQZX <typ.UInt64> x) (MOVLQZX <typ.UInt64> x))))
+(BitLen16 x) => (BSRL (LEAL1 <typ.UInt32> [1] (MOVWQZX <typ.UInt32> x) (MOVWQZX <typ.UInt32> x)))
+(BitLen8 x) => (BSRL (LEAL1 <typ.UInt32> [1] (MOVBQZX <typ.UInt32> x) (MOVBQZX <typ.UInt32> x)))
+
+(Bswap(64|32) ...) => (BSWAP(Q|L) ...)
+
+(PopCount(64|32) ...) => (POPCNT(Q|L) ...)
+(PopCount16 x) => (POPCNTL (MOVWQZX <typ.UInt32> x))
+(PopCount8 x) => (POPCNTL (MOVBQZX <typ.UInt32> x))
+
+(Sqrt ...) => (SQRTSD ...)
+
+(RoundToEven x) => (ROUNDSD [0] x)
+(Floor x) => (ROUNDSD [1] x)
+(Ceil x) => (ROUNDSD [2] x)
+(Trunc x) => (ROUNDSD [3] x)
+
+(FMA x y z) => (VFMADD231SD z x y)
+
+// Lowering extension
+// Note: we always extend to 64 bits even though some ops don't need that many result bits.
+(SignExt8to16 ...) => (MOVBQSX ...)
+(SignExt8to32 ...) => (MOVBQSX ...)
+(SignExt8to64 ...) => (MOVBQSX ...)
+(SignExt16to32 ...) => (MOVWQSX ...)
+(SignExt16to64 ...) => (MOVWQSX ...)
+(SignExt32to64 ...) => (MOVLQSX ...)
+
+(ZeroExt8to16 ...) => (MOVBQZX ...)
+(ZeroExt8to32 ...) => (MOVBQZX ...)
+(ZeroExt8to64 ...) => (MOVBQZX ...)
+(ZeroExt16to32 ...) => (MOVWQZX ...)
+(ZeroExt16to64 ...) => (MOVWQZX ...)
+(ZeroExt32to64 ...) => (MOVLQZX ...)
+
+(Slicemask <t> x) => (SARQconst (NEGQ <t> x) [63])
+
+(SpectreIndex <t> x y) => (CMOVQCC x (MOVQconst [0]) (CMPQ x y))
+(SpectreSliceIndex <t> x y) => (CMOVQHI x (MOVQconst [0]) (CMPQ x y))
+
+// Lowering truncation
+// Because we ignore high parts of registers, truncates are just copies.
+(Trunc16to8 ...) => (Copy ...)
+(Trunc32to8 ...) => (Copy ...)
+(Trunc32to16 ...) => (Copy ...)
+(Trunc64to8 ...) => (Copy ...)
+(Trunc64to16 ...) => (Copy ...)
+(Trunc64to32 ...) => (Copy ...)
+
+// Lowering float <-> int
+(Cvt32to32F ...) => (CVTSL2SS ...)
+(Cvt32to64F ...) => (CVTSL2SD ...)
+(Cvt64to32F ...) => (CVTSQ2SS ...)
+(Cvt64to64F ...) => (CVTSQ2SD ...)
+
+(Cvt32Fto32 ...) => (CVTTSS2SL ...)
+(Cvt32Fto64 ...) => (CVTTSS2SQ ...)
+(Cvt64Fto32 ...) => (CVTTSD2SL ...)
+(Cvt64Fto64 ...) => (CVTTSD2SQ ...)
+
+(Cvt32Fto64F ...) => (CVTSS2SD ...)
+(Cvt64Fto32F ...) => (CVTSD2SS ...)
+
+(Round(32|64)F ...) => (Copy ...)
+
+(CvtBoolToUint8 ...) => (Copy ...)
+
+// Lowering shifts
+// Unsigned shifts need to return 0 if shift amount is >= width of shifted value.
+// result = (arg << shift) & (shift >= argbits ? 0 : 0xffffffffffffffff)
+(Lsh64x(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDQ (SHLQ <t> x y) (SBBQcarrymask <t> (CMP(Q|L|W|B)const y [64])))
+(Lsh32x(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [32])))
+(Lsh16x(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [32])))
+(Lsh8x(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [32])))
+
+(Lsh64x(64|32|16|8) x y) && shiftIsBounded(v) => (SHLQ x y)
+(Lsh32x(64|32|16|8) x y) && shiftIsBounded(v) => (SHLL x y)
+(Lsh16x(64|32|16|8) x y) && shiftIsBounded(v) => (SHLL x y)
+(Lsh8x(64|32|16|8) x y) && shiftIsBounded(v) => (SHLL x y)
+
+(Rsh64Ux(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDQ (SHRQ <t> x y) (SBBQcarrymask <t> (CMP(Q|L|W|B)const y [64])))
+(Rsh32Ux(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [32])))
+(Rsh16Ux(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [16])))
+(Rsh8Ux(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [8])))
+
+(Rsh64Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SHRQ x y)
+(Rsh32Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SHRL x y)
+(Rsh16Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SHRW x y)
+(Rsh8Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SHRB x 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.
+(Rsh64x(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (SARQ <t> x (OR(Q|L|L|L) <y.Type> y (NOT(Q|L|L|L) <y.Type> (SBB(Q|L|L|L)carrymask <y.Type> (CMP(Q|L|W|B)const y [64])))))
+(Rsh32x(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (SARL <t> x (OR(Q|L|L|L) <y.Type> y (NOT(Q|L|L|L) <y.Type> (SBB(Q|L|L|L)carrymask <y.Type> (CMP(Q|L|W|B)const y [32])))))
+(Rsh16x(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (SARW <t> x (OR(Q|L|L|L) <y.Type> y (NOT(Q|L|L|L) <y.Type> (SBB(Q|L|L|L)carrymask <y.Type> (CMP(Q|L|W|B)const y [16])))))
+(Rsh8x(64|32|16|8) <t> x y) && !shiftIsBounded(v) => (SARB <t> x (OR(Q|L|L|L) <y.Type> y (NOT(Q|L|L|L) <y.Type> (SBB(Q|L|L|L)carrymask <y.Type> (CMP(Q|L|W|B)const y [8])))))
+
+(Rsh64x(64|32|16|8) x y) && shiftIsBounded(v) => (SARQ x y)
+(Rsh32x(64|32|16|8) x y) && shiftIsBounded(v) => (SARL x y)
+(Rsh16x(64|32|16|8) x y) && shiftIsBounded(v) => (SARW x y)
+(Rsh8x(64|32|16|8) x y) && shiftIsBounded(v) => (SARB x y)
+
+// Lowering integer comparisons
+(Less(64|32|16|8) x y) => (SETL (CMP(Q|L|W|B) x y))
+(Less(64|32|16|8)U x y) => (SETB (CMP(Q|L|W|B) x y))
+(Leq(64|32|16|8) x y) => (SETLE (CMP(Q|L|W|B) x y))
+(Leq(64|32|16|8)U x y) => (SETBE (CMP(Q|L|W|B) x y))
+(Eq(Ptr|64|32|16|8|B) x y) => (SETEQ (CMP(Q|Q|L|W|B|B) x y))
+(Neq(Ptr|64|32|16|8|B) x y) => (SETNE (CMP(Q|Q|L|W|B|B) x y))
+
+// Lowering floating point comparisons
+// Note Go assembler gets UCOMISx operand order wrong, but it is right here
+// and the operands are reversed when generating assembly language.
+(Eq(32|64)F x y) => (SETEQF (UCOMIS(S|D) x y))
+(Neq(32|64)F x y) => (SETNEF (UCOMIS(S|D) x y))
+// Use SETGF/SETGEF with reversed operands to dodge NaN case.
+(Less(32|64)F x y) => (SETGF (UCOMIS(S|D) y x))
+(Leq(32|64)F x y) => (SETGEF (UCOMIS(S|D) y x))
+
+// Lowering loads
+(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) => (MOVQload ptr mem)
+(Load <t> ptr mem) && is32BitInt(t) => (MOVLload ptr mem)
+(Load <t> ptr mem) && is16BitInt(t) => (MOVWload ptr mem)
+(Load <t> ptr mem) && (t.IsBoolean() || is8BitInt(t)) => (MOVBload ptr mem)
+(Load <t> ptr mem) && is32BitFloat(t) => (MOVSSload ptr mem)
+(Load <t> ptr mem) && is64BitFloat(t) => (MOVSDload ptr mem)
+
+// Lowering stores
+// These more-specific FP versions of Store pattern should come first.
+(Store {t} ptr val mem) && t.Size() == 8 && is64BitFloat(val.Type) => (MOVSDstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && is32BitFloat(val.Type) => (MOVSSstore ptr val mem)
+
+(Store {t} ptr val mem) && t.Size() == 8 => (MOVQstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 => (MOVLstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 2 => (MOVWstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 1 => (MOVBstore ptr val mem)
+
+// Lowering moves
+(Move [0] _ _ mem) => mem
+(Move [1] dst src mem) => (MOVBstore dst (MOVBload src mem) mem)
+(Move [2] dst src mem) => (MOVWstore dst (MOVWload src mem) mem)
+(Move [4] dst src mem) => (MOVLstore dst (MOVLload src mem) mem)
+(Move [8] dst src mem) => (MOVQstore dst (MOVQload src mem) mem)
+(Move [16] dst src mem) && config.useSSE => (MOVOstore dst (MOVOload src mem) mem)
+(Move [16] dst src mem) && !config.useSSE =>
+ (MOVQstore [8] dst (MOVQload [8] src mem)
+ (MOVQstore dst (MOVQload src mem) mem))
+
+(Move [32] dst src mem) =>
+ (Move [16]
+ (OffPtr <dst.Type> dst [16])
+ (OffPtr <src.Type> src [16])
+ (Move [16] dst src mem))
+
+(Move [48] dst src mem) && config.useSSE =>
+ (Move [32]
+ (OffPtr <dst.Type> dst [16])
+ (OffPtr <src.Type> src [16])
+ (Move [16] dst src mem))
+
+(Move [64] dst src mem) && config.useSSE =>
+ (Move [32]
+ (OffPtr <dst.Type> dst [32])
+ (OffPtr <src.Type> src [32])
+ (Move [32] dst src mem))
+
+(Move [3] dst src mem) =>
+ (MOVBstore [2] dst (MOVBload [2] src mem)
+ (MOVWstore dst (MOVWload src mem) mem))
+(Move [5] dst src mem) =>
+ (MOVBstore [4] dst (MOVBload [4] src mem)
+ (MOVLstore dst (MOVLload src mem) mem))
+(Move [6] dst src mem) =>
+ (MOVWstore [4] dst (MOVWload [4] src mem)
+ (MOVLstore dst (MOVLload src mem) mem))
+(Move [7] dst src mem) =>
+ (MOVLstore [3] dst (MOVLload [3] src mem)
+ (MOVLstore dst (MOVLload src mem) mem))
+(Move [9] dst src mem) =>
+ (MOVBstore [8] dst (MOVBload [8] src mem)
+ (MOVQstore dst (MOVQload src mem) mem))
+(Move [10] dst src mem) =>
+ (MOVWstore [8] dst (MOVWload [8] src mem)
+ (MOVQstore dst (MOVQload src mem) mem))
+(Move [12] dst src mem) =>
+ (MOVLstore [8] dst (MOVLload [8] src mem)
+ (MOVQstore dst (MOVQload src mem) mem))
+(Move [s] dst src mem) && s == 11 || s >= 13 && s <= 15 =>
+ (MOVQstore [int32(s-8)] dst (MOVQload [int32(s-8)] src mem)
+ (MOVQstore dst (MOVQload src mem) mem))
+
+// Adjust moves to be a multiple of 16 bytes.
+(Move [s] dst src mem)
+ && s > 16 && s%16 != 0 && s%16 <= 8 =>
+ (Move [s-s%16]
+ (OffPtr <dst.Type> dst [s%16])
+ (OffPtr <src.Type> src [s%16])
+ (MOVQstore dst (MOVQload src mem) mem))
+(Move [s] dst src mem)
+ && s > 16 && s%16 != 0 && s%16 > 8 && config.useSSE =>
+ (Move [s-s%16]
+ (OffPtr <dst.Type> dst [s%16])
+ (OffPtr <src.Type> src [s%16])
+ (MOVOstore dst (MOVOload src mem) mem))
+(Move [s] dst src mem)
+ && s > 16 && s%16 != 0 && s%16 > 8 && !config.useSSE =>
+ (Move [s-s%16]
+ (OffPtr <dst.Type> dst [s%16])
+ (OffPtr <src.Type> src [s%16])
+ (MOVQstore [8] dst (MOVQload [8] src mem)
+ (MOVQstore dst (MOVQload src mem) mem)))
+
+// Medium copying uses a duff device.
+(Move [s] dst src mem)
+ && s > 64 && s <= 16*64 && s%16 == 0
+ && !config.noDuffDevice && logLargeCopy(v, s) =>
+ (DUFFCOPY [s] dst src mem)
+
+// Large copying uses REP MOVSQ.
+(Move [s] dst src mem) && (s > 16*64 || config.noDuffDevice) && s%8 == 0 && logLargeCopy(v, s) =>
+ (REPMOVSQ dst src (MOVQconst [s/8]) mem)
+
+// Lowering Zero instructions
+(Zero [0] _ mem) => mem
+(Zero [1] destptr mem) => (MOVBstoreconst [makeValAndOff32(0,0)] destptr mem)
+(Zero [2] destptr mem) => (MOVWstoreconst [makeValAndOff32(0,0)] destptr mem)
+(Zero [4] destptr mem) => (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem)
+(Zero [8] destptr mem) => (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem)
+
+(Zero [3] destptr mem) =>
+ (MOVBstoreconst [makeValAndOff32(0,2)] destptr
+ (MOVWstoreconst [makeValAndOff32(0,0)] destptr mem))
+(Zero [5] destptr mem) =>
+ (MOVBstoreconst [makeValAndOff32(0,4)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+(Zero [6] destptr mem) =>
+ (MOVWstoreconst [makeValAndOff32(0,4)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+(Zero [7] destptr mem) =>
+ (MOVLstoreconst [makeValAndOff32(0,3)] destptr
+ (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+
+// Strip off any fractional word zeroing.
+(Zero [s] destptr mem) && s%8 != 0 && s > 8 && !config.useSSE =>
+ (Zero [s-s%8] (OffPtr <destptr.Type> destptr [s%8])
+ (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem))
+
+// Zero small numbers of words directly.
+(Zero [16] destptr mem) && !config.useSSE =>
+ (MOVQstoreconst [makeValAndOff32(0,8)] destptr
+ (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem))
+(Zero [24] destptr mem) && !config.useSSE =>
+ (MOVQstoreconst [makeValAndOff32(0,16)] destptr
+ (MOVQstoreconst [makeValAndOff32(0,8)] destptr
+ (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem)))
+(Zero [32] destptr mem) && !config.useSSE =>
+ (MOVQstoreconst [makeValAndOff32(0,24)] destptr
+ (MOVQstoreconst [makeValAndOff32(0,16)] destptr
+ (MOVQstoreconst [makeValAndOff32(0,8)] destptr
+ (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem))))
+
+(Zero [s] destptr mem) && s > 8 && s < 16 && config.useSSE =>
+ (MOVQstoreconst [makeValAndOff32(0,int32(s-8))] destptr
+ (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem))
+
+// Adjust zeros to be a multiple of 16 bytes.
+(Zero [s] destptr mem) && s%16 != 0 && s > 16 && s%16 > 8 && config.useSSE =>
+ (Zero [s-s%16] (OffPtr <destptr.Type> destptr [s%16])
+ (MOVOstore destptr (MOVOconst [0]) mem))
+
+(Zero [s] destptr mem) && s%16 != 0 && s > 16 && s%16 <= 8 && config.useSSE =>
+ (Zero [s-s%16] (OffPtr <destptr.Type> destptr [s%16])
+ (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem))
+
+(Zero [16] destptr mem) && config.useSSE =>
+ (MOVOstore destptr (MOVOconst [0]) mem)
+(Zero [32] destptr mem) && config.useSSE =>
+ (MOVOstore (OffPtr <destptr.Type> destptr [16]) (MOVOconst [0])
+ (MOVOstore destptr (MOVOconst [0]) mem))
+(Zero [48] destptr mem) && config.useSSE =>
+ (MOVOstore (OffPtr <destptr.Type> destptr [32]) (MOVOconst [0])
+ (MOVOstore (OffPtr <destptr.Type> destptr [16]) (MOVOconst [0])
+ (MOVOstore destptr (MOVOconst [0]) mem)))
+(Zero [64] destptr mem) && config.useSSE =>
+ (MOVOstore (OffPtr <destptr.Type> destptr [48]) (MOVOconst [0])
+ (MOVOstore (OffPtr <destptr.Type> destptr [32]) (MOVOconst [0])
+ (MOVOstore (OffPtr <destptr.Type> destptr [16]) (MOVOconst [0])
+ (MOVOstore destptr (MOVOconst [0]) mem))))
+
+// Medium zeroing uses a duff device.
+(Zero [s] destptr mem)
+ && s > 64 && s <= 1024 && s%16 == 0 && !config.noDuffDevice =>
+ (DUFFZERO [s] destptr (MOVOconst [0]) mem)
+
+// Large zeroing uses REP STOSQ.
+(Zero [s] destptr mem)
+ && (s > 1024 || (config.noDuffDevice && s > 64 || !config.useSSE && s > 32))
+ && s%8 == 0 =>
+ (REPSTOSQ destptr (MOVQconst [s/8]) (MOVQconst [0]) mem)
+
+// Lowering constants
+(Const8 [c]) => (MOVLconst [int32(c)])
+(Const16 [c]) => (MOVLconst [int32(c)])
+(Const32 ...) => (MOVLconst ...)
+(Const64 ...) => (MOVQconst ...)
+(Const32F ...) => (MOVSSconst ...)
+(Const64F ...) => (MOVSDconst ...)
+(ConstNil ) => (MOVQconst [0])
+(ConstBool [c]) => (MOVLconst [b2i32(c)])
+
+// Lowering calls
+(StaticCall ...) => (CALLstatic ...)
+(ClosureCall ...) => (CALLclosure ...)
+(InterCall ...) => (CALLinter ...)
+
+// Lowering conditional moves
+// If the condition is a SETxx, we can just run a CMOV from the comparison that was
+// setting the flags.
+// Legend: HI=unsigned ABOVE, CS=unsigned BELOW, CC=unsigned ABOVE EQUAL, LS=unsigned BELOW EQUAL
+(CondSelect <t> x y (SET(EQ|NE|L|G|LE|GE|A|B|AE|BE|EQF|NEF|GF|GEF) cond)) && (is64BitInt(t) || isPtr(t))
+ => (CMOVQ(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS|EQF|NEF|GTF|GEF) y x cond)
+(CondSelect <t> x y (SET(EQ|NE|L|G|LE|GE|A|B|AE|BE|EQF|NEF|GF|GEF) cond)) && is32BitInt(t)
+ => (CMOVL(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS|EQF|NEF|GTF|GEF) y x cond)
+(CondSelect <t> x y (SET(EQ|NE|L|G|LE|GE|A|B|AE|BE|EQF|NEF|GF|GEF) cond)) && is16BitInt(t)
+ => (CMOVW(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS|EQF|NEF|GTF|GEF) y x cond)
+
+// If the condition does not set the flags, we need to generate a comparison.
+(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 1
+ => (CondSelect <t> x y (MOVBQZX <typ.UInt64> check))
+(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 2
+ => (CondSelect <t> x y (MOVWQZX <typ.UInt64> check))
+(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 4
+ => (CondSelect <t> x y (MOVLQZX <typ.UInt64> check))
+
+(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 8 && (is64BitInt(t) || isPtr(t))
+ => (CMOVQNE y x (CMPQconst [0] check))
+(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 8 && is32BitInt(t)
+ => (CMOVLNE y x (CMPQconst [0] check))
+(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 8 && is16BitInt(t)
+ => (CMOVWNE y x (CMPQconst [0] check))
+
+// Absorb InvertFlags
+(CMOVQ(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS) x y (InvertFlags cond))
+ => (CMOVQ(EQ|NE|GT|LT|GE|LE|CS|HI|LS|CC) x y cond)
+(CMOVL(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS) x y (InvertFlags cond))
+ => (CMOVL(EQ|NE|GT|LT|GE|LE|CS|HI|LS|CC) x y cond)
+(CMOVW(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS) x y (InvertFlags cond))
+ => (CMOVW(EQ|NE|GT|LT|GE|LE|CS|HI|LS|CC) x y cond)
+
+// Absorb constants generated during lower
+(CMOV(QEQ|QLE|QGE|QCC|QLS|LEQ|LLE|LGE|LCC|LLS|WEQ|WLE|WGE|WCC|WLS) _ x (FlagEQ)) => x
+(CMOV(QNE|QLT|QGT|QCS|QHI|LNE|LLT|LGT|LCS|LHI|WNE|WLT|WGT|WCS|WHI) y _ (FlagEQ)) => y
+(CMOV(QNE|QGT|QGE|QHI|QCC|LNE|LGT|LGE|LHI|LCC|WNE|WGT|WGE|WHI|WCC) _ x (FlagGT_UGT)) => x
+(CMOV(QEQ|QLE|QLT|QLS|QCS|LEQ|LLE|LLT|LLS|LCS|WEQ|WLE|WLT|WLS|WCS) y _ (FlagGT_UGT)) => y
+(CMOV(QNE|QGT|QGE|QLS|QCS|LNE|LGT|LGE|LLS|LCS|WNE|WGT|WGE|WLS|WCS) _ x (FlagGT_ULT)) => x
+(CMOV(QEQ|QLE|QLT|QHI|QCC|LEQ|LLE|LLT|LHI|LCC|WEQ|WLE|WLT|WHI|WCC) y _ (FlagGT_ULT)) => y
+(CMOV(QNE|QLT|QLE|QCS|QLS|LNE|LLT|LLE|LCS|LLS|WNE|WLT|WLE|WCS|WLS) _ x (FlagLT_ULT)) => x
+(CMOV(QEQ|QGT|QGE|QHI|QCC|LEQ|LGT|LGE|LHI|LCC|WEQ|WGT|WGE|WHI|WCC) y _ (FlagLT_ULT)) => y
+(CMOV(QNE|QLT|QLE|QHI|QCC|LNE|LLT|LLE|LHI|LCC|WNE|WLT|WLE|WHI|WCC) _ x (FlagLT_UGT)) => x
+(CMOV(QEQ|QGT|QGE|QCS|QLS|LEQ|LGT|LGE|LCS|LLS|WEQ|WGT|WGE|WCS|WLS) y _ (FlagLT_UGT)) => y
+
+// Miscellaneous
+(IsNonNil p) => (SETNE (TESTQ p p))
+(IsInBounds idx len) => (SETB (CMPQ idx len))
+(IsSliceInBounds idx len) => (SETBE (CMPQ idx len))
+(NilCheck ...) => (LoweredNilCheck ...)
+(GetG ...) => (LoweredGetG ...)
+(GetClosurePtr ...) => (LoweredGetClosurePtr ...)
+(GetCallerPC ...) => (LoweredGetCallerPC ...)
+(GetCallerSP ...) => (LoweredGetCallerSP ...)
+
+(HasCPUFeature {s}) => (SETNE (CMPQconst [0] (LoweredHasCPUFeature {s})))
+(Addr {sym} base) => (LEAQ {sym} base)
+(LocalAddr {sym} base _) => (LEAQ {sym} base)
+
+(MOVBstore [off] {sym} ptr y:(SETL x) mem) && y.Uses == 1 => (SETLstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr y:(SETLE x) mem) && y.Uses == 1 => (SETLEstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr y:(SETG x) mem) && y.Uses == 1 => (SETGstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr y:(SETGE x) mem) && y.Uses == 1 => (SETGEstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr y:(SETEQ x) mem) && y.Uses == 1 => (SETEQstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr y:(SETNE x) mem) && y.Uses == 1 => (SETNEstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr y:(SETB x) mem) && y.Uses == 1 => (SETBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr y:(SETBE x) mem) && y.Uses == 1 => (SETBEstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr y:(SETA x) mem) && y.Uses == 1 => (SETAstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr y:(SETAE x) mem) && y.Uses == 1 => (SETAEstore [off] {sym} ptr x 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)
+(If (SETO cmp) yes no) => (OS 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) => (NEF cmp yes no)
+
+(If cond yes no) => (NE (TESTB cond cond) yes no)
+
+// Atomic loads. Other than preserving their ordering with respect to other loads, nothing special here.
+(AtomicLoad8 ptr mem) => (MOVBatomicload ptr mem)
+(AtomicLoad32 ptr mem) => (MOVLatomicload ptr mem)
+(AtomicLoad64 ptr mem) => (MOVQatomicload ptr mem)
+(AtomicLoadPtr ptr mem) => (MOVQatomicload ptr mem)
+
+// Atomic stores. We use XCHG to prevent the hardware reordering a subsequent load.
+// TODO: most runtime uses of atomic stores don't need that property. Use normal stores for those?
+(AtomicStore8 ptr val mem) => (Select1 (XCHGB <types.NewTuple(typ.UInt8,types.TypeMem)> val ptr mem))
+(AtomicStore32 ptr val mem) => (Select1 (XCHGL <types.NewTuple(typ.UInt32,types.TypeMem)> val ptr mem))
+(AtomicStore64 ptr val mem) => (Select1 (XCHGQ <types.NewTuple(typ.UInt64,types.TypeMem)> val ptr mem))
+(AtomicStorePtrNoWB ptr val mem) => (Select1 (XCHGQ <types.NewTuple(typ.BytePtr,types.TypeMem)> val ptr mem))
+
+// Atomic exchanges.
+(AtomicExchange32 ptr val mem) => (XCHGL val ptr mem)
+(AtomicExchange64 ptr val mem) => (XCHGQ val ptr mem)
+
+// Atomic adds.
+(AtomicAdd32 ptr val mem) => (AddTupleFirst32 val (XADDLlock val ptr mem))
+(AtomicAdd64 ptr val mem) => (AddTupleFirst64 val (XADDQlock val ptr mem))
+(Select0 <t> (AddTupleFirst32 val tuple)) => (ADDL val (Select0 <t> tuple))
+(Select1 (AddTupleFirst32 _ tuple)) => (Select1 tuple)
+(Select0 <t> (AddTupleFirst64 val tuple)) => (ADDQ val (Select0 <t> tuple))
+(Select1 (AddTupleFirst64 _ tuple)) => (Select1 tuple)
+
+// Atomic compare and swap.
+(AtomicCompareAndSwap32 ptr old new_ mem) => (CMPXCHGLlock ptr old new_ mem)
+(AtomicCompareAndSwap64 ptr old new_ mem) => (CMPXCHGQlock ptr old new_ mem)
+
+// Atomic memory updates.
+(AtomicAnd8 ptr val mem) => (ANDBlock ptr val mem)
+(AtomicAnd32 ptr val mem) => (ANDLlock ptr val mem)
+(AtomicOr8 ptr val mem) => (ORBlock ptr val mem)
+(AtomicOr32 ptr val mem) => (ORLlock ptr val mem)
+
+// Write barrier.
+(WB ...) => (LoweredWB ...)
+
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
+
+// ***************************
+// Above: lowering rules
+// Below: optimizations
+// ***************************
+// TODO: Should the optimizations be a separate pass?
+
+// Fold boolean tests into blocks
+(NE (TESTB (SETL cmp) (SETL cmp)) yes no) => (LT cmp yes no)
+(NE (TESTB (SETLE cmp) (SETLE cmp)) yes no) => (LE cmp yes no)
+(NE (TESTB (SETG cmp) (SETG cmp)) yes no) => (GT cmp yes no)
+(NE (TESTB (SETGE cmp) (SETGE cmp)) yes no) => (GE cmp yes no)
+(NE (TESTB (SETEQ cmp) (SETEQ cmp)) yes no) => (EQ cmp yes no)
+(NE (TESTB (SETNE cmp) (SETNE cmp)) yes no) => (NE cmp yes no)
+(NE (TESTB (SETB cmp) (SETB cmp)) yes no) => (ULT cmp yes no)
+(NE (TESTB (SETBE cmp) (SETBE cmp)) yes no) => (ULE cmp yes no)
+(NE (TESTB (SETA cmp) (SETA cmp)) yes no) => (UGT cmp yes no)
+(NE (TESTB (SETAE cmp) (SETAE cmp)) yes no) => (UGE cmp yes no)
+(NE (TESTB (SETO cmp) (SETO cmp)) yes no) => (OS cmp yes no)
+
+// Unsigned comparisons to 0/1
+(ULT (TEST(Q|L|W|B) x x) yes no) => (First no yes)
+(UGE (TEST(Q|L|W|B) x x) yes no) => (First yes no)
+(SETB (TEST(Q|L|W|B) x x)) => (ConstBool [false])
+(SETAE (TEST(Q|L|W|B) x x)) => (ConstBool [true])
+
+// x & 1 != 0 -> x & 1
+(SETNE (TEST(B|W)const [1] x)) => (AND(L|L)const [1] x)
+(SETB (BT(L|Q)const [0] x)) => (AND(L|Q)const [1] x)
+
+// Recognize bit tests: a&(1<<b) != 0 for b suitably bounded
+// Note that BTx instructions use the carry bit, so we need to convert tests for zero flag
+// into tests for carry flags.
+// ULT and SETB check the carry flag; they are identical to CS and SETCS. Same, mutatis
+// mutandis, for UGE and SETAE, and CC and SETCC.
+((NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) => ((ULT|UGE) (BTL x y))
+((NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) => ((ULT|UGE) (BTQ x y))
+((NE|EQ) (TESTLconst [c] x)) && isUint32PowerOfTwo(int64(c))
+ => ((ULT|UGE) (BTLconst [int8(log32(c))] x))
+((NE|EQ) (TESTQconst [c] x)) && isUint64PowerOfTwo(int64(c))
+ => ((ULT|UGE) (BTQconst [int8(log32(c))] x))
+((NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUint64PowerOfTwo(c)
+ => ((ULT|UGE) (BTQconst [int8(log64(c))] x))
+(SET(NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) => (SET(B|AE) (BTL x y))
+(SET(NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) => (SET(B|AE) (BTQ x y))
+(SET(NE|EQ) (TESTLconst [c] x)) && isUint32PowerOfTwo(int64(c))
+ => (SET(B|AE) (BTLconst [int8(log32(c))] x))
+(SET(NE|EQ) (TESTQconst [c] x)) && isUint64PowerOfTwo(int64(c))
+ => (SET(B|AE) (BTQconst [int8(log32(c))] x))
+(SET(NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUint64PowerOfTwo(c)
+ => (SET(B|AE) (BTQconst [int8(log64(c))] x))
+// SET..store variant
+(SET(NE|EQ)store [off] {sym} ptr (TESTL (SHLL (MOVLconst [1]) x) y) mem)
+ => (SET(B|AE)store [off] {sym} ptr (BTL x y) mem)
+(SET(NE|EQ)store [off] {sym} ptr (TESTQ (SHLQ (MOVQconst [1]) x) y) mem)
+ => (SET(B|AE)store [off] {sym} ptr (BTQ x y) mem)
+(SET(NE|EQ)store [off] {sym} ptr (TESTLconst [c] x) mem) && isUint32PowerOfTwo(int64(c))
+ => (SET(B|AE)store [off] {sym} ptr (BTLconst [int8(log32(c))] x) mem)
+(SET(NE|EQ)store [off] {sym} ptr (TESTQconst [c] x) mem) && isUint64PowerOfTwo(int64(c))
+ => (SET(B|AE)store [off] {sym} ptr (BTQconst [int8(log32(c))] x) mem)
+(SET(NE|EQ)store [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem) && isUint64PowerOfTwo(c)
+ => (SET(B|AE)store [off] {sym} ptr (BTQconst [int8(log64(c))] x) mem)
+
+// Handle bit-testing in the form (a>>b)&1 != 0 by building the above rules
+// and further combining shifts.
+(BT(Q|L)const [c] (SHRQconst [d] x)) && (c+d)<64 => (BTQconst [c+d] x)
+(BT(Q|L)const [c] (SHLQconst [d] x)) && c>d => (BT(Q|L)const [c-d] x)
+(BT(Q|L)const [0] s:(SHRQ x y)) => (BTQ y x)
+(BTLconst [c] (SHRLconst [d] x)) && (c+d)<32 => (BTLconst [c+d] x)
+(BTLconst [c] (SHLLconst [d] x)) && c>d => (BTLconst [c-d] x)
+(BTLconst [0] s:(SHRL x y)) => (BTL y x)
+
+// Rewrite a & 1 != 1 into a & 1 == 0.
+// Among other things, this lets us turn (a>>b)&1 != 1 into a bit test.
+(SET(NE|EQ) (CMPLconst [1] s:(ANDLconst [1] _))) => (SET(EQ|NE) (CMPLconst [0] s))
+(SET(NE|EQ)store [off] {sym} ptr (CMPLconst [1] s:(ANDLconst [1] _)) mem) => (SET(EQ|NE)store [off] {sym} ptr (CMPLconst [0] s) mem)
+(SET(NE|EQ) (CMPQconst [1] s:(ANDQconst [1] _))) => (SET(EQ|NE) (CMPQconst [0] s))
+(SET(NE|EQ)store [off] {sym} ptr (CMPQconst [1] s:(ANDQconst [1] _)) mem) => (SET(EQ|NE)store [off] {sym} ptr (CMPQconst [0] s) mem)
+
+// Recognize bit setting (a |= 1<<b) and toggling (a ^= 1<<b)
+(OR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) => (BTS(Q|L) x y)
+(XOR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) => (BTC(Q|L) x y)
+(ORLmodify [off] {sym} ptr s:(SHLL (MOVLconst [1]) <t> x) mem) =>
+ (BTSLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
+(ORQmodify [off] {sym} ptr s:(SHLQ (MOVQconst [1]) <t> x) mem) =>
+ (BTSQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
+(XORLmodify [off] {sym} ptr s:(SHLL (MOVLconst [1]) <t> x) mem) =>
+ (BTCLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
+(XORQmodify [off] {sym} ptr s:(SHLQ (MOVQconst [1]) <t> x) mem) =>
+ (BTCQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
+
+// Convert ORconst into BTS, if the code gets smaller, with boundary being
+// (ORL $40,AX is 3 bytes, ORL $80,AX is 6 bytes).
+((ORQ|XORQ)const [c] x) && isUint64PowerOfTwo(int64(c)) && uint64(c) >= 128
+ => (BT(S|C)Qconst [int8(log32(c))] x)
+((ORL|XORL)const [c] x) && isUint32PowerOfTwo(int64(c)) && uint64(c) >= 128
+ => (BT(S|C)Lconst [int8(log32(c))] x)
+((ORQ|XORQ) (MOVQconst [c]) x) && isUint64PowerOfTwo(c) && uint64(c) >= 128
+ => (BT(S|C)Qconst [int8(log64(c))] x)
+((ORL|XORL) (MOVLconst [c]) x) && isUint32PowerOfTwo(int64(c)) && uint64(c) >= 128
+ => (BT(S|C)Lconst [int8(log32(c))] x)
+
+// Recognize bit clearing: a &^= 1<<b
+(AND(Q|L) (NOT(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y)) x) => (BTR(Q|L) x y)
+(ANDQconst [c] x) && isUint64PowerOfTwo(int64(^c)) && uint64(^c) >= 128
+ => (BTRQconst [int8(log32(^c))] x)
+(ANDLconst [c] x) && isUint32PowerOfTwo(int64(^c)) && uint64(^c) >= 128
+ => (BTRLconst [int8(log32(^c))] x)
+(ANDQ (MOVQconst [c]) x) && isUint64PowerOfTwo(^c) && uint64(^c) >= 128
+ => (BTRQconst [int8(log64(^c))] x)
+(ANDL (MOVLconst [c]) x) && isUint32PowerOfTwo(int64(^c)) && uint64(^c) >= 128
+ => (BTRLconst [int8(log32(^c))] x)
+(ANDLmodify [off] {sym} ptr (NOTL s:(SHLL (MOVLconst [1]) <t> x)) mem) =>
+ (BTRLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
+(ANDQmodify [off] {sym} ptr (NOTQ s:(SHLQ (MOVQconst [1]) <t> x)) mem) =>
+ (BTRQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
+
+// Special-case bit patterns on first/last bit.
+// generic.rules changes ANDs of high-part/low-part masks into a couple of shifts,
+// for instance:
+// x & 0xFFFF0000 -> (x >> 16) << 16
+// x & 0x80000000 -> (x >> 31) << 31
+//
+// In case the mask is just one bit (like second example above), it conflicts
+// with the above rules to detect bit-testing / bit-clearing of first/last bit.
+// We thus special-case them, by detecting the shift patterns.
+
+// Special case resetting first/last bit
+(SHL(L|Q)const [1] (SHR(L|Q)const [1] x))
+ => (BTR(L|Q)const [0] x)
+(SHRLconst [1] (SHLLconst [1] x))
+ => (BTRLconst [31] x)
+(SHRQconst [1] (SHLQconst [1] x))
+ => (BTRQconst [63] x)
+
+// Special case testing first/last bit (with double-shift generated by generic.rules)
+((SETNE|SETEQ|NE|EQ) (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2)) && z1==z2
+ => ((SETB|SETAE|ULT|UGE) (BTQconst [63] x))
+((SETNE|SETEQ|NE|EQ) (TESTL z1:(SHLLconst [31] (SHRQconst [31] x)) z2)) && z1==z2
+ => ((SETB|SETAE|ULT|UGE) (BTQconst [31] x))
+(SET(NE|EQ)store [off] {sym} ptr (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2) mem) && z1==z2
+ => (SET(B|AE)store [off] {sym} ptr (BTQconst [63] x) mem)
+(SET(NE|EQ)store [off] {sym} ptr (TESTL z1:(SHLLconst [31] (SHRLconst [31] x)) z2) mem) && z1==z2
+ => (SET(B|AE)store [off] {sym} ptr (BTLconst [31] x) mem)
+
+((SETNE|SETEQ|NE|EQ) (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2)) && z1==z2
+ => ((SETB|SETAE|ULT|UGE) (BTQconst [0] x))
+((SETNE|SETEQ|NE|EQ) (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2)) && z1==z2
+ => ((SETB|SETAE|ULT|UGE) (BTLconst [0] x))
+(SET(NE|EQ)store [off] {sym} ptr (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2) mem) && z1==z2
+ => (SET(B|AE)store [off] {sym} ptr (BTQconst [0] x) mem)
+(SET(NE|EQ)store [off] {sym} ptr (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2) mem) && z1==z2
+ => (SET(B|AE)store [off] {sym} ptr (BTLconst [0] x) mem)
+
+// Special-case manually testing last bit with "a>>63 != 0" (without "&1")
+((SETNE|SETEQ|NE|EQ) (TESTQ z1:(SHRQconst [63] x) z2)) && z1==z2
+ => ((SETB|SETAE|ULT|UGE) (BTQconst [63] x))
+((SETNE|SETEQ|NE|EQ) (TESTL z1:(SHRLconst [31] x) z2)) && z1==z2
+ => ((SETB|SETAE|ULT|UGE) (BTLconst [31] x))
+(SET(NE|EQ)store [off] {sym} ptr (TESTQ z1:(SHRQconst [63] x) z2) mem) && z1==z2
+ => (SET(B|AE)store [off] {sym} ptr (BTQconst [63] x) mem)
+(SET(NE|EQ)store [off] {sym} ptr (TESTL z1:(SHRLconst [31] x) z2) mem) && z1==z2
+ => (SET(B|AE)store [off] {sym} ptr (BTLconst [31] x) mem)
+
+// Fold combinations of bit ops on same bit. An example is math.Copysign(c,-1)
+(BTS(Q|L)const [c] (BTR(Q|L)const [c] x)) => (BTS(Q|L)const [c] x)
+(BTS(Q|L)const [c] (BTC(Q|L)const [c] x)) => (BTS(Q|L)const [c] x)
+(BTR(Q|L)const [c] (BTS(Q|L)const [c] x)) => (BTR(Q|L)const [c] x)
+(BTR(Q|L)const [c] (BTC(Q|L)const [c] x)) => (BTR(Q|L)const [c] x)
+
+// Fold boolean negation into SETcc.
+(XORLconst [1] (SETNE x)) => (SETEQ x)
+(XORLconst [1] (SETEQ x)) => (SETNE x)
+(XORLconst [1] (SETL x)) => (SETGE x)
+(XORLconst [1] (SETGE x)) => (SETL x)
+(XORLconst [1] (SETLE x)) => (SETG x)
+(XORLconst [1] (SETG x)) => (SETLE x)
+(XORLconst [1] (SETB x)) => (SETAE x)
+(XORLconst [1] (SETAE x)) => (SETB x)
+(XORLconst [1] (SETBE x)) => (SETA x)
+(XORLconst [1] (SETA x)) => (SETBE x)
+
+// Special case for floating point - LF/LEF not generated
+(NE (TESTB (SETGF cmp) (SETGF cmp)) yes no) => (UGT cmp yes no)
+(NE (TESTB (SETGEF cmp) (SETGEF cmp)) yes no) => (UGE cmp yes no)
+(NE (TESTB (SETEQF cmp) (SETEQF cmp)) yes no) => (EQF cmp yes no)
+(NE (TESTB (SETNEF cmp) (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 <typ.Int8> x) (SETNAN <typ.Int8> x))
+// (SETEQF x) => (ANDQ (SETEQ <typ.Int8> x) (SETORD <typ.Int8> x))
+
+// fold constants into instructions
+(ADDQ x (MOVQconst [c])) && is32Bit(c) => (ADDQconst [int32(c)] x)
+(ADDQ x (MOVLconst [c])) => (ADDQconst [c] x)
+(ADDL x (MOVLconst [c])) => (ADDLconst [c] x)
+
+(SUBQ x (MOVQconst [c])) && is32Bit(c) => (SUBQconst x [int32(c)])
+(SUBQ (MOVQconst [c]) x) && is32Bit(c) => (NEGQ (SUBQconst <v.Type> x [int32(c)]))
+(SUBL x (MOVLconst [c])) => (SUBLconst x [c])
+(SUBL (MOVLconst [c]) x) => (NEGL (SUBLconst <v.Type> x [c]))
+
+(MULQ x (MOVQconst [c])) && is32Bit(c) => (MULQconst [int32(c)] x)
+(MULL x (MOVLconst [c])) => (MULLconst [c] x)
+
+(ANDQ x (MOVQconst [c])) && is32Bit(c) => (ANDQconst [int32(c)] x)
+(ANDL x (MOVLconst [c])) => (ANDLconst [c] x)
+
+(AND(L|Q)const [c] (AND(L|Q)const [d] x)) => (AND(L|Q)const [c & d] x)
+(XOR(L|Q)const [c] (XOR(L|Q)const [d] x)) => (XOR(L|Q)const [c ^ d] x)
+(OR(L|Q)const [c] (OR(L|Q)const [d] x)) => (OR(L|Q)const [c | d] x)
+
+(BTRLconst [c] (ANDLconst [d] x)) => (ANDLconst [d &^ (1<<uint32(c))] x)
+(ANDLconst [c] (BTRLconst [d] x)) => (ANDLconst [c &^ (1<<uint32(d))] x)
+(BTRLconst [c] (BTRLconst [d] x)) => (ANDLconst [^(1<<uint32(c) | 1<<uint32(d))] x)
+
+(BTCLconst [c] (XORLconst [d] x)) => (XORLconst [d ^ 1<<uint32(c)] x)
+(XORLconst [c] (BTCLconst [d] x)) => (XORLconst [c ^ 1<<uint32(d)] x)
+(BTCLconst [c] (BTCLconst [d] x)) => (XORLconst [1<<uint32(c) | 1<<uint32(d)] x)
+
+(BTSLconst [c] (ORLconst [d] x)) => (ORLconst [d | 1<<uint32(c)] x)
+(ORLconst [c] (BTSLconst [d] x)) => (ORLconst [c | 1<<uint32(d)] x)
+(BTSLconst [c] (BTSLconst [d] x)) => (ORLconst [1<<uint32(c) | 1<<uint32(d)] x)
+
+(BTRQconst [c] (ANDQconst [d] x)) && is32Bit(int64(d) &^ (1<<uint32(c))) => (ANDQconst [d &^ (1<<uint32(c))] x)
+(ANDQconst [c] (BTRQconst [d] x)) && is32Bit(int64(c) &^ (1<<uint32(d))) => (ANDQconst [c &^ (1<<uint32(d))] x)
+(BTRQconst [c] (BTRQconst [d] x)) && is32Bit(^(1<<uint32(c) | 1<<uint32(d))) => (ANDQconst [^(1<<uint32(c) | 1<<uint32(d))] x)
+
+(BTCQconst [c] (XORQconst [d] x)) && is32Bit(int64(d) ^ 1<<uint32(c)) => (XORQconst [d ^ 1<<uint32(c)] x)
+(XORQconst [c] (BTCQconst [d] x)) && is32Bit(int64(c) ^ 1<<uint32(d)) => (XORQconst [c ^ 1<<uint32(d)] x)
+(BTCQconst [c] (BTCQconst [d] x)) && is32Bit(1<<uint32(c) ^ 1<<uint32(d)) => (XORQconst [1<<uint32(c) ^ 1<<uint32(d)] x)
+
+(BTSQconst [c] (ORQconst [d] x)) && is32Bit(int64(d) | 1<<uint32(c)) => (ORQconst [d | 1<<uint32(c)] x)
+(ORQconst [c] (BTSQconst [d] x)) && is32Bit(int64(c) | 1<<uint32(d)) => (ORQconst [c | 1<<uint32(d)] x)
+(BTSQconst [c] (BTSQconst [d] x)) && is32Bit(1<<uint32(c) | 1<<uint32(d)) => (ORQconst [1<<uint32(c) | 1<<uint32(d)] x)
+
+
+(MULLconst [c] (MULLconst [d] x)) => (MULLconst [c * d] x)
+(MULQconst [c] (MULQconst [d] x)) && is32Bit(int64(c)*int64(d)) => (MULQconst [c * d] x)
+
+(ORQ x (MOVQconst [c])) && is32Bit(c) => (ORQconst [int32(c)] x)
+(ORQ x (MOVLconst [c])) => (ORQconst [c] x)
+(ORL x (MOVLconst [c])) => (ORLconst [c] x)
+
+(XORQ x (MOVQconst [c])) && is32Bit(c) => (XORQconst [int32(c)] x)
+(XORL x (MOVLconst [c])) => (XORLconst [c] x)
+
+(SHLQ x (MOV(Q|L)const [c])) => (SHLQconst [int8(c&63)] x)
+(SHLL x (MOV(Q|L)const [c])) => (SHLLconst [int8(c&31)] x)
+
+(SHRQ x (MOV(Q|L)const [c])) => (SHRQconst [int8(c&63)] x)
+(SHRL x (MOV(Q|L)const [c])) => (SHRLconst [int8(c&31)] x)
+(SHRW x (MOV(Q|L)const [c])) && c&31 < 16 => (SHRWconst [int8(c&31)] x)
+(SHRW _ (MOV(Q|L)const [c])) && c&31 >= 16 => (MOVLconst [0])
+(SHRB x (MOV(Q|L)const [c])) && c&31 < 8 => (SHRBconst [int8(c&31)] x)
+(SHRB _ (MOV(Q|L)const [c])) && c&31 >= 8 => (MOVLconst [0])
+
+(SARQ x (MOV(Q|L)const [c])) => (SARQconst [int8(c&63)] x)
+(SARL x (MOV(Q|L)const [c])) => (SARLconst [int8(c&31)] x)
+(SARW x (MOV(Q|L)const [c])) => (SARWconst [int8(min(int64(c)&31,15))] x)
+(SARB x (MOV(Q|L)const [c])) => (SARBconst [int8(min(int64(c)&31,7))] x)
+
+
+// Operations which don't affect the low 6/5 bits of the shift amount are NOPs.
+((SHLQ|SHRQ|SARQ) x (ADDQconst [c] y)) && c & 63 == 0 => ((SHLQ|SHRQ|SARQ) x y)
+((SHLQ|SHRQ|SARQ) x (NEGQ <t> (ADDQconst [c] y))) && c & 63 == 0 => ((SHLQ|SHRQ|SARQ) x (NEGQ <t> y))
+((SHLQ|SHRQ|SARQ) x (ANDQconst [c] y)) && c & 63 == 63 => ((SHLQ|SHRQ|SARQ) x y)
+((SHLQ|SHRQ|SARQ) x (NEGQ <t> (ANDQconst [c] y))) && c & 63 == 63 => ((SHLQ|SHRQ|SARQ) x (NEGQ <t> y))
+
+((SHLL|SHRL|SARL) x (ADDQconst [c] y)) && c & 31 == 0 => ((SHLL|SHRL|SARL) x y)
+((SHLL|SHRL|SARL) x (NEGQ <t> (ADDQconst [c] y))) && c & 31 == 0 => ((SHLL|SHRL|SARL) x (NEGQ <t> y))
+((SHLL|SHRL|SARL) x (ANDQconst [c] y)) && c & 31 == 31 => ((SHLL|SHRL|SARL) x y)
+((SHLL|SHRL|SARL) x (NEGQ <t> (ANDQconst [c] y))) && c & 31 == 31 => ((SHLL|SHRL|SARL) x (NEGQ <t> y))
+
+((SHLQ|SHRQ|SARQ) x (ADDLconst [c] y)) && c & 63 == 0 => ((SHLQ|SHRQ|SARQ) x y)
+((SHLQ|SHRQ|SARQ) x (NEGL <t> (ADDLconst [c] y))) && c & 63 == 0 => ((SHLQ|SHRQ|SARQ) x (NEGL <t> y))
+((SHLQ|SHRQ|SARQ) x (ANDLconst [c] y)) && c & 63 == 63 => ((SHLQ|SHRQ|SARQ) x y)
+((SHLQ|SHRQ|SARQ) x (NEGL <t> (ANDLconst [c] y))) && c & 63 == 63 => ((SHLQ|SHRQ|SARQ) x (NEGL <t> y))
+
+((SHLL|SHRL|SARL) x (ADDLconst [c] y)) && c & 31 == 0 => ((SHLL|SHRL|SARL) x y)
+((SHLL|SHRL|SARL) x (NEGL <t> (ADDLconst [c] y))) && c & 31 == 0 => ((SHLL|SHRL|SARL) x (NEGL <t> y))
+((SHLL|SHRL|SARL) x (ANDLconst [c] y)) && c & 31 == 31 => ((SHLL|SHRL|SARL) x y)
+((SHLL|SHRL|SARL) x (NEGL <t> (ANDLconst [c] y))) && c & 31 == 31 => ((SHLL|SHRL|SARL) x (NEGL <t> y))
+
+// Constant rotate instructions
+((ADDQ|ORQ|XORQ) (SHLQconst x [c]) (SHRQconst x [d])) && d==64-c => (ROLQconst x [c])
+((ADDL|ORL|XORL) (SHLLconst x [c]) (SHRLconst x [d])) && d==32-c => (ROLLconst x [c])
+
+((ADDL|ORL|XORL) <t> (SHLLconst x [c]) (SHRWconst x [d])) && d==16-c && c < 16 && t.Size() == 2 => (ROLWconst x [c])
+((ADDL|ORL|XORL) <t> (SHLLconst x [c]) (SHRBconst x [d])) && d==8-c && c < 8 && t.Size() == 1 => (ROLBconst x [c])
+
+(ROLQconst [c] (ROLQconst [d] x)) => (ROLQconst [(c+d)&63] x)
+(ROLLconst [c] (ROLLconst [d] x)) => (ROLLconst [(c+d)&31] x)
+(ROLWconst [c] (ROLWconst [d] x)) => (ROLWconst [(c+d)&15] x)
+(ROLBconst [c] (ROLBconst [d] x)) => (ROLBconst [(c+d)& 7] x)
+
+(RotateLeft8 ...) => (ROLB ...)
+(RotateLeft16 ...) => (ROLW ...)
+(RotateLeft32 ...) => (ROLL ...)
+(RotateLeft64 ...) => (ROLQ ...)
+
+// Non-constant rotates.
+// We want to issue a rotate when the Go source contains code like
+// y &= 63
+// x << y | x >> (64-y)
+// The shift rules above convert << to SHLx and >> to SHRx.
+// SHRx converts its shift argument from 64-y to -y.
+// A tricky situation occurs when y==0. Then the original code would be:
+// x << 0 | x >> 64
+// But x >> 64 is 0, not x. So there's an additional mask that is ANDed in
+// to force the second term to 0. We don't need that mask, but we must match
+// it in order to strip it out.
+(ORQ (SHLQ x y) (ANDQ (SHRQ x (NEG(Q|L) y)) (SBBQcarrymask (CMP(Q|L)const (NEG(Q|L) (ADD(Q|L)const (AND(Q|L)const y [63]) [-64])) [64])))) => (ROLQ x y)
+(ORQ (SHRQ x y) (ANDQ (SHLQ x (NEG(Q|L) y)) (SBBQcarrymask (CMP(Q|L)const (NEG(Q|L) (ADD(Q|L)const (AND(Q|L)const y [63]) [-64])) [64])))) => (RORQ x y)
+
+(ORL (SHLL x y) (ANDL (SHRL x (NEG(Q|L) y)) (SBBLcarrymask (CMP(Q|L)const (NEG(Q|L) (ADD(Q|L)const (AND(Q|L)const y [31]) [-32])) [32])))) => (ROLL x y)
+(ORL (SHRL x y) (ANDL (SHLL x (NEG(Q|L) y)) (SBBLcarrymask (CMP(Q|L)const (NEG(Q|L) (ADD(Q|L)const (AND(Q|L)const y [31]) [-32])) [32])))) => (RORL x y)
+
+// Help with rotate detection
+(CMPQconst (NEGQ (ADDQconst [-16] (ANDQconst [15] _))) [32]) => (FlagLT_ULT)
+(CMPQconst (NEGQ (ADDQconst [ -8] (ANDQconst [7] _))) [32]) => (FlagLT_ULT)
+
+(ORL (SHLL x (AND(Q|L)const y [15]))
+ (ANDL (SHRW x (NEG(Q|L) (ADD(Q|L)const (AND(Q|L)const y [15]) [-16])))
+ (SBBLcarrymask (CMP(Q|L)const (NEG(Q|L) (ADD(Q|L)const (AND(Q|L)const y [15]) [-16])) [16]))))
+ && v.Type.Size() == 2
+ => (ROLW x y)
+(ORL (SHRW x (AND(Q|L)const y [15]))
+ (SHLL x (NEG(Q|L) (ADD(Q|L)const (AND(Q|L)const y [15]) [-16]))))
+ && v.Type.Size() == 2
+ => (RORW x y)
+
+(ORL (SHLL x (AND(Q|L)const y [ 7]))
+ (ANDL (SHRB x (NEG(Q|L) (ADD(Q|L)const (AND(Q|L)const y [ 7]) [ -8])))
+ (SBBLcarrymask (CMP(Q|L)const (NEG(Q|L) (ADD(Q|L)const (AND(Q|L)const y [ 7]) [ -8])) [ 8]))))
+ && v.Type.Size() == 1
+ => (ROLB x y)
+(ORL (SHRB x (AND(Q|L)const y [ 7]))
+ (SHLL x (NEG(Q|L) (ADD(Q|L)const (AND(Q|L)const y [ 7]) [ -8]))))
+ && v.Type.Size() == 1
+ => (RORB x y)
+
+// rotate left negative = rotate right
+(ROLQ x (NEG(Q|L) y)) => (RORQ x y)
+(ROLL x (NEG(Q|L) y)) => (RORL x y)
+(ROLW x (NEG(Q|L) y)) => (RORW x y)
+(ROLB x (NEG(Q|L) y)) => (RORB x y)
+
+// rotate right negative = rotate left
+(RORQ x (NEG(Q|L) y)) => (ROLQ x y)
+(RORL x (NEG(Q|L) y)) => (ROLL x y)
+(RORW x (NEG(Q|L) y)) => (ROLW x y)
+(RORB x (NEG(Q|L) y)) => (ROLB x y)
+
+// rotate by constants
+(ROLQ x (MOV(Q|L)const [c])) => (ROLQconst [int8(c&63)] x)
+(ROLL x (MOV(Q|L)const [c])) => (ROLLconst [int8(c&31)] x)
+(ROLW x (MOV(Q|L)const [c])) => (ROLWconst [int8(c&15)] x)
+(ROLB x (MOV(Q|L)const [c])) => (ROLBconst [int8(c&7) ] x)
+
+(RORQ x (MOV(Q|L)const [c])) => (ROLQconst [int8((-c)&63)] x)
+(RORL x (MOV(Q|L)const [c])) => (ROLLconst [int8((-c)&31)] x)
+(RORW x (MOV(Q|L)const [c])) => (ROLWconst [int8((-c)&15)] x)
+(RORB x (MOV(Q|L)const [c])) => (ROLBconst [int8((-c)&7) ] x)
+
+// Constant shift simplifications
+((SHLQ|SHRQ|SARQ)const x [0]) => x
+((SHLL|SHRL|SARL)const x [0]) => x
+((SHRW|SARW)const x [0]) => x
+((SHRB|SARB)const x [0]) => x
+((ROLQ|ROLL|ROLW|ROLB)const x [0]) => 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.
+// (SHRW x (MOVLconst [24])), but just in case.
+
+(CMPQ x (MOVQconst [c])) && is32Bit(c) => (CMPQconst x [int32(c)])
+(CMPQ (MOVQconst [c]) x) && is32Bit(c) => (InvertFlags (CMPQconst x [int32(c)]))
+(CMPL x (MOVLconst [c])) => (CMPLconst x [c])
+(CMPL (MOVLconst [c]) x) => (InvertFlags (CMPLconst x [c]))
+(CMPW x (MOVLconst [c])) => (CMPWconst x [int16(c)])
+(CMPW (MOVLconst [c]) x) => (InvertFlags (CMPWconst x [int16(c)]))
+(CMPB x (MOVLconst [c])) => (CMPBconst x [int8(c)])
+(CMPB (MOVLconst [c]) x) => (InvertFlags (CMPBconst x [int8(c)]))
+
+// Canonicalize the order of arguments to comparisons - helps with CSE.
+(CMP(Q|L|W|B) x y) && x.ID > y.ID => (InvertFlags (CMP(Q|L|W|B) y x))
+
+// Using MOVZX instead of AND is cheaper.
+(AND(Q|L)const [ 0xFF] x) => (MOVBQZX x)
+(AND(Q|L)const [0xFFFF] x) => (MOVWQZX x)
+// This rule is currently invalid because 0xFFFFFFFF is not representable by a signed int32.
+// Commenting out for now, because it also can't trigger because of the is32bit guard on the
+// ANDQconst lowering-rule, above, prevents 0xFFFFFFFF from matching (for the same reason)
+// Using an alternate form of this rule segfaults some binaries because of
+// adverse interactions with other passes.
+// (ANDQconst [0xFFFFFFFF] x) => (MOVLQZX x)
+
+// strength reduction
+// Assumes that the following costs from https://gmplib.org/~tege/x86-timing.pdf:
+// 1 - addq, shlq, leaq, negq, subq
+// 3 - imulq
+// This limits the rewrites to two instructions.
+// Note that negq always operates in-place,
+// which can require a register-register move
+// to preserve the original value,
+// so it must be used with care.
+(MUL(Q|L)const [-9] x) => (NEG(Q|L) (LEA(Q|L)8 <v.Type> x x))
+(MUL(Q|L)const [-5] x) => (NEG(Q|L) (LEA(Q|L)4 <v.Type> x x))
+(MUL(Q|L)const [-3] x) => (NEG(Q|L) (LEA(Q|L)2 <v.Type> x x))
+(MUL(Q|L)const [-1] x) => (NEG(Q|L) x)
+(MUL(Q|L)const [ 0] _) => (MOV(Q|L)const [0])
+(MUL(Q|L)const [ 1] x) => x
+(MUL(Q|L)const [ 3] x) => (LEA(Q|L)2 x x)
+(MUL(Q|L)const [ 5] x) => (LEA(Q|L)4 x x)
+(MUL(Q|L)const [ 7] x) => (LEA(Q|L)2 x (LEA(Q|L)2 <v.Type> x x))
+(MUL(Q|L)const [ 9] x) => (LEA(Q|L)8 x x)
+(MUL(Q|L)const [11] x) => (LEA(Q|L)2 x (LEA(Q|L)4 <v.Type> x x))
+(MUL(Q|L)const [13] x) => (LEA(Q|L)4 x (LEA(Q|L)2 <v.Type> x x))
+(MUL(Q|L)const [19] x) => (LEA(Q|L)2 x (LEA(Q|L)8 <v.Type> x x))
+(MUL(Q|L)const [21] x) => (LEA(Q|L)4 x (LEA(Q|L)4 <v.Type> x x))
+(MUL(Q|L)const [25] x) => (LEA(Q|L)8 x (LEA(Q|L)2 <v.Type> x x))
+(MUL(Q|L)const [27] x) => (LEA(Q|L)8 (LEA(Q|L)2 <v.Type> x x) (LEA(Q|L)2 <v.Type> x x))
+(MUL(Q|L)const [37] x) => (LEA(Q|L)4 x (LEA(Q|L)8 <v.Type> x x))
+(MUL(Q|L)const [41] x) => (LEA(Q|L)8 x (LEA(Q|L)4 <v.Type> x x))
+(MUL(Q|L)const [45] x) => (LEA(Q|L)8 (LEA(Q|L)4 <v.Type> x x) (LEA(Q|L)4 <v.Type> x x))
+(MUL(Q|L)const [73] x) => (LEA(Q|L)8 x (LEA(Q|L)8 <v.Type> x x))
+(MUL(Q|L)const [81] x) => (LEA(Q|L)8 (LEA(Q|L)8 <v.Type> x x) (LEA(Q|L)8 <v.Type> x x))
+
+(MUL(Q|L)const [c] x) && isPowerOfTwo64(int64(c)+1) && c >= 15 => (SUB(Q|L) (SHL(Q|L)const <v.Type> [int8(log64(int64(c)+1))] x) x)
+(MUL(Q|L)const [c] x) && isPowerOfTwo32(c-1) && c >= 17 => (LEA(Q|L)1 (SHL(Q|L)const <v.Type> [int8(log32(c-1))] x) x)
+(MUL(Q|L)const [c] x) && isPowerOfTwo32(c-2) && c >= 34 => (LEA(Q|L)2 (SHL(Q|L)const <v.Type> [int8(log32(c-2))] x) x)
+(MUL(Q|L)const [c] x) && isPowerOfTwo32(c-4) && c >= 68 => (LEA(Q|L)4 (SHL(Q|L)const <v.Type> [int8(log32(c-4))] x) x)
+(MUL(Q|L)const [c] x) && isPowerOfTwo32(c-8) && c >= 136 => (LEA(Q|L)8 (SHL(Q|L)const <v.Type> [int8(log32(c-8))] x) x)
+(MUL(Q|L)const [c] x) && c%3 == 0 && isPowerOfTwo32(c/3) => (SHL(Q|L)const [int8(log32(c/3))] (LEA(Q|L)2 <v.Type> x x))
+(MUL(Q|L)const [c] x) && c%5 == 0 && isPowerOfTwo32(c/5) => (SHL(Q|L)const [int8(log32(c/5))] (LEA(Q|L)4 <v.Type> x x))
+(MUL(Q|L)const [c] x) && c%9 == 0 && isPowerOfTwo32(c/9) => (SHL(Q|L)const [int8(log32(c/9))] (LEA(Q|L)8 <v.Type> x x))
+
+// combine add/shift into LEAQ/LEAL
+(ADD(L|Q) x (SHL(L|Q)const [3] y)) => (LEA(L|Q)8 x y)
+(ADD(L|Q) x (SHL(L|Q)const [2] y)) => (LEA(L|Q)4 x y)
+(ADD(L|Q) x (SHL(L|Q)const [1] y)) => (LEA(L|Q)2 x y)
+(ADD(L|Q) x (ADD(L|Q) y y)) => (LEA(L|Q)2 x y)
+(ADD(L|Q) x (ADD(L|Q) x y)) => (LEA(L|Q)2 y x)
+
+// combine ADDQ/ADDQconst into LEAQ1/LEAL1
+(ADD(Q|L)const [c] (ADD(Q|L) x y)) => (LEA(Q|L)1 [c] x y)
+(ADD(Q|L) (ADD(Q|L)const [c] x) y) => (LEA(Q|L)1 [c] x y)
+(ADD(Q|L)const [c] (SHL(Q|L)const [1] x)) => (LEA(Q|L)1 [c] x x)
+
+// fold ADDQ/ADDL into LEAQ/LEAL
+(ADD(Q|L)const [c] (LEA(Q|L) [d] {s} x)) && is32Bit(int64(c)+int64(d)) => (LEA(Q|L) [c+d] {s} x)
+(LEA(Q|L) [c] {s} (ADD(Q|L)const [d] x)) && is32Bit(int64(c)+int64(d)) => (LEA(Q|L) [c+d] {s} x)
+(LEA(Q|L) [c] {s} (ADD(Q|L) x y)) && x.Op != OpSB && y.Op != OpSB => (LEA(Q|L)1 [c] {s} x y)
+(ADD(Q|L) x (LEA(Q|L) [c] {s} y)) && x.Op != OpSB && y.Op != OpSB => (LEA(Q|L)1 [c] {s} x y)
+
+// fold ADDQconst/ADDLconst into LEAQx/LEALx
+(ADD(Q|L)const [c] (LEA(Q|L)1 [d] {s} x y)) && is32Bit(int64(c)+int64(d)) => (LEA(Q|L)1 [c+d] {s} x y)
+(ADD(Q|L)const [c] (LEA(Q|L)2 [d] {s} x y)) && is32Bit(int64(c)+int64(d)) => (LEA(Q|L)2 [c+d] {s} x y)
+(ADD(Q|L)const [c] (LEA(Q|L)4 [d] {s} x y)) && is32Bit(int64(c)+int64(d)) => (LEA(Q|L)4 [c+d] {s} x y)
+(ADD(Q|L)const [c] (LEA(Q|L)8 [d] {s} x y)) && is32Bit(int64(c)+int64(d)) => (LEA(Q|L)8 [c+d] {s} x y)
+(LEA(Q|L)1 [c] {s} (ADD(Q|L)const [d] x) y) && is32Bit(int64(c)+int64(d)) && x.Op != OpSB => (LEA(Q|L)1 [c+d] {s} x y)
+(LEA(Q|L)2 [c] {s} (ADD(Q|L)const [d] x) y) && is32Bit(int64(c)+int64(d)) && x.Op != OpSB => (LEA(Q|L)2 [c+d] {s} x y)
+(LEA(Q|L)2 [c] {s} x (ADD(Q|L)const [d] y)) && is32Bit(int64(c)+2*int64(d)) && y.Op != OpSB => (LEA(Q|L)2 [c+2*d] {s} x y)
+(LEA(Q|L)4 [c] {s} (ADD(Q|L)const [d] x) y) && is32Bit(int64(c)+int64(d)) && x.Op != OpSB => (LEA(Q|L)4 [c+d] {s} x y)
+(LEA(Q|L)4 [c] {s} x (ADD(Q|L)const [d] y)) && is32Bit(int64(c)+4*int64(d)) && y.Op != OpSB => (LEA(Q|L)4 [c+4*d] {s} x y)
+(LEA(Q|L)8 [c] {s} (ADD(Q|L)const [d] x) y) && is32Bit(int64(c)+int64(d)) && x.Op != OpSB => (LEA(Q|L)8 [c+d] {s} x y)
+(LEA(Q|L)8 [c] {s} x (ADD(Q|L)const [d] y)) && is32Bit(int64(c)+8*int64(d)) && y.Op != OpSB => (LEA(Q|L)8 [c+8*d] {s} x y)
+
+// fold shifts into LEAQx/LEALx
+(LEA(Q|L)1 [c] {s} x (SHL(Q|L)const [1] y)) => (LEA(Q|L)2 [c] {s} x y)
+(LEA(Q|L)1 [c] {s} x (SHL(Q|L)const [2] y)) => (LEA(Q|L)4 [c] {s} x y)
+(LEA(Q|L)1 [c] {s} x (SHL(Q|L)const [3] y)) => (LEA(Q|L)8 [c] {s} x y)
+(LEA(Q|L)2 [c] {s} x (SHL(Q|L)const [1] y)) => (LEA(Q|L)4 [c] {s} x y)
+(LEA(Q|L)2 [c] {s} x (SHL(Q|L)const [2] y)) => (LEA(Q|L)8 [c] {s} x y)
+(LEA(Q|L)4 [c] {s} x (SHL(Q|L)const [1] y)) => (LEA(Q|L)8 [c] {s} 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)
+
+(SETLstore [off] {sym} ptr (InvertFlags x) mem) => (SETGstore [off] {sym} ptr x mem)
+(SETGstore [off] {sym} ptr (InvertFlags x) mem) => (SETLstore [off] {sym} ptr x mem)
+(SETBstore [off] {sym} ptr (InvertFlags x) mem) => (SETAstore [off] {sym} ptr x mem)
+(SETAstore [off] {sym} ptr (InvertFlags x) mem) => (SETBstore [off] {sym} ptr x mem)
+(SETLEstore [off] {sym} ptr (InvertFlags x) mem) => (SETGEstore [off] {sym} ptr x mem)
+(SETGEstore [off] {sym} ptr (InvertFlags x) mem) => (SETLEstore [off] {sym} ptr x mem)
+(SETBEstore [off] {sym} ptr (InvertFlags x) mem) => (SETAEstore [off] {sym} ptr x mem)
+(SETAEstore [off] {sym} ptr (InvertFlags x) mem) => (SETBEstore [off] {sym} ptr x mem)
+(SETEQstore [off] {sym} ptr (InvertFlags x) mem) => (SETEQstore [off] {sym} ptr x mem)
+(SETNEstore [off] {sym} ptr (InvertFlags x) mem) => (SETNEstore [off] {sym} ptr x mem)
+
+// 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.
+// Make sure we don't combine these ops if the load has another use.
+// This prevents a single load from being split into multiple loads
+// which then might return different values. See test/atomicload.go.
+(MOVBQSX x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
+(MOVBQSX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
+(MOVBQSX x:(MOVLload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
+(MOVBQSX x:(MOVQload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
+(MOVBQZX x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+(MOVBQZX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+(MOVBQZX x:(MOVLload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+(MOVBQZX x:(MOVQload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+(MOVWQSX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWQSXload <v.Type> [off] {sym} ptr mem)
+(MOVWQSX x:(MOVLload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWQSXload <v.Type> [off] {sym} ptr mem)
+(MOVWQSX x:(MOVQload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWQSXload <v.Type> [off] {sym} ptr mem)
+(MOVWQZX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWload <v.Type> [off] {sym} ptr mem)
+(MOVWQZX x:(MOVLload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWload <v.Type> [off] {sym} ptr mem)
+(MOVWQZX x:(MOVQload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWload <v.Type> [off] {sym} ptr mem)
+(MOVLQSX x:(MOVLload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVLQSXload <v.Type> [off] {sym} ptr mem)
+(MOVLQSX x:(MOVQload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVLQSXload <v.Type> [off] {sym} ptr mem)
+(MOVLQZX x:(MOVLload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVLload <v.Type> [off] {sym} ptr mem)
+(MOVLQZX x:(MOVQload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVLload <v.Type> [off] {sym} ptr mem)
+
+(MOVLQZX x) && zeroUpper32Bits(x,3) => x
+(MOVWQZX x) && zeroUpper48Bits(x,3) => x
+(MOVBQZX x) && zeroUpper56Bits(x,3) => x
+
+// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
+(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVBQZX x)
+(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVWQZX x)
+(MOVLload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVLQZX x)
+(MOVQload [off] {sym} ptr (MOVQstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => x
+(MOVBQSXload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVBQSX x)
+(MOVWQSXload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVWQSX x)
+(MOVLQSXload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVLQSX x)
+
+// Fold extensions and ANDs together.
+(MOVBQZX (ANDLconst [c] x)) => (ANDLconst [c & 0xff] x)
+(MOVWQZX (ANDLconst [c] x)) => (ANDLconst [c & 0xffff] x)
+(MOVLQZX (ANDLconst [c] x)) => (ANDLconst [c] x)
+(MOVBQSX (ANDLconst [c] x)) && c & 0x80 == 0 => (ANDLconst [c & 0x7f] x)
+(MOVWQSX (ANDLconst [c] x)) && c & 0x8000 == 0 => (ANDLconst [c & 0x7fff] x)
+(MOVLQSX (ANDLconst [c] x)) && uint32(c) & 0x80000000 == 0 => (ANDLconst [c & 0x7fffffff] x)
+
+// 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!
+(MOV(Q|L|W|B|SS|SD|O)load [off1] {sym} (ADDQconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOV(Q|L|W|B|SS|SD|O)load [off1+off2] {sym} ptr mem)
+(MOV(Q|L|W|B|SS|SD|O)store [off1] {sym} (ADDQconst [off2] ptr) val mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOV(Q|L|W|B|SS|SD|O)store [off1+off2] {sym} ptr val mem)
+(SET(L|G|B|A|LE|GE|BE|AE|EQ|NE)store [off1] {sym} (ADDQconst [off2] base) val mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (SET(L|G|B|A|LE|GE|BE|AE|EQ|NE)store [off1+off2] {sym} base val mem)
+((ADD|SUB|AND|OR|XOR)Qload [off1] {sym} val (ADDQconst [off2] base) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ ((ADD|SUB|AND|OR|XOR)Qload [off1+off2] {sym} val base mem)
+((ADD|SUB|AND|OR|XOR)Lload [off1] {sym} val (ADDQconst [off2] base) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ ((ADD|SUB|AND|OR|XOR)Lload [off1+off2] {sym} val base mem)
+(CMP(Q|L|W|B)load [off1] {sym} (ADDQconst [off2] base) val mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (CMP(Q|L|W|B)load [off1+off2] {sym} base val mem)
+(CMP(Q|L|W|B)constload [valoff1] {sym} (ADDQconst [off2] base) mem) && ValAndOff(valoff1).canAdd32(off2) =>
+ (CMP(Q|L|W|B)constload [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+
+((ADD|SUB|MUL|DIV)SSload [off1] {sym} val (ADDQconst [off2] base) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ ((ADD|SUB|MUL|DIV)SSload [off1+off2] {sym} val base mem)
+((ADD|SUB|MUL|DIV)SDload [off1] {sym} val (ADDQconst [off2] base) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ ((ADD|SUB|MUL|DIV)SDload [off1+off2] {sym} val base mem)
+((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem) && ValAndOff(valoff1).canAdd32(off2) =>
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem) && ValAndOff(valoff1).canAdd32(off2) =>
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off1] {sym} (ADDQconst [off2] base) val mem) && is32Bit(int64(off1)+int64(off2)) =>
+ ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off1+off2] {sym} base val mem)
+((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off1] {sym} (ADDQconst [off2] base) val mem) && is32Bit(int64(off1)+int64(off2)) =>
+ ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off1+off2] {sym} base val mem)
+
+// Fold constants into stores.
+(MOVQstore [off] {sym} ptr (MOVQconst [c]) mem) && validVal(c) =>
+ (MOVQstoreconst [makeValAndOff32(int32(c),off)] {sym} ptr mem)
+(MOVLstore [off] {sym} ptr (MOV(L|Q)const [c]) mem) =>
+ (MOVLstoreconst [makeValAndOff32(int32(c),off)] {sym} ptr mem)
+(MOVWstore [off] {sym} ptr (MOV(L|Q)const [c]) mem) =>
+ (MOVWstoreconst [makeValAndOff32(int32(int16(c)),off)] {sym} ptr mem)
+(MOVBstore [off] {sym} ptr (MOV(L|Q)const [c]) mem) =>
+ (MOVBstoreconst [makeValAndOff32(int32(int8(c)),off)] {sym} ptr mem)
+
+// Fold address offsets into constant stores.
+(MOV(Q|L|W|B)storeconst [sc] {s} (ADDQconst [off] ptr) mem) && ValAndOff(sc).canAdd32(off) =>
+ (MOV(Q|L|W|B)storeconst [ValAndOff(sc).addOffset32(off)] {s} ptr 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.
+(MOV(Q|L|W|B|SS|SD|O|BQSX|WQSX|LQSX)load [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOV(Q|L|W|B|SS|SD|O|BQSX|WQSX|LQSX)load [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOV(Q|L|W|B|SS|SD|O)store [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOV(Q|L|W|B|SS|SD|O)store [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOV(Q|L|W|B)storeconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off) =>
+ (MOV(Q|L|W|B)storeconst [ValAndOff(sc).addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+(SET(L|G|B|A|LE|GE|BE|AE|EQ|NE)store [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (SET(L|G|B|A|LE|GE|BE|AE|EQ|NE)store [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+((ADD|SUB|AND|OR|XOR)Qload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ ((ADD|SUB|AND|OR|XOR)Qload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+((ADD|SUB|AND|OR|XOR)Lload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ ((ADD|SUB|AND|OR|XOR)Lload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+(CMP(Q|L|W|B)load [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (CMP(Q|L|W|B)load [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(CMP(Q|L|W|B)constload [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ && ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2) =>
+ (CMP(Q|L|W|B)constload [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+
+((ADD|SUB|MUL|DIV)SSload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ ((ADD|SUB|MUL|DIV)SSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+((ADD|SUB|MUL|DIV)SDload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ ((ADD|SUB|MUL|DIV)SDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ && ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2) =>
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ && ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2) =>
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+
+// fold LEAQs together
+(LEAQ [off1] {sym1} (LEAQ [off2] {sym2} x)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAQ [off1+off2] {mergeSym(sym1,sym2)} x)
+
+// LEAQ into LEAQ1
+(LEAQ1 [off1] {sym1} (LEAQ [off2] {sym2} x) y) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB =>
+ (LEAQ1 [off1+off2] {mergeSym(sym1,sym2)} x y)
+
+// LEAQ1 into LEAQ
+(LEAQ [off1] {sym1} (LEAQ1 [off2] {sym2} x y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAQ1 [off1+off2] {mergeSym(sym1,sym2)} x y)
+
+// LEAQ into LEAQ[248]
+(LEAQ2 [off1] {sym1} (LEAQ [off2] {sym2} x) y) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB =>
+ (LEAQ2 [off1+off2] {mergeSym(sym1,sym2)} x y)
+(LEAQ4 [off1] {sym1} (LEAQ [off2] {sym2} x) y) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB =>
+ (LEAQ4 [off1+off2] {mergeSym(sym1,sym2)} x y)
+(LEAQ8 [off1] {sym1} (LEAQ [off2] {sym2} x) y) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB =>
+ (LEAQ8 [off1+off2] {mergeSym(sym1,sym2)} x y)
+
+// LEAQ[248] into LEAQ
+(LEAQ [off1] {sym1} (LEAQ2 [off2] {sym2} x y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAQ2 [off1+off2] {mergeSym(sym1,sym2)} x y)
+(LEAQ [off1] {sym1} (LEAQ4 [off2] {sym2} x y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAQ4 [off1+off2] {mergeSym(sym1,sym2)} x y)
+(LEAQ [off1] {sym1} (LEAQ8 [off2] {sym2} x y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAQ8 [off1+off2] {mergeSym(sym1,sym2)} x y)
+
+// LEAQ[1248] into LEAQ[1248]. Only some such merges are possible.
+(LEAQ1 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAQ2 [off1+off2] {mergeSym(sym1, sym2)} x y)
+(LEAQ1 [off1] {sym1} x (LEAQ1 [off2] {sym2} x y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (LEAQ2 [off1+off2] {mergeSym(sym1, sym2)} y x)
+(LEAQ2 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y)) && is32Bit(int64(off1)+2*int64(off2)) && sym2 == nil =>
+ (LEAQ4 [off1+2*off2] {sym1} x y)
+(LEAQ4 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y)) && is32Bit(int64(off1)+4*int64(off2)) && sym2 == nil =>
+ (LEAQ8 [off1+4*off2] {sym1} x y)
+// TODO: more?
+
+// Lower LEAQ2/4/8 when the offset is a constant
+(LEAQ2 [off] {sym} x (MOV(Q|L)const [scale])) && is32Bit(int64(off)+int64(scale)*2) =>
+ (LEAQ [off+int32(scale)*2] {sym} x)
+(LEAQ4 [off] {sym} x (MOV(Q|L)const [scale])) && is32Bit(int64(off)+int64(scale)*4) =>
+ (LEAQ [off+int32(scale)*4] {sym} x)
+(LEAQ8 [off] {sym} x (MOV(Q|L)const [scale])) && is32Bit(int64(off)+int64(scale)*8) =>
+ (LEAQ [off+int32(scale)*8] {sym} x)
+
+// 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)
+
+// Constant comparisons.
+(CMPQconst (MOVQconst [x]) [y]) && x==int64(y) => (FlagEQ)
+(CMPQconst (MOVQconst [x]) [y]) && x<int64(y) && uint64(x)<uint64(int64(y)) => (FlagLT_ULT)
+(CMPQconst (MOVQconst [x]) [y]) && x<int64(y) && uint64(x)>uint64(int64(y)) => (FlagLT_UGT)
+(CMPQconst (MOVQconst [x]) [y]) && x>int64(y) && uint64(x)<uint64(int64(y)) => (FlagGT_ULT)
+(CMPQconst (MOVQconst [x]) [y]) && x>int64(y) && uint64(x)>uint64(int64(y)) => (FlagGT_UGT)
+(CMPLconst (MOVLconst [x]) [y]) && x==y => (FlagEQ)
+(CMPLconst (MOVLconst [x]) [y]) && x<y && uint32(x)<uint32(y) => (FlagLT_ULT)
+(CMPLconst (MOVLconst [x]) [y]) && x<y && uint32(x)>uint32(y) => (FlagLT_UGT)
+(CMPLconst (MOVLconst [x]) [y]) && x>y && uint32(x)<uint32(y) => (FlagGT_ULT)
+(CMPLconst (MOVLconst [x]) [y]) && x>y && uint32(x)>uint32(y) => (FlagGT_UGT)
+(CMPWconst (MOVLconst [x]) [y]) && int16(x)==y => (FlagEQ)
+(CMPWconst (MOVLconst [x]) [y]) && int16(x)<y && uint16(x)<uint16(y) => (FlagLT_ULT)
+(CMPWconst (MOVLconst [x]) [y]) && int16(x)<y && uint16(x)>uint16(y) => (FlagLT_UGT)
+(CMPWconst (MOVLconst [x]) [y]) && int16(x)>y && uint16(x)<uint16(y) => (FlagGT_ULT)
+(CMPWconst (MOVLconst [x]) [y]) && int16(x)>y && uint16(x)>uint16(y) => (FlagGT_UGT)
+(CMPBconst (MOVLconst [x]) [y]) && int8(x)==y => (FlagEQ)
+(CMPBconst (MOVLconst [x]) [y]) && int8(x)<y && uint8(x)<uint8(y) => (FlagLT_ULT)
+(CMPBconst (MOVLconst [x]) [y]) && int8(x)<y && uint8(x)>uint8(y) => (FlagLT_UGT)
+(CMPBconst (MOVLconst [x]) [y]) && int8(x)>y && uint8(x)<uint8(y) => (FlagGT_ULT)
+(CMPBconst (MOVLconst [x]) [y]) && int8(x)>y && uint8(x)>uint8(y) => (FlagGT_UGT)
+
+// CMPQconst requires a 32 bit const, but we can still constant-fold 64 bit consts.
+// In theory this applies to any of the simplifications above,
+// but CMPQ is the only one I've actually seen occur.
+(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x==y => (FlagEQ)
+(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x<y && uint64(x)<uint64(y) => (FlagLT_ULT)
+(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x<y && uint64(x)>uint64(y) => (FlagLT_UGT)
+(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x>y && uint64(x)<uint64(y) => (FlagGT_ULT)
+(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x>y && uint64(x)>uint64(y) => (FlagGT_UGT)
+
+// Other known comparisons.
+(CMPQconst (MOVBQZX _) [c]) && 0xFF < c => (FlagLT_ULT)
+(CMPQconst (MOVWQZX _) [c]) && 0xFFFF < c => (FlagLT_ULT)
+(CMPLconst (SHRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 32 && (1<<uint64(32-c)) <= uint64(n) => (FlagLT_ULT)
+(CMPQconst (SHRQconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 64 && (1<<uint64(64-c)) <= uint64(n) => (FlagLT_ULT)
+(CMPQconst (ANDQconst _ [m]) [n]) && 0 <= m && m < n => (FlagLT_ULT)
+(CMPQconst (ANDLconst _ [m]) [n]) && 0 <= m && m < n => (FlagLT_ULT)
+(CMPLconst (ANDLconst _ [m]) [n]) && 0 <= m && m < n => (FlagLT_ULT)
+(CMPWconst (ANDLconst _ [m]) [n]) && 0 <= int16(m) && int16(m) < n => (FlagLT_ULT)
+(CMPBconst (ANDLconst _ [m]) [n]) && 0 <= int8(m) && int8(m) < n => (FlagLT_ULT)
+
+// TESTQ c c sets flags like CMPQ c 0.
+(TESTQconst [c] (MOVQconst [d])) && int64(c) == d && c == 0 => (FlagEQ)
+(TESTLconst [c] (MOVLconst [c])) && c == 0 => (FlagEQ)
+(TESTQconst [c] (MOVQconst [d])) && int64(c) == d && c < 0 => (FlagLT_UGT)
+(TESTLconst [c] (MOVLconst [c])) && c < 0 => (FlagLT_UGT)
+(TESTQconst [c] (MOVQconst [d])) && int64(c) == d && c > 0 => (FlagGT_UGT)
+(TESTLconst [c] (MOVLconst [c])) && c > 0 => (FlagGT_UGT)
+
+// TODO: DIVxU also.
+
+// Absorb flag constants into SBB ops.
+(SBBQcarrymask (FlagEQ)) => (MOVQconst [0])
+(SBBQcarrymask (FlagLT_ULT)) => (MOVQconst [-1])
+(SBBQcarrymask (FlagLT_UGT)) => (MOVQconst [0])
+(SBBQcarrymask (FlagGT_ULT)) => (MOVQconst [-1])
+(SBBQcarrymask (FlagGT_UGT)) => (MOVQconst [0])
+(SBBLcarrymask (FlagEQ)) => (MOVLconst [0])
+(SBBLcarrymask (FlagLT_ULT)) => (MOVLconst [-1])
+(SBBLcarrymask (FlagLT_UGT)) => (MOVLconst [0])
+(SBBLcarrymask (FlagGT_ULT)) => (MOVLconst [-1])
+(SBBLcarrymask (FlagGT_UGT)) => (MOVLconst [0])
+
+// Absorb flag constants into branches.
+((EQ|LE|GE|ULE|UGE) (FlagEQ) yes no) => (First yes no)
+((NE|LT|GT|ULT|UGT) (FlagEQ) yes no) => (First no yes)
+((NE|LT|LE|ULT|ULE) (FlagLT_ULT) yes no) => (First yes no)
+((EQ|GT|GE|UGT|UGE) (FlagLT_ULT) yes no) => (First no yes)
+((NE|LT|LE|UGT|UGE) (FlagLT_UGT) yes no) => (First yes no)
+((EQ|GT|GE|ULT|ULE) (FlagLT_UGT) yes no) => (First no yes)
+((NE|GT|GE|ULT|ULE) (FlagGT_ULT) yes no) => (First yes no)
+((EQ|LT|LE|UGT|UGE) (FlagGT_ULT) yes no) => (First no yes)
+((NE|GT|GE|UGT|UGE) (FlagGT_UGT) yes no) => (First yes no)
+((EQ|LT|LE|ULT|ULE) (FlagGT_UGT) yes no) => (First no yes)
+
+// Absorb flag constants into SETxx ops.
+((SETEQ|SETLE|SETGE|SETBE|SETAE) (FlagEQ)) => (MOVLconst [1])
+((SETNE|SETL|SETG|SETB|SETA) (FlagEQ)) => (MOVLconst [0])
+((SETNE|SETL|SETLE|SETB|SETBE) (FlagLT_ULT)) => (MOVLconst [1])
+((SETEQ|SETG|SETGE|SETA|SETAE) (FlagLT_ULT)) => (MOVLconst [0])
+((SETNE|SETL|SETLE|SETA|SETAE) (FlagLT_UGT)) => (MOVLconst [1])
+((SETEQ|SETG|SETGE|SETB|SETBE) (FlagLT_UGT)) => (MOVLconst [0])
+((SETNE|SETG|SETGE|SETB|SETBE) (FlagGT_ULT)) => (MOVLconst [1])
+((SETEQ|SETL|SETLE|SETA|SETAE) (FlagGT_ULT)) => (MOVLconst [0])
+((SETNE|SETG|SETGE|SETA|SETAE) (FlagGT_UGT)) => (MOVLconst [1])
+((SETEQ|SETL|SETLE|SETB|SETBE) (FlagGT_UGT)) => (MOVLconst [0])
+
+(SETEQstore [off] {sym} ptr (FlagEQ) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETEQstore [off] {sym} ptr (FlagLT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETEQstore [off] {sym} ptr (FlagLT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETEQstore [off] {sym} ptr (FlagGT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETEQstore [off] {sym} ptr (FlagGT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+
+(SETNEstore [off] {sym} ptr (FlagEQ) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETNEstore [off] {sym} ptr (FlagLT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETNEstore [off] {sym} ptr (FlagLT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETNEstore [off] {sym} ptr (FlagGT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETNEstore [off] {sym} ptr (FlagGT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+
+(SETLstore [off] {sym} ptr (FlagEQ) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETLstore [off] {sym} ptr (FlagLT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETLstore [off] {sym} ptr (FlagLT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETLstore [off] {sym} ptr (FlagGT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETLstore [off] {sym} ptr (FlagGT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+
+(SETLEstore [off] {sym} ptr (FlagEQ) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETLEstore [off] {sym} ptr (FlagLT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETLEstore [off] {sym} ptr (FlagLT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETLEstore [off] {sym} ptr (FlagGT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETLEstore [off] {sym} ptr (FlagGT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+
+(SETGstore [off] {sym} ptr (FlagEQ) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETGstore [off] {sym} ptr (FlagLT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETGstore [off] {sym} ptr (FlagLT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETGstore [off] {sym} ptr (FlagGT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETGstore [off] {sym} ptr (FlagGT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+
+(SETGEstore [off] {sym} ptr (FlagEQ) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETGEstore [off] {sym} ptr (FlagLT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETGEstore [off] {sym} ptr (FlagLT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETGEstore [off] {sym} ptr (FlagGT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETGEstore [off] {sym} ptr (FlagGT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+
+(SETBstore [off] {sym} ptr (FlagEQ) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETBstore [off] {sym} ptr (FlagLT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETBstore [off] {sym} ptr (FlagLT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETBstore [off] {sym} ptr (FlagGT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETBstore [off] {sym} ptr (FlagGT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+
+(SETBEstore [off] {sym} ptr (FlagEQ) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETBEstore [off] {sym} ptr (FlagLT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETBEstore [off] {sym} ptr (FlagLT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETBEstore [off] {sym} ptr (FlagGT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETBEstore [off] {sym} ptr (FlagGT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+
+(SETAstore [off] {sym} ptr (FlagEQ) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETAstore [off] {sym} ptr (FlagLT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETAstore [off] {sym} ptr (FlagLT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETAstore [off] {sym} ptr (FlagGT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETAstore [off] {sym} ptr (FlagGT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+
+(SETAEstore [off] {sym} ptr (FlagEQ) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETAEstore [off] {sym} ptr (FlagLT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETAEstore [off] {sym} ptr (FlagLT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+(SETAEstore [off] {sym} ptr (FlagGT_ULT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+(SETAEstore [off] {sym} ptr (FlagGT_UGT) mem) => (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+
+// Remove redundant *const ops
+(ADDQconst [0] x) => x
+(ADDLconst [c] x) && c==0 => x
+(SUBQconst [0] x) => x
+(SUBLconst [c] x) && c==0 => x
+(ANDQconst [0] _) => (MOVQconst [0])
+(ANDLconst [c] _) && c==0 => (MOVLconst [0])
+(ANDQconst [-1] x) => x
+(ANDLconst [c] x) && c==-1 => x
+(ORQconst [0] x) => x
+(ORLconst [c] x) && c==0 => x
+(ORQconst [-1] _) => (MOVQconst [-1])
+(ORLconst [c] _) && c==-1 => (MOVLconst [-1])
+(XORQconst [0] x) => x
+(XORLconst [c] x) && c==0 => x
+// TODO: since we got rid of the W/B versions, we might miss
+// things like (ANDLconst [0x100] x) which were formerly
+// (ANDBconst [0] x). Probably doesn't happen very often.
+// If we cared, we might do:
+// (ANDLconst <t> [c] x) && t.Size()==1 && int8(x)==0 -> (MOVLconst [0])
+
+// Remove redundant ops
+// Not in generic rules, because they may appear after lowering e. g. Slicemask
+(NEG(Q|L) (NEG(Q|L) x)) => x
+(NEG(Q|L) s:(SUB(Q|L) x y)) && s.Uses == 1 => (SUB(Q|L) y x)
+
+// Convert constant subtracts to constant adds
+(SUBQconst [c] x) && c != -(1<<31) => (ADDQconst [-c] x)
+(SUBLconst [c] x) => (ADDLconst [-c] x)
+
+// generic constant folding
+// TODO: more of this
+(ADDQconst [c] (MOVQconst [d])) => (MOVQconst [int64(c)+d])
+(ADDLconst [c] (MOVLconst [d])) => (MOVLconst [c+d])
+(ADDQconst [c] (ADDQconst [d] x)) && is32Bit(int64(c)+int64(d)) => (ADDQconst [c+d] x)
+(ADDLconst [c] (ADDLconst [d] x)) => (ADDLconst [c+d] x)
+(SUBQconst (MOVQconst [d]) [c]) => (MOVQconst [d-int64(c)])
+(SUBQconst (SUBQconst x [d]) [c]) && is32Bit(int64(-c)-int64(d)) => (ADDQconst [-c-d] x)
+(SARQconst [c] (MOVQconst [d])) => (MOVQconst [d>>uint64(c)])
+(SARLconst [c] (MOVQconst [d])) => (MOVQconst [int64(int32(d))>>uint64(c)])
+(SARWconst [c] (MOVQconst [d])) => (MOVQconst [int64(int16(d))>>uint64(c)])
+(SARBconst [c] (MOVQconst [d])) => (MOVQconst [int64(int8(d))>>uint64(c)])
+(NEGQ (MOVQconst [c])) => (MOVQconst [-c])
+(NEGL (MOVLconst [c])) => (MOVLconst [-c])
+(MULQconst [c] (MOVQconst [d])) => (MOVQconst [int64(c)*d])
+(MULLconst [c] (MOVLconst [d])) => (MOVLconst [c*d])
+(ANDQconst [c] (MOVQconst [d])) => (MOVQconst [int64(c)&d])
+(ANDLconst [c] (MOVLconst [d])) => (MOVLconst [c&d])
+(ORQconst [c] (MOVQconst [d])) => (MOVQconst [int64(c)|d])
+(ORLconst [c] (MOVLconst [d])) => (MOVLconst [c|d])
+(XORQconst [c] (MOVQconst [d])) => (MOVQconst [int64(c)^d])
+(XORLconst [c] (MOVLconst [d])) => (MOVLconst [c^d])
+(NOTQ (MOVQconst [c])) => (MOVQconst [^c])
+(NOTL (MOVLconst [c])) => (MOVLconst [^c])
+(BTSQconst [c] (MOVQconst [d])) => (MOVQconst [d|(1<<uint32(c))])
+(BTSLconst [c] (MOVLconst [d])) => (MOVLconst [d|(1<<uint32(c))])
+(BTRQconst [c] (MOVQconst [d])) => (MOVQconst [d&^(1<<uint32(c))])
+(BTRLconst [c] (MOVLconst [d])) => (MOVLconst [d&^(1<<uint32(c))])
+(BTCQconst [c] (MOVQconst [d])) => (MOVQconst [d^(1<<uint32(c))])
+(BTCLconst [c] (MOVLconst [d])) => (MOVLconst [d^(1<<uint32(c))])
+
+// If c or d doesn't fit into 32 bits, then we can't construct ORQconst,
+// but we can still constant-fold.
+// In theory this applies to any of the simplifications above,
+// but ORQ is the only one I've actually seen occur.
+(ORQ (MOVQconst [c]) (MOVQconst [d])) => (MOVQconst [c|d])
+
+// generic simplifications
+// TODO: more of this
+(ADDQ x (NEGQ y)) => (SUBQ x y)
+(ADDL x (NEGL y)) => (SUBL x y)
+(SUBQ x x) => (MOVQconst [0])
+(SUBL x x) => (MOVLconst [0])
+(ANDQ x x) => x
+(ANDL x x) => x
+(ORQ x x) => x
+(ORL x x) => x
+(XORQ x x) => (MOVQconst [0])
+(XORL x x) => (MOVLconst [0])
+
+(SHLLconst [d] (MOVLconst [c])) => (MOVLconst [c << uint64(d)])
+(SHLQconst [d] (MOVQconst [c])) => (MOVQconst [c << uint64(d)])
+(SHLQconst [d] (MOVLconst [c])) => (MOVQconst [int64(c) << uint64(d)])
+
+// Fold NEG into ADDconst/MULconst. Take care to keep c in 32 bit range.
+(NEGQ (ADDQconst [c] (NEGQ x))) && c != -(1<<31) => (ADDQconst [-c] x)
+(MULQconst [c] (NEGQ x)) && c != -(1<<31) => (MULQconst [-c] x)
+
+// checking AND against 0.
+(CMPQconst a:(ANDQ x y) [0]) && a.Uses == 1 => (TESTQ x y)
+(CMPLconst a:(ANDL x y) [0]) && a.Uses == 1 => (TESTL x y)
+(CMPWconst a:(ANDL x y) [0]) && a.Uses == 1 => (TESTW x y)
+(CMPBconst a:(ANDL x y) [0]) && a.Uses == 1 => (TESTB x y)
+(CMPQconst a:(ANDQconst [c] x) [0]) && a.Uses == 1 => (TESTQconst [c] x)
+(CMPLconst a:(ANDLconst [c] x) [0]) && a.Uses == 1 => (TESTLconst [c] x)
+(CMPWconst a:(ANDLconst [c] x) [0]) && a.Uses == 1 => (TESTWconst [int16(c)] x)
+(CMPBconst a:(ANDLconst [c] x) [0]) && a.Uses == 1 => (TESTBconst [int8(c)] x)
+
+// Convert TESTx to TESTxconst if possible.
+(TESTQ (MOVQconst [c]) x) && is32Bit(c) => (TESTQconst [int32(c)] x)
+(TESTL (MOVLconst [c]) x) => (TESTLconst [c] x)
+(TESTW (MOVLconst [c]) x) => (TESTWconst [int16(c)] x)
+(TESTB (MOVLconst [c]) x) => (TESTBconst [int8(c)] x)
+
+// TEST %reg,%reg is shorter than CMP
+(CMPQconst x [0]) => (TESTQ x x)
+(CMPLconst x [0]) => (TESTL x x)
+(CMPWconst x [0]) => (TESTW x x)
+(CMPBconst x [0]) => (TESTB x x)
+(TESTQconst [-1] x) && x.Op != OpAMD64MOVQconst => (TESTQ x x)
+(TESTLconst [-1] x) && x.Op != OpAMD64MOVLconst => (TESTL x x)
+(TESTWconst [-1] x) && x.Op != OpAMD64MOVLconst => (TESTW x x)
+(TESTBconst [-1] x) && x.Op != OpAMD64MOVLconst => (TESTB x x)
+
+// Convert LEAQ1 back to ADDQ if we can
+(LEAQ1 [0] x y) && v.Aux == nil => (ADDQ x y)
+
+// Combining byte loads into larger (unaligned) loads.
+// There are many ways these combinations could occur. This is
+// designed to match the way encoding/binary.LittleEndian does it.
+
+// Little-endian loads
+
+(OR(L|Q) x0:(MOVBload [i0] {s} p mem)
+ sh:(SHL(L|Q)const [8] x1:(MOVBload [i1] {s} p mem)))
+ && i1 == i0+1
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem)
+
+(OR(L|Q) x0:(MOVBload [i] {s} p0 mem)
+ sh:(SHL(L|Q)const [8] x1:(MOVBload [i] {s} p1 mem)))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVWload [i] {s} p0 mem)
+
+(OR(L|Q) x0:(MOVWload [i0] {s} p mem)
+ sh:(SHL(L|Q)const [16] x1:(MOVWload [i1] {s} p mem)))
+ && i1 == i0+2
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVLload [i0] {s} p mem)
+
+(OR(L|Q) x0:(MOVWload [i] {s} p0 mem)
+ sh:(SHL(L|Q)const [16] x1:(MOVWload [i] {s} p1 mem)))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && sequentialAddresses(p0, p1, 2)
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVLload [i] {s} p0 mem)
+
+(ORQ x0:(MOVLload [i0] {s} p mem)
+ sh:(SHLQconst [32] x1:(MOVLload [i1] {s} p mem)))
+ && i1 == i0+4
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVQload [i0] {s} p mem)
+
+(ORQ x0:(MOVLload [i] {s} p0 mem)
+ sh:(SHLQconst [32] x1:(MOVLload [i] {s} p1 mem)))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && sequentialAddresses(p0, p1, 4)
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVQload [i] {s} p0 mem)
+
+(OR(L|Q)
+ s1:(SHL(L|Q)const [j1] x1:(MOVBload [i1] {s} p mem))
+ or:(OR(L|Q)
+ s0:(SHL(L|Q)const [j0] x0:(MOVBload [i0] {s} p mem))
+ y))
+ && i1 == i0+1
+ && j1 == j0+8
+ && j0 % 16 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (OR(L|Q) <v.Type> (SHL(L|Q)const <v.Type> [j0] (MOVWload [i0] {s} p mem)) y)
+
+(OR(L|Q)
+ s1:(SHL(L|Q)const [j1] x1:(MOVBload [i] {s} p1 mem))
+ or:(OR(L|Q)
+ s0:(SHL(L|Q)const [j0] x0:(MOVBload [i] {s} p0 mem))
+ y))
+ && j1 == j0+8
+ && j0 % 16 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (OR(L|Q) <v.Type> (SHL(L|Q)const <v.Type> [j0] (MOVWload [i] {s} p0 mem)) y)
+
+(ORQ
+ s1:(SHLQconst [j1] x1:(MOVWload [i1] {s} p mem))
+ or:(ORQ
+ s0:(SHLQconst [j0] x0:(MOVWload [i0] {s} p mem))
+ y))
+ && i1 == i0+2
+ && j1 == j0+16
+ && j0 % 32 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j0] (MOVLload [i0] {s} p mem)) y)
+
+(ORQ
+ s1:(SHLQconst [j1] x1:(MOVWload [i] {s} p1 mem))
+ or:(ORQ
+ s0:(SHLQconst [j0] x0:(MOVWload [i] {s} p0 mem))
+ y))
+ && j1 == j0+16
+ && j0 % 32 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && sequentialAddresses(p0, p1, 2)
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j0] (MOVLload [i] {s} p0 mem)) y)
+
+// Big-endian loads
+
+(OR(L|Q)
+ x1:(MOVBload [i1] {s} p mem)
+ sh:(SHL(L|Q)const [8] x0:(MOVBload [i0] {s} p mem)))
+ && i1 == i0+1
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (ROLWconst <v.Type> [8] (MOVWload [i0] {s} p mem))
+
+(OR(L|Q)
+ x1:(MOVBload [i] {s} p1 mem)
+ sh:(SHL(L|Q)const [8] x0:(MOVBload [i] {s} p0 mem)))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (ROLWconst <v.Type> [8] (MOVWload [i] {s} p0 mem))
+
+(OR(L|Q)
+ r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem))
+ sh:(SHL(L|Q)const [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem))))
+ && i1 == i0+2
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && r0.Uses == 1
+ && r1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, r0, r1, sh)
+ => @mergePoint(b,x0,x1) (BSWAPL <v.Type> (MOVLload [i0] {s} p mem))
+
+(OR(L|Q)
+ r1:(ROLWconst [8] x1:(MOVWload [i] {s} p1 mem))
+ sh:(SHL(L|Q)const [16] r0:(ROLWconst [8] x0:(MOVWload [i] {s} p0 mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && r0.Uses == 1
+ && r1.Uses == 1
+ && sh.Uses == 1
+ && sequentialAddresses(p0, p1, 2)
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, r0, r1, sh)
+ => @mergePoint(b,x0,x1) (BSWAPL <v.Type> (MOVLload [i] {s} p0 mem))
+
+(ORQ
+ r1:(BSWAPL x1:(MOVLload [i1] {s} p mem))
+ sh:(SHLQconst [32] r0:(BSWAPL x0:(MOVLload [i0] {s} p mem))))
+ && i1 == i0+4
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && r0.Uses == 1
+ && r1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, r0, r1, sh)
+ => @mergePoint(b,x0,x1) (BSWAPQ <v.Type> (MOVQload [i0] {s} p mem))
+
+(ORQ
+ r1:(BSWAPL x1:(MOVLload [i] {s} p1 mem))
+ sh:(SHLQconst [32] r0:(BSWAPL x0:(MOVLload [i] {s} p0 mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && r0.Uses == 1
+ && r1.Uses == 1
+ && sh.Uses == 1
+ && sequentialAddresses(p0, p1, 4)
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, r0, r1, sh)
+ => @mergePoint(b,x0,x1) (BSWAPQ <v.Type> (MOVQload [i] {s} p0 mem))
+
+(OR(L|Q)
+ s0:(SHL(L|Q)const [j0] x0:(MOVBload [i0] {s} p mem))
+ or:(OR(L|Q)
+ s1:(SHL(L|Q)const [j1] x1:(MOVBload [i1] {s} p mem))
+ y))
+ && i1 == i0+1
+ && j1 == j0-8
+ && j1 % 16 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (OR(L|Q) <v.Type> (SHL(L|Q)const <v.Type> [j1] (ROLWconst <typ.UInt16> [8] (MOVWload [i0] {s} p mem))) y)
+
+(OR(L|Q)
+ s0:(SHL(L|Q)const [j0] x0:(MOVBload [i] {s} p0 mem))
+ or:(OR(L|Q)
+ s1:(SHL(L|Q)const [j1] x1:(MOVBload [i] {s} p1 mem))
+ y))
+ && j1 == j0-8
+ && j1 % 16 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (OR(L|Q) <v.Type> (SHL(L|Q)const <v.Type> [j1] (ROLWconst <typ.UInt16> [8] (MOVWload [i] {s} p0 mem))) y)
+
+(ORQ
+ s0:(SHLQconst [j0] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem)))
+ or:(ORQ
+ s1:(SHLQconst [j1] r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem)))
+ y))
+ && i1 == i0+2
+ && j1 == j0-16
+ && j1 % 32 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && r0.Uses == 1
+ && r1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, r0, r1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j1] (BSWAPL <typ.UInt32> (MOVLload [i0] {s} p mem))) y)
+
+(ORQ
+ s0:(SHLQconst [j0] r0:(ROLWconst [8] x0:(MOVWload [i] {s} p0 mem)))
+ or:(ORQ
+ s1:(SHLQconst [j1] r1:(ROLWconst [8] x1:(MOVWload [i] {s} p1 mem)))
+ y))
+ && j1 == j0-16
+ && j1 % 32 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && r0.Uses == 1
+ && r1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && sequentialAddresses(p0, p1, 2)
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, r0, r1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j1] (BSWAPL <typ.UInt32> (MOVLload [i] {s} p0 mem))) y)
+
+// Combine 2 byte stores + shift into rolw 8 + word store
+(MOVBstore [i] {s} p w
+ x0:(MOVBstore [i-1] {s} p (SHRWconst [8] w) mem))
+ && x0.Uses == 1
+ && clobber(x0)
+ => (MOVWstore [i-1] {s} p (ROLWconst <w.Type> [8] w) mem)
+(MOVBstore [i] {s} p1 w
+ x0:(MOVBstore [i] {s} p0 (SHRWconst [8] w) mem))
+ && x0.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && clobber(x0)
+ => (MOVWstore [i] {s} p0 (ROLWconst <w.Type> [8] w) mem)
+
+// Combine stores + shifts into bswap and larger (unaligned) stores
+(MOVBstore [i] {s} p w
+ x2:(MOVBstore [i-1] {s} p (SHRLconst [8] w)
+ x1:(MOVBstore [i-2] {s} p (SHRLconst [16] w)
+ x0:(MOVBstore [i-3] {s} p (SHRLconst [24] w) mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && clobber(x0, x1, x2)
+ => (MOVLstore [i-3] {s} p (BSWAPL <w.Type> w) mem)
+(MOVBstore [i] {s} p3 w
+ x2:(MOVBstore [i] {s} p2 (SHRLconst [8] w)
+ x1:(MOVBstore [i] {s} p1 (SHRLconst [16] w)
+ x0:(MOVBstore [i] {s} p0 (SHRLconst [24] w) mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && sequentialAddresses(p1, p2, 1)
+ && sequentialAddresses(p2, p3, 1)
+ && clobber(x0, x1, x2)
+ => (MOVLstore [i] {s} p0 (BSWAPL <w.Type> w) mem)
+
+(MOVBstore [i] {s} p w
+ x6:(MOVBstore [i-1] {s} p (SHRQconst [8] w)
+ x5:(MOVBstore [i-2] {s} p (SHRQconst [16] w)
+ x4:(MOVBstore [i-3] {s} p (SHRQconst [24] w)
+ x3:(MOVBstore [i-4] {s} p (SHRQconst [32] w)
+ x2:(MOVBstore [i-5] {s} p (SHRQconst [40] w)
+ x1:(MOVBstore [i-6] {s} p (SHRQconst [48] w)
+ x0:(MOVBstore [i-7] {s} p (SHRQconst [56] w) mem))))))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && x3.Uses == 1
+ && x4.Uses == 1
+ && x5.Uses == 1
+ && x6.Uses == 1
+ && clobber(x0, x1, x2, x3, x4, x5, x6)
+ => (MOVQstore [i-7] {s} p (BSWAPQ <w.Type> w) mem)
+(MOVBstore [i] {s} p7 w
+ x6:(MOVBstore [i] {s} p6 (SHRQconst [8] w)
+ x5:(MOVBstore [i] {s} p5 (SHRQconst [16] w)
+ x4:(MOVBstore [i] {s} p4 (SHRQconst [24] w)
+ x3:(MOVBstore [i] {s} p3 (SHRQconst [32] w)
+ x2:(MOVBstore [i] {s} p2 (SHRQconst [40] w)
+ x1:(MOVBstore [i] {s} p1 (SHRQconst [48] w)
+ x0:(MOVBstore [i] {s} p0 (SHRQconst [56] w) mem))))))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && x3.Uses == 1
+ && x4.Uses == 1
+ && x5.Uses == 1
+ && x6.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && sequentialAddresses(p1, p2, 1)
+ && sequentialAddresses(p2, p3, 1)
+ && sequentialAddresses(p3, p4, 1)
+ && sequentialAddresses(p4, p5, 1)
+ && sequentialAddresses(p5, p6, 1)
+ && sequentialAddresses(p6, p7, 1)
+ && clobber(x0, x1, x2, x3, x4, x5, x6)
+ => (MOVQstore [i] {s} p0 (BSWAPQ <w.Type> w) mem)
+
+// Combine constant stores into larger (unaligned) stores.
+(MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem))
+ && x.Uses == 1
+ && a.Off() + 1 == c.Off()
+ && clobber(x)
+ => (MOVWstoreconst [makeValAndOff64(a.Val()&0xff | c.Val()<<8, a.Off())] {s} p mem)
+(MOVBstoreconst [a] {s} p x:(MOVBstoreconst [c] {s} p mem))
+ && x.Uses == 1
+ && a.Off() + 1 == c.Off()
+ && clobber(x)
+ => (MOVWstoreconst [makeValAndOff64(a.Val()&0xff | c.Val()<<8, a.Off())] {s} p mem)
+(MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem))
+ && x.Uses == 1
+ && a.Off() + 2 == c.Off()
+ && clobber(x)
+ => (MOVLstoreconst [makeValAndOff64(a.Val()&0xffff | c.Val()<<16, a.Off())] {s} p mem)
+(MOVWstoreconst [a] {s} p x:(MOVWstoreconst [c] {s} p mem))
+ && x.Uses == 1
+ && a.Off() + 2 == c.Off()
+ && clobber(x)
+ => (MOVLstoreconst [makeValAndOff64(a.Val()&0xffff | c.Val()<<16, a.Off())] {s} p mem)
+(MOVLstoreconst [c] {s} p x:(MOVLstoreconst [a] {s} p mem))
+ && x.Uses == 1
+ && a.Off() + 4 == c.Off()
+ && clobber(x)
+ => (MOVQstore [a.Off32()] {s} p (MOVQconst [a.Val()&0xffffffff | c.Val()<<32]) mem)
+(MOVLstoreconst [a] {s} p x:(MOVLstoreconst [c] {s} p mem))
+ && x.Uses == 1
+ && a.Off() + 4 == c.Off()
+ && clobber(x)
+ => (MOVQstore [a.Off32()] {s} p (MOVQconst [a.Val()&0xffffffff | c.Val()<<32]) mem)
+(MOVQstoreconst [c] {s} p x:(MOVQstoreconst [c2] {s} p mem))
+ && config.useSSE
+ && x.Uses == 1
+ && c2.Off() + 8 == c.Off()
+ && c.Val() == 0
+ && c2.Val() == 0
+ && clobber(x)
+ => (MOVOstore [c2.Off32()] {s} p (MOVOconst [0]) mem)
+
+// Combine stores into larger (unaligned) stores. Little endian.
+(MOVBstore [i] {s} p (SHR(W|L|Q)const [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstore [i-1] {s} p w mem)
+(MOVBstore [i] {s} p w x:(MOVBstore [i+1] {s} p (SHR(W|L|Q)const [8] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstore [i] {s} p w mem)
+(MOVBstore [i] {s} p (SHR(L|Q)const [j] w) x:(MOVBstore [i-1] {s} p w0:(SHR(L|Q)const [j-8] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstore [i-1] {s} p w0 mem)
+(MOVBstore [i] {s} p1 (SHR(W|L|Q)const [8] w) x:(MOVBstore [i] {s} p0 w mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && clobber(x)
+ => (MOVWstore [i] {s} p0 w mem)
+(MOVBstore [i] {s} p0 w x:(MOVBstore [i] {s} p1 (SHR(W|L|Q)const [8] w) mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && clobber(x)
+ => (MOVWstore [i] {s} p0 w mem)
+(MOVBstore [i] {s} p1 (SHR(L|Q)const [j] w) x:(MOVBstore [i] {s} p0 w0:(SHR(L|Q)const [j-8] w) mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 1)
+ && clobber(x)
+ => (MOVWstore [i] {s} p0 w0 mem)
+
+(MOVWstore [i] {s} p (SHR(L|Q)const [16] w) x:(MOVWstore [i-2] {s} p w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVLstore [i-2] {s} p w mem)
+(MOVWstore [i] {s} p (SHR(L|Q)const [j] w) x:(MOVWstore [i-2] {s} p w0:(SHR(L|Q)const [j-16] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVLstore [i-2] {s} p w0 mem)
+(MOVWstore [i] {s} p1 (SHR(L|Q)const [16] w) x:(MOVWstore [i] {s} p0 w mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 2)
+ && clobber(x)
+ => (MOVLstore [i] {s} p0 w mem)
+(MOVWstore [i] {s} p1 (SHR(L|Q)const [j] w) x:(MOVWstore [i] {s} p0 w0:(SHR(L|Q)const [j-16] w) mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 2)
+ && clobber(x)
+ => (MOVLstore [i] {s} p0 w0 mem)
+
+(MOVLstore [i] {s} p (SHRQconst [32] w) x:(MOVLstore [i-4] {s} p w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVQstore [i-4] {s} p w mem)
+(MOVLstore [i] {s} p (SHRQconst [j] w) x:(MOVLstore [i-4] {s} p w0:(SHRQconst [j-32] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVQstore [i-4] {s} p w0 mem)
+(MOVLstore [i] {s} p1 (SHRQconst [32] w) x:(MOVLstore [i] {s} p0 w mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 4)
+ && clobber(x)
+ => (MOVQstore [i] {s} p0 w mem)
+(MOVLstore [i] {s} p1 (SHRQconst [j] w) x:(MOVLstore [i] {s} p0 w0:(SHRQconst [j-32] w) mem))
+ && x.Uses == 1
+ && sequentialAddresses(p0, p1, 4)
+ && clobber(x)
+ => (MOVQstore [i] {s} p0 w0 mem)
+
+(MOVBstore [i] {s} p
+ x1:(MOVBload [j] {s2} p2 mem)
+ mem2:(MOVBstore [i-1] {s} p
+ x2:(MOVBload [j-1] {s2} p2 mem) mem))
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && mem2.Uses == 1
+ && clobber(x1, x2, mem2)
+ => (MOVWstore [i-1] {s} p (MOVWload [j-1] {s2} p2 mem) mem)
+
+(MOVWstore [i] {s} p
+ x1:(MOVWload [j] {s2} p2 mem)
+ mem2:(MOVWstore [i-2] {s} p
+ x2:(MOVWload [j-2] {s2} p2 mem) mem))
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && mem2.Uses == 1
+ && clobber(x1, x2, mem2)
+ => (MOVLstore [i-2] {s} p (MOVLload [j-2] {s2} p2 mem) mem)
+
+(MOVLstore [i] {s} p
+ x1:(MOVLload [j] {s2} p2 mem)
+ mem2:(MOVLstore [i-4] {s} p
+ x2:(MOVLload [j-4] {s2} p2 mem) mem))
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && mem2.Uses == 1
+ && clobber(x1, x2, mem2)
+ => (MOVQstore [i-4] {s} p (MOVQload [j-4] {s2} p2 mem) mem)
+
+(MOVQload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVQload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVLload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVLload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVWload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVBload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+
+(MOVQstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVQstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVLstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVLstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVWstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVBstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+
+(MOVQstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) =>
+ (MOVQstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+(MOVLstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) =>
+ (MOVLstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+(MOVWstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) =>
+ (MOVWstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+(MOVBstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) =>
+ (MOVBstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+
+(MOVQload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) => (MOVQload [off1+off2] {sym} ptr mem)
+(MOVLload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) => (MOVLload [off1+off2] {sym} ptr mem)
+(MOVWload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) => (MOVWload [off1+off2] {sym} ptr mem)
+(MOVBload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) => (MOVBload [off1+off2] {sym} ptr mem)
+(MOVQstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(int64(off1)+int64(off2)) => (MOVQstore [off1+off2] {sym} ptr val mem)
+(MOVLstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(int64(off1)+int64(off2)) => (MOVLstore [off1+off2] {sym} ptr val mem)
+(MOVWstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(int64(off1)+int64(off2)) => (MOVWstore [off1+off2] {sym} ptr val mem)
+(MOVBstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(int64(off1)+int64(off2)) => (MOVBstore [off1+off2] {sym} ptr val mem)
+(MOVQstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) =>
+ (MOVQstoreconst [sc.addOffset32(off)] {s} ptr mem)
+(MOVLstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) =>
+ (MOVLstoreconst [sc.addOffset32(off)] {s} ptr mem)
+(MOVWstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) =>
+ (MOVWstoreconst [sc.addOffset32(off)] {s} ptr mem)
+(MOVBstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) =>
+ (MOVBstoreconst [sc.addOffset32(off)] {s} ptr mem)
+
+// Merge load and op
+// TODO: add indexed variants?
+((ADD|SUB|AND|OR|XOR)Q x l:(MOVQload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|AND|OR|XOR)Qload x [off] {sym} ptr mem)
+((ADD|SUB|AND|OR|XOR)L x l:(MOVLload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|AND|OR|XOR)Lload x [off] {sym} ptr mem)
+((ADD|SUB|MUL|DIV)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|MUL|DIV)SDload x [off] {sym} ptr mem)
+((ADD|SUB|MUL|DIV)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|MUL|DIV)SSload x [off] {sym} ptr mem)
+(MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) => ((ADD|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
+(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
+ ((ADD|SUB|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
+(MOVLstore {sym} [off] ptr y:((BTC|BTR|BTS)L l:(MOVLload [off] {sym} ptr mem) <t> x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
+ ((BTC|BTR|BTS)Lmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
+(MOVQstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Qload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) => ((ADD|AND|OR|XOR)Qmodify [off] {sym} ptr x mem)
+(MOVQstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)Q l:(MOVQload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
+ ((ADD|SUB|AND|OR|XOR)Qmodify [off] {sym} ptr x mem)
+(MOVQstore {sym} [off] ptr y:((BTC|BTR|BTS)Q l:(MOVQload [off] {sym} ptr mem) <t> x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
+ ((BTC|BTR|BTS)Qmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
+
+// Merge ADDQconst and LEAQ into atomic loads.
+(MOV(Q|L|B)atomicload [off1] {sym} (ADDQconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOV(Q|L|B)atomicload [off1+off2] {sym} ptr mem)
+(MOV(Q|L|B)atomicload [off1] {sym1} (LEAQ [off2] {sym2} ptr) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOV(Q|L|B)atomicload [off1+off2] {mergeSym(sym1, sym2)} ptr mem)
+
+// Merge ADDQconst and LEAQ into atomic stores.
+(XCHGQ [off1] {sym} val (ADDQconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (XCHGQ [off1+off2] {sym} val ptr mem)
+(XCHGQ [off1] {sym1} val (LEAQ [off2] {sym2} ptr) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && ptr.Op != OpSB =>
+ (XCHGQ [off1+off2] {mergeSym(sym1,sym2)} val ptr mem)
+(XCHGL [off1] {sym} val (ADDQconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (XCHGL [off1+off2] {sym} val ptr mem)
+(XCHGL [off1] {sym1} val (LEAQ [off2] {sym2} ptr) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && ptr.Op != OpSB =>
+ (XCHGL [off1+off2] {mergeSym(sym1,sym2)} val ptr mem)
+
+// Merge ADDQconst into atomic adds.
+// TODO: merging LEAQ doesn't work, assembler doesn't like the resulting instructions.
+(XADDQlock [off1] {sym} val (ADDQconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (XADDQlock [off1+off2] {sym} val ptr mem)
+(XADDLlock [off1] {sym} val (ADDQconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (XADDLlock [off1+off2] {sym} val ptr mem)
+
+// Merge ADDQconst into atomic compare and swaps.
+// TODO: merging LEAQ doesn't work, assembler doesn't like the resulting instructions.
+(CMPXCHGQlock [off1] {sym} (ADDQconst [off2] ptr) old new_ mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (CMPXCHGQlock [off1+off2] {sym} ptr old new_ mem)
+(CMPXCHGLlock [off1] {sym} (ADDQconst [off2] ptr) old new_ mem) && is32Bit(int64(off1)+int64(off2)) =>
+ (CMPXCHGLlock [off1+off2] {sym} ptr old new_ mem)
+
+// We don't need the conditional move if we know the arg of BSF is not zero.
+(CMOVQEQ x _ (Select1 (BSFQ (ORQconst [c] _)))) && c != 0 => x
+// Extension is unnecessary for trailing zeros.
+(BSFQ (ORQconst <t> [1<<8] (MOVBQZX x))) => (BSFQ (ORQconst <t> [1<<8] x))
+(BSFQ (ORQconst <t> [1<<16] (MOVWQZX x))) => (BSFQ (ORQconst <t> [1<<16] x))
+
+// Redundant sign/zero extensions
+// Note: see issue 21963. We have to make sure we use the right type on
+// the resulting extension (the outer type, not the inner type).
+(MOVLQSX (MOVLQSX x)) => (MOVLQSX x)
+(MOVLQSX (MOVWQSX x)) => (MOVWQSX x)
+(MOVLQSX (MOVBQSX x)) => (MOVBQSX x)
+(MOVWQSX (MOVWQSX x)) => (MOVWQSX x)
+(MOVWQSX (MOVBQSX x)) => (MOVBQSX x)
+(MOVBQSX (MOVBQSX x)) => (MOVBQSX x)
+(MOVLQZX (MOVLQZX x)) => (MOVLQZX x)
+(MOVLQZX (MOVWQZX x)) => (MOVWQZX x)
+(MOVLQZX (MOVBQZX x)) => (MOVBQZX x)
+(MOVWQZX (MOVWQZX x)) => (MOVWQZX x)
+(MOVWQZX (MOVBQZX x)) => (MOVBQZX x)
+(MOVBQZX (MOVBQZX x)) => (MOVBQZX x)
+
+(MOVQstore [off] {sym} ptr a:((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ && isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a) =>
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+(MOVLstore [off] {sym} ptr a:((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ && isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a) =>
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+
+// float <-> int register moves, with no conversion.
+// These come up when compiling math.{Float{32,64}bits,Float{32,64}frombits}.
+(MOVQload [off] {sym} ptr (MOVSDstore [off] {sym} ptr val _)) => (MOVQf2i val)
+(MOVLload [off] {sym} ptr (MOVSSstore [off] {sym} ptr val _)) => (MOVLf2i val)
+(MOVSDload [off] {sym} ptr (MOVQstore [off] {sym} ptr val _)) => (MOVQi2f val)
+(MOVSSload [off] {sym} ptr (MOVLstore [off] {sym} ptr val _)) => (MOVLi2f val)
+
+// Other load-like ops.
+(ADDQload x [off] {sym} ptr (MOVSDstore [off] {sym} ptr y _)) => (ADDQ x (MOVQf2i y))
+(ADDLload x [off] {sym} ptr (MOVSSstore [off] {sym} ptr y _)) => (ADDL x (MOVLf2i y))
+(SUBQload x [off] {sym} ptr (MOVSDstore [off] {sym} ptr y _)) => (SUBQ x (MOVQf2i y))
+(SUBLload x [off] {sym} ptr (MOVSSstore [off] {sym} ptr y _)) => (SUBL x (MOVLf2i y))
+(ANDQload x [off] {sym} ptr (MOVSDstore [off] {sym} ptr y _)) => (ANDQ x (MOVQf2i y))
+(ANDLload x [off] {sym} ptr (MOVSSstore [off] {sym} ptr y _)) => (ANDL x (MOVLf2i y))
+( ORQload x [off] {sym} ptr (MOVSDstore [off] {sym} ptr y _)) => ( ORQ x (MOVQf2i y))
+( ORLload x [off] {sym} ptr (MOVSSstore [off] {sym} ptr y _)) => ( ORL x (MOVLf2i y))
+(XORQload x [off] {sym} ptr (MOVSDstore [off] {sym} ptr y _)) => (XORQ x (MOVQf2i y))
+(XORLload x [off] {sym} ptr (MOVSSstore [off] {sym} ptr y _)) => (XORL x (MOVLf2i y))
+
+(ADDSDload x [off] {sym} ptr (MOVQstore [off] {sym} ptr y _)) => (ADDSD x (MOVQi2f y))
+(ADDSSload x [off] {sym} ptr (MOVLstore [off] {sym} ptr y _)) => (ADDSS x (MOVLi2f y))
+(SUBSDload x [off] {sym} ptr (MOVQstore [off] {sym} ptr y _)) => (SUBSD x (MOVQi2f y))
+(SUBSSload x [off] {sym} ptr (MOVLstore [off] {sym} ptr y _)) => (SUBSS x (MOVLi2f y))
+(MULSDload x [off] {sym} ptr (MOVQstore [off] {sym} ptr y _)) => (MULSD x (MOVQi2f y))
+(MULSSload x [off] {sym} ptr (MOVLstore [off] {sym} ptr y _)) => (MULSS x (MOVLi2f y))
+
+// Redirect stores to use the other register set.
+(MOVQstore [off] {sym} ptr (MOVQf2i val) mem) => (MOVSDstore [off] {sym} ptr val mem)
+(MOVLstore [off] {sym} ptr (MOVLf2i val) mem) => (MOVSSstore [off] {sym} ptr val mem)
+(MOVSDstore [off] {sym} ptr (MOVQi2f val) mem) => (MOVQstore [off] {sym} ptr val mem)
+(MOVSSstore [off] {sym} ptr (MOVLi2f val) mem) => (MOVLstore [off] {sym} ptr val mem)
+
+// Load args directly into the register class where it will be used.
+// We do this by just modifying the type of the Arg.
+(MOVQf2i <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() => @b.Func.Entry (Arg <t> [off] {sym})
+(MOVLf2i <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() => @b.Func.Entry (Arg <t> [off] {sym})
+(MOVQi2f <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() => @b.Func.Entry (Arg <t> [off] {sym})
+(MOVLi2f <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() => @b.Func.Entry (Arg <t> [off] {sym})
+
+// LEAQ is rematerializeable, so this helps to avoid register spill.
+// See issue 22947 for details
+(ADD(Q|L)const [off] x:(SP)) => (LEA(Q|L) [off] x)
+
+// HMULx is commutative, but its first argument must go in AX.
+// If possible, put a rematerializeable value in the first argument slot,
+// to reduce the odds that another value will be have to spilled
+// specifically to free up AX.
+(HMUL(Q|L) x y) && !x.rematerializeable() && y.rematerializeable() => (HMUL(Q|L) y x)
+(HMUL(Q|L)U x y) && !x.rematerializeable() && y.rematerializeable() => (HMUL(Q|L)U y x)
+
+// Fold loads into compares
+// Note: these may be undone by the flagalloc pass.
+(CMP(Q|L|W|B) l:(MOV(Q|L|W|B)load {sym} [off] ptr mem) x) && canMergeLoad(v, l) && clobber(l) => (CMP(Q|L|W|B)load {sym} [off] ptr x mem)
+(CMP(Q|L|W|B) x l:(MOV(Q|L|W|B)load {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (InvertFlags (CMP(Q|L|W|B)load {sym} [off] ptr x mem))
+
+(CMP(Q|L)const l:(MOV(Q|L)load {sym} [off] ptr mem) [c])
+ && l.Uses == 1
+ && clobber(l) =>
+@l.Block (CMP(Q|L)constload {sym} [makeValAndOff32(c,off)] ptr mem)
+(CMP(W|B)const l:(MOV(W|B)load {sym} [off] ptr mem) [c])
+ && l.Uses == 1
+ && clobber(l) =>
+@l.Block (CMP(W|B)constload {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+
+(CMPQload {sym} [off] ptr (MOVQconst [c]) mem) && validValAndOff(c,int64(off)) => (CMPQconstload {sym} [makeValAndOff64(c,int64(off))] ptr mem)
+(CMPLload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(c),int64(off)) => (CMPLconstload {sym} [makeValAndOff32(c,off)] ptr mem)
+(CMPWload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(int16(c)),int64(off)) => (CMPWconstload {sym} [makeValAndOff32(int32(int16(c)),off)] ptr mem)
+(CMPBload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(int8(c)),int64(off)) => (CMPBconstload {sym} [makeValAndOff32(int32(int8(c)),off)] ptr mem)
+
+(TEST(Q|L|W|B) l:(MOV(Q|L|W|B)load {sym} [off] ptr mem) l2)
+ && l == l2
+ && l.Uses == 2
+ && validValAndOff(0, int64(off))
+ && clobber(l) =>
+ @l.Block (CMP(Q|L|W|B)constload {sym} [makeValAndOff64(0, int64(off))] ptr mem)
+
+(MOVBload [off] {sym} (SB) _) && symIsRO(sym) => (MOVLconst [int32(read8(sym, int64(off)))])
+(MOVWload [off] {sym} (SB) _) && symIsRO(sym) => (MOVLconst [int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+(MOVLload [off] {sym} (SB) _) && symIsRO(sym) => (MOVQconst [int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+(MOVQload [off] {sym} (SB) _) && symIsRO(sym) => (MOVQconst [int64(read64(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+(MOVOstore [dstOff] {dstSym} ptr (MOVOload [srcOff] {srcSym} (SB) _) mem) && symIsRO(srcSym) =>
+ (MOVQstore [dstOff+8] {dstSym} ptr (MOVQconst [int64(read64(srcSym, int64(srcOff)+8, config.ctxt.Arch.ByteOrder))])
+ (MOVQstore [dstOff] {dstSym} ptr (MOVQconst [int64(read64(srcSym, int64(srcOff), config.ctxt.Arch.ByteOrder))]) mem))
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
new file mode 100644
index 0000000..a87581b
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
@@ -0,0 +1,946 @@
+// 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.
+
+// +build ignore
+
+package main
+
+import "strings"
+
+// Notes:
+// - Integer types live in the low portion of registers. Upper portions are junk.
+// - Boolean types use the low-order byte of a register. 0=false, 1=true.
+// Upper bytes are junk.
+// - Floating-point types live in the low natural slot of an sse2 register.
+// Unused portions are junk.
+// - We do not use AH,BH,CH,DH registers.
+// - When doing sub-register operations, we try to write the whole
+// destination register to avoid a partial-register write.
+// - Unused portions of AuxInt (or the Val portion of ValAndOff) are
+// filled by sign-extending the used portion. Users of AuxInt which interpret
+// AuxInt as unsigned (e.g. shifts) must be careful.
+// - All SymOff opcodes require their offset to fit in an int32.
+
+// Suffixes encode the bit width of various instructions.
+// Q (quad word) = 64 bit
+// L (long word) = 32 bit
+// W (word) = 16 bit
+// B (byte) = 8 bit
+
+// 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",
+
+ // If you add registers, update asyncPreempt in runtime
+
+ // pseudo-registers
+ "SB",
+}
+
+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 {
+ num[name] = 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")
+ bx = buildReg("BX")
+ 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")
+ callerSave = gp | fp
+ )
+ // Common slices of register masks
+ var (
+ gponly = []regMask{gp}
+ fponly = []regMask{fp}
+ )
+
+ // Common regInfo
+ var (
+ gp01 = regInfo{inputs: nil, outputs: gponly}
+ gp11 = regInfo{inputs: []regMask{gp}, outputs: gponly}
+ gp11sp = regInfo{inputs: []regMask{gpsp}, outputs: gponly}
+ gp11sb = regInfo{inputs: []regMask{gpspsb}, outputs: gponly}
+ gp21 = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
+ gp21sp = regInfo{inputs: []regMask{gpsp, gp}, outputs: gponly}
+ gp21sb = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly}
+ gp21shift = regInfo{inputs: []regMask{gp, cx}, outputs: []regMask{gp}}
+ gp11div = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{ax, dx}}
+ gp21hmul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx}, clobbers: ax}
+ gp21flags = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp, 0}}
+ gp2flags1flags = regInfo{inputs: []regMask{gp, gp, 0}, outputs: []regMask{gp, 0}}
+
+ gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}}
+ gp1flags = regInfo{inputs: []regMask{gpsp}}
+ gp0flagsLoad = regInfo{inputs: []regMask{gpspsb, 0}}
+ gp1flagsLoad = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
+ gp2flagsLoad = regInfo{inputs: []regMask{gpspsb, gpsp, gpsp, 0}}
+ flagsgp = regInfo{inputs: nil, outputs: gponly}
+
+ gp11flags = regInfo{inputs: []regMask{gp}, outputs: []regMask{gp, 0}}
+ gp1flags1flags = regInfo{inputs: []regMask{gp, 0}, outputs: []regMask{gp, 0}}
+
+ readflags = regInfo{inputs: nil, outputs: gponly}
+ flagsgpax = regInfo{inputs: nil, clobbers: ax, outputs: []regMask{gp &^ ax}}
+
+ gpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: gponly}
+ gp21load = regInfo{inputs: []regMask{gp, gpspsb, 0}, outputs: gponly}
+ gploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: gponly}
+ gp21loadidx = regInfo{inputs: []regMask{gp, gpspsb, gpsp, 0}, outputs: gponly}
+ gp21pax = regInfo{inputs: []regMask{gp &^ ax, gp}, outputs: []regMask{gp &^ ax}, clobbers: ax}
+
+ gpstore = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
+ gpstoreconst = regInfo{inputs: []regMask{gpspsb, 0}}
+ gpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, gpsp, 0}}
+ gpstoreconstidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
+ gpstorexchg = regInfo{inputs: []regMask{gp, gpspsb, 0}, outputs: []regMask{gp}}
+ cmpxchg = regInfo{inputs: []regMask{gp, ax, gp, 0}, outputs: []regMask{gp, 0}, clobbers: ax}
+
+ fp01 = regInfo{inputs: nil, outputs: fponly}
+ fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly}
+ fp31 = regInfo{inputs: []regMask{fp, fp, fp}, outputs: fponly}
+ fp21load = regInfo{inputs: []regMask{fp, gpspsb, 0}, outputs: fponly}
+ fp21loadidx = regInfo{inputs: []regMask{fp, gpspsb, gpspsb, 0}, outputs: fponly}
+ fpgp = regInfo{inputs: fponly, outputs: gponly}
+ gpfp = regInfo{inputs: gponly, outputs: fponly}
+ fp11 = regInfo{inputs: fponly, outputs: fponly}
+ fp2flags = regInfo{inputs: []regMask{fp, fp}}
+
+ 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}}
+ )
+
+ var AMD64ops = []opData{
+ // fp ops
+ {name: "ADDSS", argLength: 2, reg: fp21, asm: "ADDSS", commutative: true, resultInArg0: true}, // fp32 add
+ {name: "ADDSD", argLength: 2, reg: fp21, asm: "ADDSD", commutative: true, resultInArg0: true}, // fp64 add
+ {name: "SUBSS", argLength: 2, reg: fp21, asm: "SUBSS", resultInArg0: true}, // fp32 sub
+ {name: "SUBSD", argLength: 2, reg: fp21, asm: "SUBSD", resultInArg0: true}, // fp64 sub
+ {name: "MULSS", argLength: 2, reg: fp21, asm: "MULSS", commutative: true, resultInArg0: true}, // fp32 mul
+ {name: "MULSD", argLength: 2, reg: fp21, asm: "MULSD", commutative: true, resultInArg0: true}, // fp64 mul
+ {name: "DIVSS", argLength: 2, reg: fp21, asm: "DIVSS", resultInArg0: true}, // fp32 div
+ {name: "DIVSD", argLength: 2, reg: fp21, asm: "DIVSD", resultInArg0: true}, // fp64 div
+
+ {name: "MOVSSload", argLength: 2, reg: fpload, asm: "MOVSS", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // fp32 load
+ {name: "MOVSDload", argLength: 2, reg: fpload, asm: "MOVSD", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // fp64 load
+ {name: "MOVSSconst", reg: fp01, asm: "MOVSS", aux: "Float32", rematerializeable: true}, // fp32 constant
+ {name: "MOVSDconst", reg: fp01, asm: "MOVSD", aux: "Float64", rematerializeable: true}, // fp64 constant
+ {name: "MOVSSloadidx1", argLength: 3, reg: fploadidx, asm: "MOVSS", scale: 1, aux: "SymOff", symEffect: "Read"}, // fp32 load indexed by i
+ {name: "MOVSSloadidx4", argLength: 3, reg: fploadidx, asm: "MOVSS", scale: 4, aux: "SymOff", symEffect: "Read"}, // fp32 load indexed by 4*i
+ {name: "MOVSDloadidx1", argLength: 3, reg: fploadidx, asm: "MOVSD", scale: 1, aux: "SymOff", symEffect: "Read"}, // fp64 load indexed by i
+ {name: "MOVSDloadidx8", argLength: 3, reg: fploadidx, asm: "MOVSD", scale: 8, aux: "SymOff", symEffect: "Read"}, // fp64 load indexed by 8*i
+
+ {name: "MOVSSstore", argLength: 3, reg: fpstore, asm: "MOVSS", aux: "SymOff", faultOnNilArg0: true, symEffect: "Write"}, // fp32 store
+ {name: "MOVSDstore", argLength: 3, reg: fpstore, asm: "MOVSD", aux: "SymOff", faultOnNilArg0: true, symEffect: "Write"}, // fp64 store
+ {name: "MOVSSstoreidx1", argLength: 4, reg: fpstoreidx, asm: "MOVSS", scale: 1, aux: "SymOff", symEffect: "Write"}, // fp32 indexed by i store
+ {name: "MOVSSstoreidx4", argLength: 4, reg: fpstoreidx, asm: "MOVSS", scale: 4, aux: "SymOff", symEffect: "Write"}, // fp32 indexed by 4i store
+ {name: "MOVSDstoreidx1", argLength: 4, reg: fpstoreidx, asm: "MOVSD", scale: 1, aux: "SymOff", symEffect: "Write"}, // fp64 indexed by i store
+ {name: "MOVSDstoreidx8", argLength: 4, reg: fpstoreidx, asm: "MOVSD", scale: 8, aux: "SymOff", symEffect: "Write"}, // fp64 indexed by 8i store
+
+ {name: "ADDSSload", argLength: 3, reg: fp21load, asm: "ADDSS", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp32 arg0 + tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "ADDSDload", argLength: 3, reg: fp21load, asm: "ADDSD", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp64 arg0 + tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "SUBSSload", argLength: 3, reg: fp21load, asm: "SUBSS", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp32 arg0 - tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "SUBSDload", argLength: 3, reg: fp21load, asm: "SUBSD", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp64 arg0 - tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "MULSSload", argLength: 3, reg: fp21load, asm: "MULSS", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp32 arg0 * tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "MULSDload", argLength: 3, reg: fp21load, asm: "MULSD", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp64 arg0 * tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "DIVSSload", argLength: 3, reg: fp21load, asm: "DIVSS", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp32 arg0 / tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "DIVSDload", argLength: 3, reg: fp21load, asm: "DIVSD", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp64 arg0 / tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+
+ {name: "ADDSSloadidx1", argLength: 4, reg: fp21loadidx, asm: "ADDSS", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 + tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "ADDSSloadidx4", argLength: 4, reg: fp21loadidx, asm: "ADDSS", scale: 4, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 + tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "ADDSDloadidx1", argLength: 4, reg: fp21loadidx, asm: "ADDSD", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 + tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "ADDSDloadidx8", argLength: 4, reg: fp21loadidx, asm: "ADDSD", scale: 8, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 + tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "SUBSSloadidx1", argLength: 4, reg: fp21loadidx, asm: "SUBSS", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 - tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "SUBSSloadidx4", argLength: 4, reg: fp21loadidx, asm: "SUBSS", scale: 4, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 - tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "SUBSDloadidx1", argLength: 4, reg: fp21loadidx, asm: "SUBSD", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 - tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "SUBSDloadidx8", argLength: 4, reg: fp21loadidx, asm: "SUBSD", scale: 8, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 - tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "MULSSloadidx1", argLength: 4, reg: fp21loadidx, asm: "MULSS", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 * tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "MULSSloadidx4", argLength: 4, reg: fp21loadidx, asm: "MULSS", scale: 4, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 * tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "MULSDloadidx1", argLength: 4, reg: fp21loadidx, asm: "MULSD", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 * tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "MULSDloadidx8", argLength: 4, reg: fp21loadidx, asm: "MULSD", scale: 8, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 * tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "DIVSSloadidx1", argLength: 4, reg: fp21loadidx, asm: "DIVSS", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 / tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "DIVSSloadidx4", argLength: 4, reg: fp21loadidx, asm: "DIVSS", scale: 4, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 / tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "DIVSDloadidx1", argLength: 4, reg: fp21loadidx, asm: "DIVSD", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 / tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "DIVSDloadidx8", argLength: 4, reg: fp21loadidx, asm: "DIVSD", scale: 8, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 / tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+
+ // binary ops
+ {name: "ADDQ", argLength: 2, reg: gp21sp, asm: "ADDQ", commutative: true, clobberFlags: true}, // arg0 + arg1
+ {name: "ADDL", argLength: 2, reg: gp21sp, asm: "ADDL", commutative: true, clobberFlags: true}, // arg0 + arg1
+ {name: "ADDQconst", argLength: 1, reg: gp11sp, asm: "ADDQ", aux: "Int32", typ: "UInt64", clobberFlags: true}, // arg0 + auxint
+ {name: "ADDLconst", argLength: 1, reg: gp11sp, asm: "ADDL", aux: "Int32", clobberFlags: true}, // arg0 + auxint
+ {name: "ADDQconstmodify", argLength: 2, reg: gpstoreconst, asm: "ADDQ", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // add ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "ADDLconstmodify", argLength: 2, reg: gpstoreconst, asm: "ADDL", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // add ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+
+ {name: "SUBQ", argLength: 2, reg: gp21, asm: "SUBQ", resultInArg0: true, clobberFlags: true}, // arg0 - arg1
+ {name: "SUBL", argLength: 2, reg: gp21, asm: "SUBL", resultInArg0: true, clobberFlags: true}, // arg0 - arg1
+ {name: "SUBQconst", argLength: 1, reg: gp11, asm: "SUBQ", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 - auxint
+ {name: "SUBLconst", argLength: 1, reg: gp11, asm: "SUBL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 - auxint
+
+ {name: "MULQ", argLength: 2, reg: gp21, asm: "IMULQ", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 * arg1
+ {name: "MULL", argLength: 2, reg: gp21, asm: "IMULL", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 * arg1
+ {name: "MULQconst", argLength: 1, reg: gp11, asm: "IMUL3Q", aux: "Int32", clobberFlags: true}, // arg0 * auxint
+ {name: "MULLconst", argLength: 1, reg: gp11, asm: "IMUL3L", aux: "Int32", clobberFlags: true}, // arg0 * auxint
+
+ {name: "MULLU", argLength: 2, reg: regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{ax, 0}, clobbers: dx}, typ: "(UInt32,Flags)", asm: "MULL", commutative: true, clobberFlags: true}, // Let x = arg0*arg1 (full 32x32->64 unsigned multiply). Returns uint32(x), and flags set to overflow if uint32(x) != x.
+ {name: "MULQU", argLength: 2, reg: regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{ax, 0}, clobbers: dx}, typ: "(UInt64,Flags)", asm: "MULQ", commutative: true, clobberFlags: true}, // Let x = arg0*arg1 (full 64x64->128 unsigned multiply). Returns uint64(x), and flags set to overflow if uint64(x) != x.
+
+ // HMULx[U] are intentionally not marked as commutative, even though they are.
+ // This is because they have asymmetric register requirements.
+ // There are rewrite rules to try to place arguments in preferable slots.
+ {name: "HMULQ", argLength: 2, reg: gp21hmul, asm: "IMULQ", clobberFlags: true}, // (arg0 * arg1) >> width
+ {name: "HMULL", argLength: 2, reg: gp21hmul, asm: "IMULL", clobberFlags: true}, // (arg0 * arg1) >> width
+ {name: "HMULQU", argLength: 2, reg: gp21hmul, asm: "MULQ", clobberFlags: true}, // (arg0 * arg1) >> width
+ {name: "HMULLU", argLength: 2, reg: gp21hmul, asm: "MULL", clobberFlags: true}, // (arg0 * arg1) >> width
+
+ {name: "AVGQU", argLength: 2, reg: gp21, commutative: true, resultInArg0: true, clobberFlags: true}, // (arg0 + arg1) / 2 as unsigned, all 64 result bits
+
+ // For DIVQ, DIVL and DIVW, AuxInt non-zero means that the divisor has been proved to be not -1.
+ {name: "DIVQ", argLength: 2, reg: gp11div, typ: "(Int64,Int64)", asm: "IDIVQ", aux: "Bool", clobberFlags: true}, // [arg0 / arg1, arg0 % arg1]
+ {name: "DIVL", argLength: 2, reg: gp11div, typ: "(Int32,Int32)", asm: "IDIVL", aux: "Bool", clobberFlags: true}, // [arg0 / arg1, arg0 % arg1]
+ {name: "DIVW", argLength: 2, reg: gp11div, typ: "(Int16,Int16)", asm: "IDIVW", aux: "Bool", clobberFlags: true}, // [arg0 / arg1, arg0 % arg1]
+
+ {name: "DIVQU", argLength: 2, reg: gp11div, typ: "(UInt64,UInt64)", asm: "DIVQ", clobberFlags: true}, // [arg0 / arg1, arg0 % arg1]
+ {name: "DIVLU", argLength: 2, reg: gp11div, typ: "(UInt32,UInt32)", asm: "DIVL", clobberFlags: true}, // [arg0 / arg1, arg0 % arg1]
+ {name: "DIVWU", argLength: 2, reg: gp11div, typ: "(UInt16,UInt16)", asm: "DIVW", clobberFlags: true}, // [arg0 / arg1, arg0 % arg1]
+
+ {name: "NEGLflags", argLength: 1, reg: gp11flags, typ: "(UInt32,Flags)", asm: "NEGL", resultInArg0: true}, // -arg0, flags set for 0-arg0.
+ // The following 4 add opcodes return the low 64 bits of the sum in the first result and
+ // the carry (the 65th bit) in the carry flag.
+ {name: "ADDQcarry", argLength: 2, reg: gp21flags, typ: "(UInt64,Flags)", asm: "ADDQ", commutative: true, resultInArg0: true}, // r = arg0+arg1
+ {name: "ADCQ", argLength: 3, reg: gp2flags1flags, typ: "(UInt64,Flags)", asm: "ADCQ", commutative: true, resultInArg0: true}, // r = arg0+arg1+carry(arg2)
+ {name: "ADDQconstcarry", argLength: 1, reg: gp11flags, typ: "(UInt64,Flags)", asm: "ADDQ", aux: "Int32", resultInArg0: true}, // r = arg0+auxint
+ {name: "ADCQconst", argLength: 2, reg: gp1flags1flags, typ: "(UInt64,Flags)", asm: "ADCQ", aux: "Int32", resultInArg0: true}, // r = arg0+auxint+carry(arg1)
+
+ // The following 4 add opcodes return the low 64 bits of the difference in the first result and
+ // the borrow (if the result is negative) in the carry flag.
+ {name: "SUBQborrow", argLength: 2, reg: gp21flags, typ: "(UInt64,Flags)", asm: "SUBQ", resultInArg0: true}, // r = arg0-arg1
+ {name: "SBBQ", argLength: 3, reg: gp2flags1flags, typ: "(UInt64,Flags)", asm: "SBBQ", resultInArg0: true}, // r = arg0-(arg1+carry(arg2))
+ {name: "SUBQconstborrow", argLength: 1, reg: gp11flags, typ: "(UInt64,Flags)", asm: "SUBQ", aux: "Int32", resultInArg0: true}, // r = arg0-auxint
+ {name: "SBBQconst", argLength: 2, reg: gp1flags1flags, typ: "(UInt64,Flags)", asm: "SBBQ", aux: "Int32", resultInArg0: true}, // r = arg0-(auxint+carry(arg1))
+
+ {name: "MULQU2", argLength: 2, reg: regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx, ax}}, commutative: true, asm: "MULQ", clobberFlags: true}, // arg0 * arg1, returns (hi, lo)
+ {name: "DIVQU2", argLength: 3, reg: regInfo{inputs: []regMask{dx, ax, gpsp}, outputs: []regMask{ax, dx}}, asm: "DIVQ", clobberFlags: true}, // arg0:arg1 / arg2 (128-bit divided by 64-bit), returns (q, r)
+
+ {name: "ANDQ", argLength: 2, reg: gp21, asm: "ANDQ", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 & arg1
+ {name: "ANDL", argLength: 2, reg: gp21, asm: "ANDL", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 & arg1
+ {name: "ANDQconst", argLength: 1, reg: gp11, asm: "ANDQ", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 & auxint
+ {name: "ANDLconst", argLength: 1, reg: gp11, asm: "ANDL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 & auxint
+ {name: "ANDQconstmodify", argLength: 2, reg: gpstoreconst, asm: "ANDQ", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // and ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "ANDLconstmodify", argLength: 2, reg: gpstoreconst, asm: "ANDL", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // and ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+
+ {name: "ORQ", argLength: 2, reg: gp21, asm: "ORQ", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 | arg1
+ {name: "ORL", argLength: 2, reg: gp21, asm: "ORL", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 | arg1
+ {name: "ORQconst", argLength: 1, reg: gp11, asm: "ORQ", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 | auxint
+ {name: "ORLconst", argLength: 1, reg: gp11, asm: "ORL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 | auxint
+ {name: "ORQconstmodify", argLength: 2, reg: gpstoreconst, asm: "ORQ", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // or ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "ORLconstmodify", argLength: 2, reg: gpstoreconst, asm: "ORL", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // or ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+
+ {name: "XORQ", argLength: 2, reg: gp21, asm: "XORQ", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 ^ arg1
+ {name: "XORL", argLength: 2, reg: gp21, asm: "XORL", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 ^ arg1
+ {name: "XORQconst", argLength: 1, reg: gp11, asm: "XORQ", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 ^ auxint
+ {name: "XORLconst", argLength: 1, reg: gp11, asm: "XORL", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 ^ auxint
+ {name: "XORQconstmodify", argLength: 2, reg: gpstoreconst, asm: "XORQ", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // xor ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "XORLconstmodify", argLength: 2, reg: gpstoreconst, asm: "XORL", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // xor ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+
+ {name: "CMPQ", argLength: 2, reg: gp2flags, asm: "CMPQ", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPL", argLength: 2, reg: gp2flags, asm: "CMPL", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPB", argLength: 2, reg: gp2flags, asm: "CMPB", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPQconst", argLength: 1, reg: gp1flags, asm: "CMPQ", typ: "Flags", aux: "Int32"}, // arg0 compare to auxint
+ {name: "CMPLconst", argLength: 1, reg: gp1flags, asm: "CMPL", typ: "Flags", aux: "Int32"}, // arg0 compare to auxint
+ {name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", typ: "Flags", aux: "Int16"}, // arg0 compare to auxint
+ {name: "CMPBconst", argLength: 1, reg: gp1flags, asm: "CMPB", typ: "Flags", aux: "Int8"}, // arg0 compare to auxint
+
+ // compare *(arg0+auxint+aux) to arg1 (in that order). arg2=mem.
+ {name: "CMPQload", argLength: 3, reg: gp1flagsLoad, asm: "CMPQ", aux: "SymOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPLload", argLength: 3, reg: gp1flagsLoad, asm: "CMPL", aux: "SymOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPWload", argLength: 3, reg: gp1flagsLoad, asm: "CMPW", aux: "SymOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPBload", argLength: 3, reg: gp1flagsLoad, asm: "CMPB", aux: "SymOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+
+ // compare *(arg0+ValAndOff(AuxInt).Off()+aux) to ValAndOff(AuxInt).Val() (in that order). arg1=mem.
+ {name: "CMPQconstload", argLength: 2, reg: gp0flagsLoad, asm: "CMPQ", aux: "SymValAndOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPLconstload", argLength: 2, reg: gp0flagsLoad, asm: "CMPL", aux: "SymValAndOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPWconstload", argLength: 2, reg: gp0flagsLoad, asm: "CMPW", aux: "SymValAndOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPBconstload", argLength: 2, reg: gp0flagsLoad, asm: "CMPB", aux: "SymValAndOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+
+ // compare *(arg0+N*arg1+auxint+aux) to arg2 (in that order). arg3=mem.
+ {name: "CMPQloadidx8", argLength: 4, reg: gp2flagsLoad, asm: "CMPQ", scale: 8, aux: "SymOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPQloadidx1", argLength: 4, reg: gp2flagsLoad, asm: "CMPQ", scale: 1, commutative: true, aux: "SymOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPLloadidx4", argLength: 4, reg: gp2flagsLoad, asm: "CMPL", scale: 4, aux: "SymOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPLloadidx1", argLength: 4, reg: gp2flagsLoad, asm: "CMPL", scale: 1, commutative: true, aux: "SymOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPWloadidx2", argLength: 4, reg: gp2flagsLoad, asm: "CMPW", scale: 2, aux: "SymOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPWloadidx1", argLength: 4, reg: gp2flagsLoad, asm: "CMPW", scale: 1, commutative: true, aux: "SymOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPBloadidx1", argLength: 4, reg: gp2flagsLoad, asm: "CMPB", scale: 1, commutative: true, aux: "SymOff", typ: "Flags", symEffect: "Read"},
+
+ // compare *(arg0+N*arg1+ValAndOff(AuxInt).Off()+aux) to ValAndOff(AuxInt).Val() (in that order). arg2=mem.
+ {name: "CMPQconstloadidx8", argLength: 3, reg: gp1flagsLoad, asm: "CMPQ", scale: 8, aux: "SymValAndOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPQconstloadidx1", argLength: 3, reg: gp1flagsLoad, asm: "CMPQ", scale: 1, commutative: true, aux: "SymValAndOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPLconstloadidx4", argLength: 3, reg: gp1flagsLoad, asm: "CMPL", scale: 4, aux: "SymValAndOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPLconstloadidx1", argLength: 3, reg: gp1flagsLoad, asm: "CMPL", scale: 1, commutative: true, aux: "SymValAndOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPWconstloadidx2", argLength: 3, reg: gp1flagsLoad, asm: "CMPW", scale: 2, aux: "SymValAndOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPWconstloadidx1", argLength: 3, reg: gp1flagsLoad, asm: "CMPW", scale: 1, commutative: true, aux: "SymValAndOff", typ: "Flags", symEffect: "Read"},
+ {name: "CMPBconstloadidx1", argLength: 3, reg: gp1flagsLoad, asm: "CMPB", scale: 1, commutative: true, aux: "SymValAndOff", typ: "Flags", symEffect: "Read"},
+
+ {name: "UCOMISS", argLength: 2, reg: fp2flags, asm: "UCOMISS", typ: "Flags"}, // arg0 compare to arg1, f32
+ {name: "UCOMISD", argLength: 2, reg: fp2flags, asm: "UCOMISD", typ: "Flags"}, // arg0 compare to arg1, f64
+
+ {name: "BTL", argLength: 2, reg: gp2flags, asm: "BTL", typ: "Flags"}, // test whether bit arg0%32 in arg1 is set
+ {name: "BTQ", argLength: 2, reg: gp2flags, asm: "BTQ", typ: "Flags"}, // test whether bit arg0%64 in arg1 is set
+ {name: "BTCL", argLength: 2, reg: gp21, asm: "BTCL", resultInArg0: true, clobberFlags: true}, // complement bit arg1%32 in arg0
+ {name: "BTCQ", argLength: 2, reg: gp21, asm: "BTCQ", resultInArg0: true, clobberFlags: true}, // complement bit arg1%64 in arg0
+ {name: "BTRL", argLength: 2, reg: gp21, asm: "BTRL", resultInArg0: true, clobberFlags: true}, // reset bit arg1%32 in arg0
+ {name: "BTRQ", argLength: 2, reg: gp21, asm: "BTRQ", resultInArg0: true, clobberFlags: true}, // reset bit arg1%64 in arg0
+ {name: "BTSL", argLength: 2, reg: gp21, asm: "BTSL", resultInArg0: true, clobberFlags: true}, // set bit arg1%32 in arg0
+ {name: "BTSQ", argLength: 2, reg: gp21, asm: "BTSQ", resultInArg0: true, clobberFlags: true}, // set bit arg1%64 in arg0
+ {name: "BTLconst", argLength: 1, reg: gp1flags, asm: "BTL", typ: "Flags", aux: "Int8"}, // test whether bit auxint in arg0 is set, 0 <= auxint < 32
+ {name: "BTQconst", argLength: 1, reg: gp1flags, asm: "BTQ", typ: "Flags", aux: "Int8"}, // test whether bit auxint in arg0 is set, 0 <= auxint < 64
+ {name: "BTCLconst", argLength: 1, reg: gp11, asm: "BTCL", resultInArg0: true, clobberFlags: true, aux: "Int8"}, // complement bit auxint in arg0, 0 <= auxint < 32
+ {name: "BTCQconst", argLength: 1, reg: gp11, asm: "BTCQ", resultInArg0: true, clobberFlags: true, aux: "Int8"}, // complement bit auxint in arg0, 0 <= auxint < 64
+ {name: "BTRLconst", argLength: 1, reg: gp11, asm: "BTRL", resultInArg0: true, clobberFlags: true, aux: "Int8"}, // reset bit auxint in arg0, 0 <= auxint < 32
+ {name: "BTRQconst", argLength: 1, reg: gp11, asm: "BTRQ", resultInArg0: true, clobberFlags: true, aux: "Int8"}, // reset bit auxint in arg0, 0 <= auxint < 64
+ {name: "BTSLconst", argLength: 1, reg: gp11, asm: "BTSL", resultInArg0: true, clobberFlags: true, aux: "Int8"}, // set bit auxint in arg0, 0 <= auxint < 32
+ {name: "BTSQconst", argLength: 1, reg: gp11, asm: "BTSQ", resultInArg0: true, clobberFlags: true, aux: "Int8"}, // set bit auxint in arg0, 0 <= auxint < 64
+
+ // direct bit operation on memory operand
+ //
+ // Note that these operations do not mask the bit offset (arg1), and will write beyond their expected
+ // bounds if that argument is larger than 64/32 (for BT*Q and BT*L, respectively). If the compiler
+ // cannot prove that arg1 is in range, it must be explicitly masked (see e.g. the patterns that produce
+ // BT*modify from (MOVstore (BT* (MOVLload ptr mem) x) mem)).
+ {name: "BTCQmodify", argLength: 3, reg: gpstore, asm: "BTCQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // complement bit arg1 in 64-bit arg0+auxint+aux, arg2=mem
+ {name: "BTCLmodify", argLength: 3, reg: gpstore, asm: "BTCL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // complement bit arg1 in 32-bit arg0+auxint+aux, arg2=mem
+ {name: "BTSQmodify", argLength: 3, reg: gpstore, asm: "BTSQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // set bit arg1 in 64-bit arg0+auxint+aux, arg2=mem
+ {name: "BTSLmodify", argLength: 3, reg: gpstore, asm: "BTSL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // set bit arg1 in 32-bit arg0+auxint+aux, arg2=mem
+ {name: "BTRQmodify", argLength: 3, reg: gpstore, asm: "BTRQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // reset bit arg1 in 64-bit arg0+auxint+aux, arg2=mem
+ {name: "BTRLmodify", argLength: 3, reg: gpstore, asm: "BTRL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // reset bit arg1 in 32-bit arg0+auxint+aux, arg2=mem
+ {name: "BTCQconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTCQ", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // complement bit ValAndOff(AuxInt).Val() in 64-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "BTCLconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTCL", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // complement bit ValAndOff(AuxInt).Val() in 32-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "BTSQconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTSQ", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // set bit ValAndOff(AuxInt).Val() in 64-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "BTSLconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTSL", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // set bit ValAndOff(AuxInt).Val() in 32-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "BTRQconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTRQ", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // reset bit ValAndOff(AuxInt).Val() in 64-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "BTRLconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTRL", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // reset bit ValAndOff(AuxInt).Val() in 32-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+
+ {name: "TESTQ", argLength: 2, reg: gp2flags, commutative: true, asm: "TESTQ", typ: "Flags"}, // (arg0 & arg1) compare to 0
+ {name: "TESTL", argLength: 2, reg: gp2flags, commutative: true, asm: "TESTL", typ: "Flags"}, // (arg0 & arg1) compare to 0
+ {name: "TESTW", argLength: 2, reg: gp2flags, commutative: true, asm: "TESTW", typ: "Flags"}, // (arg0 & arg1) compare to 0
+ {name: "TESTB", argLength: 2, reg: gp2flags, commutative: true, asm: "TESTB", typ: "Flags"}, // (arg0 & arg1) compare to 0
+ {name: "TESTQconst", argLength: 1, reg: gp1flags, asm: "TESTQ", typ: "Flags", aux: "Int32"}, // (arg0 & auxint) compare to 0
+ {name: "TESTLconst", argLength: 1, reg: gp1flags, asm: "TESTL", typ: "Flags", aux: "Int32"}, // (arg0 & auxint) compare to 0
+ {name: "TESTWconst", argLength: 1, reg: gp1flags, asm: "TESTW", typ: "Flags", aux: "Int16"}, // (arg0 & auxint) compare to 0
+ {name: "TESTBconst", argLength: 1, reg: gp1flags, asm: "TESTB", typ: "Flags", aux: "Int8"}, // (arg0 & auxint) compare to 0
+
+ {name: "SHLQ", argLength: 2, reg: gp21shift, asm: "SHLQ", resultInArg0: true, clobberFlags: true}, // arg0 << arg1, shift amount is mod 64
+ {name: "SHLL", argLength: 2, reg: gp21shift, asm: "SHLL", resultInArg0: true, clobberFlags: true}, // arg0 << arg1, shift amount is mod 32
+ {name: "SHLQconst", argLength: 1, reg: gp11, asm: "SHLQ", aux: "Int8", resultInArg0: true, clobberFlags: true}, // arg0 << auxint, shift amount 0-63
+ {name: "SHLLconst", argLength: 1, reg: gp11, asm: "SHLL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // 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", argLength: 2, reg: gp21shift, asm: "SHRQ", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> arg1, shift amount is mod 64
+ {name: "SHRL", argLength: 2, reg: gp21shift, asm: "SHRL", resultInArg0: true, clobberFlags: true}, // unsigned uint32(arg0) >> arg1, shift amount is mod 32
+ {name: "SHRW", argLength: 2, reg: gp21shift, asm: "SHRW", resultInArg0: true, clobberFlags: true}, // unsigned uint16(arg0) >> arg1, shift amount is mod 32
+ {name: "SHRB", argLength: 2, reg: gp21shift, asm: "SHRB", resultInArg0: true, clobberFlags: true}, // unsigned uint8(arg0) >> arg1, shift amount is mod 32
+ {name: "SHRQconst", argLength: 1, reg: gp11, asm: "SHRQ", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-63
+ {name: "SHRLconst", argLength: 1, reg: gp11, asm: "SHRL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned uint32(arg0) >> auxint, shift amount 0-31
+ {name: "SHRWconst", argLength: 1, reg: gp11, asm: "SHRW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned uint16(arg0) >> auxint, shift amount 0-15
+ {name: "SHRBconst", argLength: 1, reg: gp11, asm: "SHRB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned uint8(arg0) >> auxint, shift amount 0-7
+
+ {name: "SARQ", argLength: 2, reg: gp21shift, asm: "SARQ", resultInArg0: true, clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 64
+ {name: "SARL", argLength: 2, reg: gp21shift, asm: "SARL", resultInArg0: true, clobberFlags: true}, // signed int32(arg0) >> arg1, shift amount is mod 32
+ {name: "SARW", argLength: 2, reg: gp21shift, asm: "SARW", resultInArg0: true, clobberFlags: true}, // signed int16(arg0) >> arg1, shift amount is mod 32
+ {name: "SARB", argLength: 2, reg: gp21shift, asm: "SARB", resultInArg0: true, clobberFlags: true}, // signed int8(arg0) >> arg1, shift amount is mod 32
+ {name: "SARQconst", argLength: 1, reg: gp11, asm: "SARQ", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-63
+ {name: "SARLconst", argLength: 1, reg: gp11, asm: "SARL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed int32(arg0) >> auxint, shift amount 0-31
+ {name: "SARWconst", argLength: 1, reg: gp11, asm: "SARW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed int16(arg0) >> auxint, shift amount 0-15
+ {name: "SARBconst", argLength: 1, reg: gp11, asm: "SARB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed int8(arg0) >> auxint, shift amount 0-7
+
+ {name: "ROLQ", argLength: 2, reg: gp21shift, asm: "ROLQ", resultInArg0: true, clobberFlags: true}, // arg0 rotate left arg1 bits.
+ {name: "ROLL", argLength: 2, reg: gp21shift, asm: "ROLL", resultInArg0: true, clobberFlags: true}, // arg0 rotate left arg1 bits.
+ {name: "ROLW", argLength: 2, reg: gp21shift, asm: "ROLW", resultInArg0: true, clobberFlags: true}, // arg0 rotate left arg1 bits.
+ {name: "ROLB", argLength: 2, reg: gp21shift, asm: "ROLB", resultInArg0: true, clobberFlags: true}, // arg0 rotate left arg1 bits.
+ {name: "RORQ", argLength: 2, reg: gp21shift, asm: "RORQ", resultInArg0: true, clobberFlags: true}, // arg0 rotate right arg1 bits.
+ {name: "RORL", argLength: 2, reg: gp21shift, asm: "RORL", resultInArg0: true, clobberFlags: true}, // arg0 rotate right arg1 bits.
+ {name: "RORW", argLength: 2, reg: gp21shift, asm: "RORW", resultInArg0: true, clobberFlags: true}, // arg0 rotate right arg1 bits.
+ {name: "RORB", argLength: 2, reg: gp21shift, asm: "RORB", resultInArg0: true, clobberFlags: true}, // arg0 rotate right arg1 bits.
+ {name: "ROLQconst", argLength: 1, reg: gp11, asm: "ROLQ", aux: "Int8", resultInArg0: true, clobberFlags: true}, // arg0 rotate left auxint, rotate amount 0-63
+ {name: "ROLLconst", argLength: 1, reg: gp11, asm: "ROLL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // arg0 rotate left auxint, rotate amount 0-31
+ {name: "ROLWconst", argLength: 1, reg: gp11, asm: "ROLW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // arg0 rotate left auxint, rotate amount 0-15
+ {name: "ROLBconst", argLength: 1, reg: gp11, asm: "ROLB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // arg0 rotate left auxint, rotate amount 0-7
+
+ {name: "ADDLload", argLength: 3, reg: gp21load, asm: "ADDL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 + tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "ADDQload", argLength: 3, reg: gp21load, asm: "ADDQ", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 + tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "SUBQload", argLength: 3, reg: gp21load, asm: "SUBQ", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 - tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "SUBLload", argLength: 3, reg: gp21load, asm: "SUBL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 - tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "ANDLload", argLength: 3, reg: gp21load, asm: "ANDL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 & tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "ANDQload", argLength: 3, reg: gp21load, asm: "ANDQ", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 & tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "ORQload", argLength: 3, reg: gp21load, asm: "ORQ", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 | tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "ORLload", argLength: 3, reg: gp21load, asm: "ORL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 | tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "XORQload", argLength: 3, reg: gp21load, asm: "XORQ", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 ^ tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+ {name: "XORLload", argLength: 3, reg: gp21load, asm: "XORL", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 ^ tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+
+ {name: "ADDLloadidx1", argLength: 4, reg: gp21loadidx, asm: "ADDL", scale: 1, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 + tmp, tmp loaded from arg1+ arg2+auxint+aux, arg3 = mem
+ {name: "ADDLloadidx4", argLength: 4, reg: gp21loadidx, asm: "ADDL", scale: 4, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 + tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "ADDLloadidx8", argLength: 4, reg: gp21loadidx, asm: "ADDL", scale: 8, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 + tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "ADDQloadidx1", argLength: 4, reg: gp21loadidx, asm: "ADDQ", scale: 1, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 + tmp, tmp loaded from arg1+ arg2+auxint+aux, arg3 = mem
+ {name: "ADDQloadidx8", argLength: 4, reg: gp21loadidx, asm: "ADDQ", scale: 8, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 + tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "SUBLloadidx1", argLength: 4, reg: gp21loadidx, asm: "SUBL", scale: 1, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 - tmp, tmp loaded from arg1+ arg2+auxint+aux, arg3 = mem
+ {name: "SUBLloadidx4", argLength: 4, reg: gp21loadidx, asm: "SUBL", scale: 4, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 - tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "SUBLloadidx8", argLength: 4, reg: gp21loadidx, asm: "SUBL", scale: 8, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 - tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "SUBQloadidx1", argLength: 4, reg: gp21loadidx, asm: "SUBQ", scale: 1, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 - tmp, tmp loaded from arg1+ arg2+auxint+aux, arg3 = mem
+ {name: "SUBQloadidx8", argLength: 4, reg: gp21loadidx, asm: "SUBQ", scale: 8, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 - tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "ANDLloadidx1", argLength: 4, reg: gp21loadidx, asm: "ANDL", scale: 1, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 & tmp, tmp loaded from arg1+ arg2+auxint+aux, arg3 = mem
+ {name: "ANDLloadidx4", argLength: 4, reg: gp21loadidx, asm: "ANDL", scale: 4, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 & tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "ANDLloadidx8", argLength: 4, reg: gp21loadidx, asm: "ANDL", scale: 8, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 & tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "ANDQloadidx1", argLength: 4, reg: gp21loadidx, asm: "ANDQ", scale: 1, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 & tmp, tmp loaded from arg1+ arg2+auxint+aux, arg3 = mem
+ {name: "ANDQloadidx8", argLength: 4, reg: gp21loadidx, asm: "ANDQ", scale: 8, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 & tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "ORLloadidx1", argLength: 4, reg: gp21loadidx, asm: "ORL", scale: 1, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 | tmp, tmp loaded from arg1+ arg2+auxint+aux, arg3 = mem
+ {name: "ORLloadidx4", argLength: 4, reg: gp21loadidx, asm: "ORL", scale: 4, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 | tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "ORLloadidx8", argLength: 4, reg: gp21loadidx, asm: "ORL", scale: 8, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 | tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "ORQloadidx1", argLength: 4, reg: gp21loadidx, asm: "ORQ", scale: 1, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 | tmp, tmp loaded from arg1+ arg2+auxint+aux, arg3 = mem
+ {name: "ORQloadidx8", argLength: 4, reg: gp21loadidx, asm: "ORQ", scale: 8, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 | tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "XORLloadidx1", argLength: 4, reg: gp21loadidx, asm: "XORL", scale: 1, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 ^ tmp, tmp loaded from arg1+ arg2+auxint+aux, arg3 = mem
+ {name: "XORLloadidx4", argLength: 4, reg: gp21loadidx, asm: "XORL", scale: 4, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 ^ tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "XORLloadidx8", argLength: 4, reg: gp21loadidx, asm: "XORL", scale: 8, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 ^ tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "XORQloadidx1", argLength: 4, reg: gp21loadidx, asm: "XORQ", scale: 1, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 ^ tmp, tmp loaded from arg1+ arg2+auxint+aux, arg3 = mem
+ {name: "XORQloadidx8", argLength: 4, reg: gp21loadidx, asm: "XORQ", scale: 8, aux: "SymOff", resultInArg0: true, clobberFlags: true, symEffect: "Read"}, // arg0 ^ tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+
+ // direct binary-op on memory (read-modify-write)
+ {name: "ADDQmodify", argLength: 3, reg: gpstore, asm: "ADDQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) += arg1, arg2=mem
+ {name: "SUBQmodify", argLength: 3, reg: gpstore, asm: "SUBQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) -= arg1, arg2=mem
+ {name: "ANDQmodify", argLength: 3, reg: gpstore, asm: "ANDQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) &= arg1, arg2=mem
+ {name: "ORQmodify", argLength: 3, reg: gpstore, asm: "ORQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) |= arg1, arg2=mem
+ {name: "XORQmodify", argLength: 3, reg: gpstore, asm: "XORQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) ^= arg1, arg2=mem
+ {name: "ADDLmodify", argLength: 3, reg: gpstore, asm: "ADDL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) += arg1, arg2=mem
+ {name: "SUBLmodify", argLength: 3, reg: gpstore, asm: "SUBL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) -= arg1, arg2=mem
+ {name: "ANDLmodify", argLength: 3, reg: gpstore, asm: "ANDL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) &= arg1, arg2=mem
+ {name: "ORLmodify", argLength: 3, reg: gpstore, asm: "ORL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) |= arg1, arg2=mem
+ {name: "XORLmodify", argLength: 3, reg: gpstore, asm: "XORL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) ^= arg1, arg2=mem
+
+ {name: "ADDQmodifyidx1", argLength: 4, reg: gpstoreidx, asm: "ADDQ", scale: 1, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+auxint+aux) += arg2, arg3=mem
+ {name: "ADDQmodifyidx8", argLength: 4, reg: gpstoreidx, asm: "ADDQ", scale: 8, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+auxint+aux) += arg2, arg3=mem
+ {name: "SUBQmodifyidx1", argLength: 4, reg: gpstoreidx, asm: "SUBQ", scale: 1, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+auxint+aux) -= arg2, arg3=mem
+ {name: "SUBQmodifyidx8", argLength: 4, reg: gpstoreidx, asm: "SUBQ", scale: 8, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+auxint+aux) -= arg2, arg3=mem
+ {name: "ANDQmodifyidx1", argLength: 4, reg: gpstoreidx, asm: "ANDQ", scale: 1, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+auxint+aux) &= arg2, arg3=mem
+ {name: "ANDQmodifyidx8", argLength: 4, reg: gpstoreidx, asm: "ANDQ", scale: 8, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+auxint+aux) &= arg2, arg3=mem
+ {name: "ORQmodifyidx1", argLength: 4, reg: gpstoreidx, asm: "ORQ", scale: 1, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+auxint+aux) |= arg2, arg3=mem
+ {name: "ORQmodifyidx8", argLength: 4, reg: gpstoreidx, asm: "ORQ", scale: 8, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+auxint+aux) |= arg2, arg3=mem
+ {name: "XORQmodifyidx1", argLength: 4, reg: gpstoreidx, asm: "XORQ", scale: 1, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+auxint+aux) ^= arg2, arg3=mem
+ {name: "XORQmodifyidx8", argLength: 4, reg: gpstoreidx, asm: "XORQ", scale: 8, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+auxint+aux) ^= arg2, arg3=mem
+ {name: "ADDLmodifyidx1", argLength: 4, reg: gpstoreidx, asm: "ADDL", scale: 1, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+auxint+aux) += arg2, arg3=mem
+ {name: "ADDLmodifyidx4", argLength: 4, reg: gpstoreidx, asm: "ADDL", scale: 4, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+4*arg1+auxint+aux) += arg2, arg3=mem
+ {name: "ADDLmodifyidx8", argLength: 4, reg: gpstoreidx, asm: "ADDL", scale: 8, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+auxint+aux) += arg2, arg3=mem
+ {name: "SUBLmodifyidx1", argLength: 4, reg: gpstoreidx, asm: "SUBL", scale: 1, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+auxint+aux) -= arg2, arg3=mem
+ {name: "SUBLmodifyidx4", argLength: 4, reg: gpstoreidx, asm: "SUBL", scale: 4, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+4*arg1+auxint+aux) -= arg2, arg3=mem
+ {name: "SUBLmodifyidx8", argLength: 4, reg: gpstoreidx, asm: "SUBL", scale: 8, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+auxint+aux) -= arg2, arg3=mem
+ {name: "ANDLmodifyidx1", argLength: 4, reg: gpstoreidx, asm: "ANDL", scale: 1, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+auxint+aux) &= arg2, arg3=mem
+ {name: "ANDLmodifyidx4", argLength: 4, reg: gpstoreidx, asm: "ANDL", scale: 4, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+4*arg1+auxint+aux) &= arg2, arg3=mem
+ {name: "ANDLmodifyidx8", argLength: 4, reg: gpstoreidx, asm: "ANDL", scale: 8, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+auxint+aux) &= arg2, arg3=mem
+ {name: "ORLmodifyidx1", argLength: 4, reg: gpstoreidx, asm: "ORL", scale: 1, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+auxint+aux) |= arg2, arg3=mem
+ {name: "ORLmodifyidx4", argLength: 4, reg: gpstoreidx, asm: "ORL", scale: 4, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+4*arg1+auxint+aux) |= arg2, arg3=mem
+ {name: "ORLmodifyidx8", argLength: 4, reg: gpstoreidx, asm: "ORL", scale: 8, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+auxint+aux) |= arg2, arg3=mem
+ {name: "XORLmodifyidx1", argLength: 4, reg: gpstoreidx, asm: "XORL", scale: 1, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+auxint+aux) ^= arg2, arg3=mem
+ {name: "XORLmodifyidx4", argLength: 4, reg: gpstoreidx, asm: "XORL", scale: 4, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+4*arg1+auxint+aux) ^= arg2, arg3=mem
+ {name: "XORLmodifyidx8", argLength: 4, reg: gpstoreidx, asm: "XORL", scale: 8, aux: "SymOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+auxint+aux) ^= arg2, arg3=mem
+
+ {name: "ADDQconstmodifyidx1", argLength: 3, reg: gpstoreconstidx, asm: "ADDQ", scale: 1, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+ValAndOff(AuxInt).Off()+aux) += ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ADDQconstmodifyidx8", argLength: 3, reg: gpstoreconstidx, asm: "ADDQ", scale: 8, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+ValAndOff(AuxInt).Off()+aux) += ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ANDQconstmodifyidx1", argLength: 3, reg: gpstoreconstidx, asm: "ANDQ", scale: 1, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+ValAndOff(AuxInt).Off()+aux) &= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ANDQconstmodifyidx8", argLength: 3, reg: gpstoreconstidx, asm: "ANDQ", scale: 8, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+ValAndOff(AuxInt).Off()+aux) &= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ORQconstmodifyidx1", argLength: 3, reg: gpstoreconstidx, asm: "ORQ", scale: 1, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+ValAndOff(AuxInt).Off()+aux) |= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ORQconstmodifyidx8", argLength: 3, reg: gpstoreconstidx, asm: "ORQ", scale: 8, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+ValAndOff(AuxInt).Off()+aux) |= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "XORQconstmodifyidx1", argLength: 3, reg: gpstoreconstidx, asm: "XORQ", scale: 1, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+ValAndOff(AuxInt).Off()+aux) ^= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "XORQconstmodifyidx8", argLength: 3, reg: gpstoreconstidx, asm: "XORQ", scale: 8, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+ValAndOff(AuxInt).Off()+aux) ^= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ADDLconstmodifyidx1", argLength: 3, reg: gpstoreconstidx, asm: "ADDL", scale: 1, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+ValAndOff(AuxInt).Off()+aux) += ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ADDLconstmodifyidx4", argLength: 3, reg: gpstoreconstidx, asm: "ADDL", scale: 4, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+4*arg1+ValAndOff(AuxInt).Off()+aux) += ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ADDLconstmodifyidx8", argLength: 3, reg: gpstoreconstidx, asm: "ADDL", scale: 8, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+ValAndOff(AuxInt).Off()+aux) += ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ANDLconstmodifyidx1", argLength: 3, reg: gpstoreconstidx, asm: "ANDL", scale: 1, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+ValAndOff(AuxInt).Off()+aux) &= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ANDLconstmodifyidx4", argLength: 3, reg: gpstoreconstidx, asm: "ANDL", scale: 4, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+4*arg1+ValAndOff(AuxInt).Off()+aux) &= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ANDLconstmodifyidx8", argLength: 3, reg: gpstoreconstidx, asm: "ANDL", scale: 8, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+ValAndOff(AuxInt).Off()+aux) &= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ORLconstmodifyidx1", argLength: 3, reg: gpstoreconstidx, asm: "ORL", scale: 1, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+ValAndOff(AuxInt).Off()+aux) |= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ORLconstmodifyidx4", argLength: 3, reg: gpstoreconstidx, asm: "ORL", scale: 4, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+4*arg1+ValAndOff(AuxInt).Off()+aux) |= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "ORLconstmodifyidx8", argLength: 3, reg: gpstoreconstidx, asm: "ORL", scale: 8, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+ValAndOff(AuxInt).Off()+aux) |= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "XORLconstmodifyidx1", argLength: 3, reg: gpstoreconstidx, asm: "XORL", scale: 1, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+1*arg1+ValAndOff(AuxInt).Off()+aux) ^= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "XORLconstmodifyidx4", argLength: 3, reg: gpstoreconstidx, asm: "XORL", scale: 4, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+4*arg1+ValAndOff(AuxInt).Off()+aux) ^= ValAndOff(AuxInt).Val(), arg2=mem
+ {name: "XORLconstmodifyidx8", argLength: 3, reg: gpstoreconstidx, asm: "XORL", scale: 8, aux: "SymValAndOff", typ: "Mem", clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+8*arg1+ValAndOff(AuxInt).Off()+aux) ^= ValAndOff(AuxInt).Val(), arg2=mem
+
+ // unary ops
+ {name: "NEGQ", argLength: 1, reg: gp11, asm: "NEGQ", resultInArg0: true, clobberFlags: true}, // -arg0
+ {name: "NEGL", argLength: 1, reg: gp11, asm: "NEGL", resultInArg0: true, clobberFlags: true}, // -arg0
+
+ {name: "NOTQ", argLength: 1, reg: gp11, asm: "NOTQ", resultInArg0: true, clobberFlags: true}, // ^arg0
+ {name: "NOTL", argLength: 1, reg: gp11, asm: "NOTL", resultInArg0: true, clobberFlags: true}, // ^arg0
+
+ // BS{F,R}Q returns a tuple [result, flags]
+ // result is undefined if the input is zero.
+ // flags are set to "equal" if the input is zero, "not equal" otherwise.
+ // BS{F,R}L returns only the result.
+ {name: "BSFQ", argLength: 1, reg: gp11flags, asm: "BSFQ", typ: "(UInt64,Flags)"}, // # of low-order zeroes in 64-bit arg
+ {name: "BSFL", argLength: 1, reg: gp11, asm: "BSFL", typ: "UInt32", clobberFlags: true}, // # of low-order zeroes in 32-bit arg
+ {name: "BSRQ", argLength: 1, reg: gp11flags, asm: "BSRQ", typ: "(UInt64,Flags)"}, // # of high-order zeroes in 64-bit arg
+ {name: "BSRL", argLength: 1, reg: gp11, asm: "BSRL", typ: "UInt32", clobberFlags: true}, // # of high-order zeroes in 32-bit arg
+
+ // CMOV instructions: 64, 32 and 16-bit sizes.
+ // if arg2 encodes a true result, return arg1, else arg0
+ {name: "CMOVQEQ", argLength: 3, reg: gp21, asm: "CMOVQEQ", resultInArg0: true},
+ {name: "CMOVQNE", argLength: 3, reg: gp21, asm: "CMOVQNE", resultInArg0: true},
+ {name: "CMOVQLT", argLength: 3, reg: gp21, asm: "CMOVQLT", resultInArg0: true},
+ {name: "CMOVQGT", argLength: 3, reg: gp21, asm: "CMOVQGT", resultInArg0: true},
+ {name: "CMOVQLE", argLength: 3, reg: gp21, asm: "CMOVQLE", resultInArg0: true},
+ {name: "CMOVQGE", argLength: 3, reg: gp21, asm: "CMOVQGE", resultInArg0: true},
+ {name: "CMOVQLS", argLength: 3, reg: gp21, asm: "CMOVQLS", resultInArg0: true},
+ {name: "CMOVQHI", argLength: 3, reg: gp21, asm: "CMOVQHI", resultInArg0: true},
+ {name: "CMOVQCC", argLength: 3, reg: gp21, asm: "CMOVQCC", resultInArg0: true},
+ {name: "CMOVQCS", argLength: 3, reg: gp21, asm: "CMOVQCS", resultInArg0: true},
+
+ {name: "CMOVLEQ", argLength: 3, reg: gp21, asm: "CMOVLEQ", resultInArg0: true},
+ {name: "CMOVLNE", argLength: 3, reg: gp21, asm: "CMOVLNE", resultInArg0: true},
+ {name: "CMOVLLT", argLength: 3, reg: gp21, asm: "CMOVLLT", resultInArg0: true},
+ {name: "CMOVLGT", argLength: 3, reg: gp21, asm: "CMOVLGT", resultInArg0: true},
+ {name: "CMOVLLE", argLength: 3, reg: gp21, asm: "CMOVLLE", resultInArg0: true},
+ {name: "CMOVLGE", argLength: 3, reg: gp21, asm: "CMOVLGE", resultInArg0: true},
+ {name: "CMOVLLS", argLength: 3, reg: gp21, asm: "CMOVLLS", resultInArg0: true},
+ {name: "CMOVLHI", argLength: 3, reg: gp21, asm: "CMOVLHI", resultInArg0: true},
+ {name: "CMOVLCC", argLength: 3, reg: gp21, asm: "CMOVLCC", resultInArg0: true},
+ {name: "CMOVLCS", argLength: 3, reg: gp21, asm: "CMOVLCS", resultInArg0: true},
+
+ {name: "CMOVWEQ", argLength: 3, reg: gp21, asm: "CMOVWEQ", resultInArg0: true},
+ {name: "CMOVWNE", argLength: 3, reg: gp21, asm: "CMOVWNE", resultInArg0: true},
+ {name: "CMOVWLT", argLength: 3, reg: gp21, asm: "CMOVWLT", resultInArg0: true},
+ {name: "CMOVWGT", argLength: 3, reg: gp21, asm: "CMOVWGT", resultInArg0: true},
+ {name: "CMOVWLE", argLength: 3, reg: gp21, asm: "CMOVWLE", resultInArg0: true},
+ {name: "CMOVWGE", argLength: 3, reg: gp21, asm: "CMOVWGE", resultInArg0: true},
+ {name: "CMOVWLS", argLength: 3, reg: gp21, asm: "CMOVWLS", resultInArg0: true},
+ {name: "CMOVWHI", argLength: 3, reg: gp21, asm: "CMOVWHI", resultInArg0: true},
+ {name: "CMOVWCC", argLength: 3, reg: gp21, asm: "CMOVWCC", resultInArg0: true},
+ {name: "CMOVWCS", argLength: 3, reg: gp21, asm: "CMOVWCS", resultInArg0: true},
+
+ // CMOV with floating point instructions. We need separate pseudo-op to handle
+ // InvertFlags correctly, and to generate special code that handles NaN (unordered flag).
+ // NOTE: the fact that CMOV*EQF here is marked to generate CMOV*NE is not a bug. See
+ // code generation in amd64/ssa.go.
+ {name: "CMOVQEQF", argLength: 3, reg: gp21pax, asm: "CMOVQNE", resultInArg0: true},
+ {name: "CMOVQNEF", argLength: 3, reg: gp21, asm: "CMOVQNE", resultInArg0: true},
+ {name: "CMOVQGTF", argLength: 3, reg: gp21, asm: "CMOVQHI", resultInArg0: true},
+ {name: "CMOVQGEF", argLength: 3, reg: gp21, asm: "CMOVQCC", resultInArg0: true},
+ {name: "CMOVLEQF", argLength: 3, reg: gp21pax, asm: "CMOVLNE", resultInArg0: true},
+ {name: "CMOVLNEF", argLength: 3, reg: gp21, asm: "CMOVLNE", resultInArg0: true},
+ {name: "CMOVLGTF", argLength: 3, reg: gp21, asm: "CMOVLHI", resultInArg0: true},
+ {name: "CMOVLGEF", argLength: 3, reg: gp21, asm: "CMOVLCC", resultInArg0: true},
+ {name: "CMOVWEQF", argLength: 3, reg: gp21pax, asm: "CMOVWNE", resultInArg0: true},
+ {name: "CMOVWNEF", argLength: 3, reg: gp21, asm: "CMOVWNE", resultInArg0: true},
+ {name: "CMOVWGTF", argLength: 3, reg: gp21, asm: "CMOVWHI", resultInArg0: true},
+ {name: "CMOVWGEF", argLength: 3, reg: gp21, asm: "CMOVWCC", resultInArg0: true},
+
+ {name: "BSWAPQ", argLength: 1, reg: gp11, asm: "BSWAPQ", resultInArg0: true, clobberFlags: true}, // arg0 swap bytes
+ {name: "BSWAPL", argLength: 1, reg: gp11, asm: "BSWAPL", resultInArg0: true, clobberFlags: true}, // arg0 swap bytes
+
+ // POPCNT instructions aren't guaranteed to be on the target platform (they are SSE4).
+ // Any use must be preceded by a successful check of runtime.x86HasPOPCNT.
+ {name: "POPCNTQ", argLength: 1, reg: gp11, asm: "POPCNTQ", clobberFlags: true}, // count number of set bits in arg0
+ {name: "POPCNTL", argLength: 1, reg: gp11, asm: "POPCNTL", clobberFlags: true}, // count number of set bits in arg0
+
+ {name: "SQRTSD", argLength: 1, reg: fp11, asm: "SQRTSD"}, // sqrt(arg0)
+
+ // ROUNDSD instruction isn't guaranteed to be on the target platform (it is SSE4.1)
+ // Any use must be preceded by a successful check of runtime.x86HasSSE41.
+ {name: "ROUNDSD", argLength: 1, reg: fp11, aux: "Int8", asm: "ROUNDSD"}, // rounds arg0 depending on auxint, 1 means math.Floor, 2 Ceil, 3 Trunc
+
+ // VFMADD231SD only exists on platforms with the FMA3 instruction set.
+ // Any use must be preceded by a successful check of runtime.support_fma.
+ {name: "VFMADD231SD", argLength: 3, reg: fp31, resultInArg0: true, asm: "VFMADD231SD"},
+
+ {name: "SBBQcarrymask", argLength: 1, reg: flagsgp, asm: "SBBQ"}, // (int64)(-1) if carry is set, 0 if carry is clear.
+ {name: "SBBLcarrymask", argLength: 1, 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", argLength: 1, reg: readflags, asm: "SETEQ"}, // extract == condition from arg0
+ {name: "SETNE", argLength: 1, reg: readflags, asm: "SETNE"}, // extract != condition from arg0
+ {name: "SETL", argLength: 1, reg: readflags, asm: "SETLT"}, // extract signed < condition from arg0
+ {name: "SETLE", argLength: 1, reg: readflags, asm: "SETLE"}, // extract signed <= condition from arg0
+ {name: "SETG", argLength: 1, reg: readflags, asm: "SETGT"}, // extract signed > condition from arg0
+ {name: "SETGE", argLength: 1, reg: readflags, asm: "SETGE"}, // extract signed >= condition from arg0
+ {name: "SETB", argLength: 1, reg: readflags, asm: "SETCS"}, // extract unsigned < condition from arg0
+ {name: "SETBE", argLength: 1, reg: readflags, asm: "SETLS"}, // extract unsigned <= condition from arg0
+ {name: "SETA", argLength: 1, reg: readflags, asm: "SETHI"}, // extract unsigned > condition from arg0
+ {name: "SETAE", argLength: 1, reg: readflags, asm: "SETCC"}, // extract unsigned >= condition from arg0
+ {name: "SETO", argLength: 1, reg: readflags, asm: "SETOS"}, // extract if overflow flag is set from arg0
+ // Variants that store result to memory
+ {name: "SETEQstore", argLength: 3, reg: gpstoreconst, asm: "SETEQ", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // extract == condition from arg1 to arg0+auxint+aux, arg2=mem
+ {name: "SETNEstore", argLength: 3, reg: gpstoreconst, asm: "SETNE", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // extract != condition from arg1 to arg0+auxint+aux, arg2=mem
+ {name: "SETLstore", argLength: 3, reg: gpstoreconst, asm: "SETLT", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // extract signed < condition from arg1 to arg0+auxint+aux, arg2=mem
+ {name: "SETLEstore", argLength: 3, reg: gpstoreconst, asm: "SETLE", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // extract signed <= condition from arg1 to arg0+auxint+aux, arg2=mem
+ {name: "SETGstore", argLength: 3, reg: gpstoreconst, asm: "SETGT", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // extract signed > condition from arg1 to arg0+auxint+aux, arg2=mem
+ {name: "SETGEstore", argLength: 3, reg: gpstoreconst, asm: "SETGE", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // extract signed >= condition from arg1 to arg0+auxint+aux, arg2=mem
+ {name: "SETBstore", argLength: 3, reg: gpstoreconst, asm: "SETCS", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // extract unsigned < condition from arg1 to arg0+auxint+aux, arg2=mem
+ {name: "SETBEstore", argLength: 3, reg: gpstoreconst, asm: "SETLS", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // extract unsigned <= condition from arg1 to arg0+auxint+aux, arg2=mem
+ {name: "SETAstore", argLength: 3, reg: gpstoreconst, asm: "SETHI", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // extract unsigned > condition from arg1 to arg0+auxint+aux, arg2=mem
+ {name: "SETAEstore", argLength: 3, reg: gpstoreconst, asm: "SETCC", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // extract unsigned >= condition from arg1 to arg0+auxint+aux, arg2=mem
+ // 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", argLength: 1, reg: flagsgpax, asm: "SETEQ", clobberFlags: true}, // extract == condition from arg0
+ {name: "SETNEF", argLength: 1, reg: flagsgpax, asm: "SETNE", clobberFlags: true}, // extract != condition from arg0
+ {name: "SETORD", argLength: 1, reg: flagsgp, asm: "SETPC"}, // extract "ordered" (No Nan present) condition from arg0
+ {name: "SETNAN", argLength: 1, reg: flagsgp, asm: "SETPS"}, // extract "unordered" (Nan present) condition from arg0
+
+ {name: "SETGF", argLength: 1, reg: flagsgp, asm: "SETHI"}, // extract floating > condition from arg0
+ {name: "SETGEF", argLength: 1, reg: flagsgp, asm: "SETCC"}, // extract floating >= condition from arg0
+
+ {name: "MOVBQSX", argLength: 1, reg: gp11, asm: "MOVBQSX"}, // sign extend arg0 from int8 to int64
+ {name: "MOVBQZX", argLength: 1, reg: gp11, asm: "MOVBLZX"}, // zero extend arg0 from int8 to int64
+ {name: "MOVWQSX", argLength: 1, reg: gp11, asm: "MOVWQSX"}, // sign extend arg0 from int16 to int64
+ {name: "MOVWQZX", argLength: 1, reg: gp11, asm: "MOVWLZX"}, // zero extend arg0 from int16 to int64
+ {name: "MOVLQSX", argLength: 1, reg: gp11, asm: "MOVLQSX"}, // sign extend arg0 from int32 to int64
+ {name: "MOVLQZX", argLength: 1, reg: gp11, asm: "MOVL"}, // zero extend arg0 from int32 to int64
+
+ {name: "MOVLconst", reg: gp01, asm: "MOVL", typ: "UInt32", aux: "Int32", rematerializeable: true}, // 32 low bits of auxint
+ {name: "MOVQconst", reg: gp01, asm: "MOVQ", typ: "UInt64", aux: "Int64", rematerializeable: true}, // auxint
+
+ {name: "CVTTSD2SL", argLength: 1, reg: fpgp, asm: "CVTTSD2SL"}, // convert float64 to int32
+ {name: "CVTTSD2SQ", argLength: 1, reg: fpgp, asm: "CVTTSD2SQ"}, // convert float64 to int64
+ {name: "CVTTSS2SL", argLength: 1, reg: fpgp, asm: "CVTTSS2SL"}, // convert float32 to int32
+ {name: "CVTTSS2SQ", argLength: 1, reg: fpgp, asm: "CVTTSS2SQ"}, // convert float32 to int64
+ {name: "CVTSL2SS", argLength: 1, reg: gpfp, asm: "CVTSL2SS"}, // convert int32 to float32
+ {name: "CVTSL2SD", argLength: 1, reg: gpfp, asm: "CVTSL2SD"}, // convert int32 to float64
+ {name: "CVTSQ2SS", argLength: 1, reg: gpfp, asm: "CVTSQ2SS"}, // convert int64 to float32
+ {name: "CVTSQ2SD", argLength: 1, reg: gpfp, asm: "CVTSQ2SD"}, // convert int64 to float64
+ {name: "CVTSD2SS", argLength: 1, reg: fp11, asm: "CVTSD2SS"}, // convert float64 to float32
+ {name: "CVTSS2SD", argLength: 1, reg: fp11, asm: "CVTSS2SD"}, // convert float32 to float64
+
+ // Move values between int and float registers, with no conversion.
+ // TODO: should we have generic versions of these?
+ {name: "MOVQi2f", argLength: 1, reg: gpfp, typ: "Float64"}, // move 64 bits from int to float reg
+ {name: "MOVQf2i", argLength: 1, reg: fpgp, typ: "UInt64"}, // move 64 bits from float to int reg
+ {name: "MOVLi2f", argLength: 1, reg: gpfp, typ: "Float32"}, // move 32 bits from int to float reg
+ {name: "MOVLf2i", argLength: 1, reg: fpgp, typ: "UInt32"}, // move 32 bits from float to int reg, zero extend
+
+ {name: "PXOR", argLength: 2, reg: fp21, asm: "PXOR", commutative: true, resultInArg0: true}, // exclusive or, applied to X regs for float negation.
+
+ {name: "LEAQ", argLength: 1, reg: gp11sb, asm: "LEAQ", aux: "SymOff", rematerializeable: true, symEffect: "Addr"}, // arg0 + auxint + offset encoded in aux
+ {name: "LEAL", argLength: 1, reg: gp11sb, asm: "LEAL", aux: "SymOff", rematerializeable: true, symEffect: "Addr"}, // arg0 + auxint + offset encoded in aux
+ {name: "LEAW", argLength: 1, reg: gp11sb, asm: "LEAW", aux: "SymOff", rematerializeable: true, symEffect: "Addr"}, // arg0 + auxint + offset encoded in aux
+ {name: "LEAQ1", argLength: 2, reg: gp21sb, asm: "LEAQ", scale: 1, commutative: true, aux: "SymOff", symEffect: "Addr"}, // arg0 + arg1 + auxint + aux
+ {name: "LEAL1", argLength: 2, reg: gp21sb, asm: "LEAL", scale: 1, commutative: true, aux: "SymOff", symEffect: "Addr"}, // arg0 + arg1 + auxint + aux
+ {name: "LEAW1", argLength: 2, reg: gp21sb, asm: "LEAW", scale: 1, commutative: true, aux: "SymOff", symEffect: "Addr"}, // arg0 + arg1 + auxint + aux
+ {name: "LEAQ2", argLength: 2, reg: gp21sb, asm: "LEAQ", scale: 2, aux: "SymOff", symEffect: "Addr"}, // arg0 + 2*arg1 + auxint + aux
+ {name: "LEAL2", argLength: 2, reg: gp21sb, asm: "LEAL", scale: 2, aux: "SymOff", symEffect: "Addr"}, // arg0 + 2*arg1 + auxint + aux
+ {name: "LEAW2", argLength: 2, reg: gp21sb, asm: "LEAW", scale: 2, aux: "SymOff", symEffect: "Addr"}, // arg0 + 2*arg1 + auxint + aux
+ {name: "LEAQ4", argLength: 2, reg: gp21sb, asm: "LEAQ", scale: 4, aux: "SymOff", symEffect: "Addr"}, // arg0 + 4*arg1 + auxint + aux
+ {name: "LEAL4", argLength: 2, reg: gp21sb, asm: "LEAL", scale: 4, aux: "SymOff", symEffect: "Addr"}, // arg0 + 4*arg1 + auxint + aux
+ {name: "LEAW4", argLength: 2, reg: gp21sb, asm: "LEAW", scale: 4, aux: "SymOff", symEffect: "Addr"}, // arg0 + 4*arg1 + auxint + aux
+ {name: "LEAQ8", argLength: 2, reg: gp21sb, asm: "LEAQ", scale: 8, aux: "SymOff", symEffect: "Addr"}, // arg0 + 8*arg1 + auxint + aux
+ {name: "LEAL8", argLength: 2, reg: gp21sb, asm: "LEAL", scale: 8, aux: "SymOff", symEffect: "Addr"}, // arg0 + 8*arg1 + auxint + aux
+ {name: "LEAW8", argLength: 2, reg: gp21sb, asm: "LEAW", scale: 8, aux: "SymOff", symEffect: "Addr"}, // arg0 + 8*arg1 + auxint + aux
+ // Note: LEAx{1,2,4,8} must not have OpSB as either argument.
+
+ // auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
+ {name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVBLZX", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load byte from arg0+auxint+aux. arg1=mem. Zero extend.
+ {name: "MOVBQSXload", argLength: 2, reg: gpload, asm: "MOVBQSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
+ {name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVWLZX", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
+ {name: "MOVWQSXload", argLength: 2, reg: gpload, asm: "MOVWQSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
+ {name: "MOVLload", argLength: 2, reg: gpload, asm: "MOVL", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
+ {name: "MOVLQSXload", argLength: 2, reg: gpload, asm: "MOVLQSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
+ {name: "MOVQload", argLength: 2, reg: gpload, asm: "MOVQ", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes from arg0+auxint+aux. arg1=mem
+ {name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem
+ {name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
+ {name: "MOVLstore", argLength: 3, reg: gpstore, asm: "MOVL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
+ {name: "MOVQstore", argLength: 3, reg: gpstore, asm: "MOVQ", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem
+ {name: "MOVOload", argLength: 2, reg: fpload, asm: "MOVUPS", aux: "SymOff", typ: "Int128", faultOnNilArg0: true, symEffect: "Read"}, // load 16 bytes from arg0+auxint+aux. arg1=mem
+ {name: "MOVOstore", argLength: 3, reg: fpstore, asm: "MOVUPS", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 16 bytes in arg1 to arg0+auxint+aux. arg2=mem
+
+ // indexed loads/stores
+ {name: "MOVBloadidx1", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVBLZX", scale: 1, aux: "SymOff", typ: "UInt8", symEffect: "Read"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem
+ {name: "MOVWloadidx1", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWLZX", scale: 1, aux: "SymOff", typ: "UInt16", symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem
+ {name: "MOVWloadidx2", argLength: 3, reg: gploadidx, asm: "MOVWLZX", scale: 2, aux: "SymOff", typ: "UInt16", symEffect: "Read"}, // load 2 bytes from arg0+2*arg1+auxint+aux. arg2=mem
+ {name: "MOVLloadidx1", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVL", scale: 1, aux: "SymOff", typ: "UInt32", symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem
+ {name: "MOVLloadidx4", argLength: 3, reg: gploadidx, asm: "MOVL", scale: 4, aux: "SymOff", typ: "UInt32", symEffect: "Read"}, // load 4 bytes from arg0+4*arg1+auxint+aux. arg2=mem
+ {name: "MOVLloadidx8", argLength: 3, reg: gploadidx, asm: "MOVL", scale: 8, aux: "SymOff", typ: "UInt32", symEffect: "Read"}, // load 4 bytes from arg0+8*arg1+auxint+aux. arg2=mem
+ {name: "MOVQloadidx1", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVQ", scale: 1, aux: "SymOff", typ: "UInt64", symEffect: "Read"}, // load 8 bytes from arg0+arg1+auxint+aux. arg2=mem
+ {name: "MOVQloadidx8", argLength: 3, reg: gploadidx, asm: "MOVQ", scale: 8, aux: "SymOff", typ: "UInt64", symEffect: "Read"}, // load 8 bytes from arg0+8*arg1+auxint+aux. arg2=mem
+ // TODO: sign-extending indexed loads
+ {name: "MOVBstoreidx1", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVB", scale: 1, aux: "SymOff", symEffect: "Write"}, // store byte in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVWstoreidx1", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVW", scale: 1, aux: "SymOff", symEffect: "Write"}, // store 2 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVWstoreidx2", argLength: 4, reg: gpstoreidx, asm: "MOVW", scale: 2, aux: "SymOff", symEffect: "Write"}, // store 2 bytes in arg2 to arg0+2*arg1+auxint+aux. arg3=mem
+ {name: "MOVLstoreidx1", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVL", scale: 1, aux: "SymOff", symEffect: "Write"}, // store 4 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVLstoreidx4", argLength: 4, reg: gpstoreidx, asm: "MOVL", scale: 4, aux: "SymOff", symEffect: "Write"}, // store 4 bytes in arg2 to arg0+4*arg1+auxint+aux. arg3=mem
+ {name: "MOVLstoreidx8", argLength: 4, reg: gpstoreidx, asm: "MOVL", scale: 8, aux: "SymOff", symEffect: "Write"}, // store 4 bytes in arg2 to arg0+8*arg1+auxint+aux. arg3=mem
+ {name: "MOVQstoreidx1", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVQ", scale: 1, aux: "SymOff", symEffect: "Write"}, // store 8 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVQstoreidx8", argLength: 4, reg: gpstoreidx, asm: "MOVQ", scale: 8, aux: "SymOff", symEffect: "Write"}, // store 8 bytes in arg2 to arg0+8*arg1+auxint+aux. arg3=mem
+ // TODO: add size-mismatched indexed loads, like MOVBstoreidx4.
+
+ // For storeconst ops, the AuxInt field encodes both
+ // the value to store and an address offset of the store.
+ // Cast AuxInt to a ValAndOff to extract Val and Off fields.
+ {name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem
+ {name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 2 bytes of ...
+ {name: "MOVLstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVL", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 4 bytes of ...
+ {name: "MOVQstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVQ", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of ...
+
+ {name: "MOVBstoreconstidx1", argLength: 3, reg: gpstoreconstidx, commutative: true, asm: "MOVB", scale: 1, aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+1*arg1+ValAndOff(AuxInt).Off()+aux. arg2=mem
+ {name: "MOVWstoreconstidx1", argLength: 3, reg: gpstoreconstidx, commutative: true, asm: "MOVW", scale: 1, aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low 2 bytes of ... arg1 ...
+ {name: "MOVWstoreconstidx2", argLength: 3, reg: gpstoreconstidx, asm: "MOVW", scale: 2, aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low 2 bytes of ... 2*arg1 ...
+ {name: "MOVLstoreconstidx1", argLength: 3, reg: gpstoreconstidx, commutative: true, asm: "MOVL", scale: 1, aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low 4 bytes of ... arg1 ...
+ {name: "MOVLstoreconstidx4", argLength: 3, reg: gpstoreconstidx, asm: "MOVL", scale: 4, aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low 4 bytes of ... 4*arg1 ...
+ {name: "MOVQstoreconstidx1", argLength: 3, reg: gpstoreconstidx, commutative: true, asm: "MOVQ", scale: 1, aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store 8 bytes of ... arg1 ...
+ {name: "MOVQstoreconstidx8", argLength: 3, reg: gpstoreconstidx, asm: "MOVQ", scale: 8, aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store 8 bytes of ... 8*arg1 ...
+
+ // arg0 = pointer to start of memory to zero
+ // arg1 = value to store (will always be zero)
+ // arg2 = mem
+ // auxint = # of bytes to zero
+ // returns mem
+ {
+ name: "DUFFZERO",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("DI"), buildReg("X0")},
+ clobbers: buildReg("DI"),
+ },
+ faultOnNilArg0: true,
+ unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
+ },
+ {name: "MOVOconst", reg: regInfo{nil, 0, []regMask{fp}}, typ: "Int128", aux: "Int128", rematerializeable: true},
+
+ // 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",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{buildReg("DI"), buildReg("CX"), buildReg("AX")},
+ clobbers: buildReg("DI CX"),
+ },
+ faultOnNilArg0: true,
+ },
+
+ {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
+ {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
+ {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
+
+ // arg0 = destination pointer
+ // arg1 = source pointer
+ // arg2 = mem
+ // auxint = # of bytes to copy, must be multiple of 16
+ // returns memory
+ {
+ name: "DUFFCOPY",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("DI"), buildReg("SI")},
+ clobbers: buildReg("DI SI X0"), // uses X0 as a temporary
+ },
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
+ },
+
+ // arg0 = destination pointer
+ // arg1 = source pointer
+ // arg2 = # of 8-byte words to copy
+ // arg3 = mem
+ // returns memory
+ {
+ name: "REPMOVSQ",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{buildReg("DI"), buildReg("SI"), buildReg("CX")},
+ clobbers: buildReg("DI SI CX"),
+ },
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // (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", argLength: 1}, // reverse direction of arg0
+
+ // Pseudo-ops
+ {name: "LoweredGetG", argLength: 1, reg: gp01}, // arg0=mem
+ // 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")}}, zeroWidth: true},
+ // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+ // I.e., if f calls g "calls" getcallerpc,
+ // the result should be the PC within f that g will return to.
+ // See runtime/stubs.go for a more detailed discussion.
+ {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
+ // LoweredGetCallerSP returns the SP of the caller of the current function.
+ {name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
+ //arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
+ {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
+ // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+ // It saves all GP registers if necessary, but may clobber others.
+ {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("DI"), buildReg("AX CX DX BX BP SI R8 R9")}, clobbers: callerSave &^ gp}, clobberFlags: true, aux: "Sym", symEffect: "None"},
+
+ {name: "LoweredHasCPUFeature", argLength: 0, reg: gp01, rematerializeable: true, typ: "UInt64", aux: "Sym", symEffect: "None"},
+
+ // There are three of these functions so that they can have three different register inputs.
+ // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
+ // default registers to match so we don't need to copy registers around unnecessarily.
+ {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{dx, bx}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
+ {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{cx, dx}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
+ {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{ax, cx}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
+
+ // Constant flag values. For any comparison, there are 5 possible
+ // outcomes: the three from the signed total order (<,==,>) and the
+ // three from the unsigned total order. The == cases overlap.
+ // Note: there's a sixth "unordered" outcome for floating-point
+ // comparisons, but we don't use such a beast yet.
+ // These ops are for temporary use by rewrite rules. They
+ // cannot appear in the generated assembly.
+ {name: "FlagEQ"}, // equal
+ {name: "FlagLT_ULT"}, // signed < and unsigned <
+ {name: "FlagLT_UGT"}, // signed < and unsigned >
+ {name: "FlagGT_UGT"}, // signed > and unsigned >
+ {name: "FlagGT_ULT"}, // signed > and unsigned <
+
+ // Atomic loads. These are just normal loads but return <value,memory> tuples
+ // so they can be properly ordered with other loads.
+ // load from arg0+auxint+aux. arg1=mem.
+ {name: "MOVBatomicload", argLength: 2, reg: gpload, asm: "MOVB", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},
+ {name: "MOVLatomicload", argLength: 2, reg: gpload, asm: "MOVL", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},
+ {name: "MOVQatomicload", argLength: 2, reg: gpload, asm: "MOVQ", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},
+
+ // Atomic stores and exchanges. Stores use XCHG to get the right memory ordering semantics.
+ // store arg0 to arg1+auxint+aux, arg2=mem.
+ // These ops return a tuple of <old contents of *(arg1+auxint+aux), memory>.
+ // Note: arg0 and arg1 are backwards compared to MOVLstore (to facilitate resultInArg0)!
+ {name: "XCHGB", argLength: 3, reg: gpstorexchg, asm: "XCHGB", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true, symEffect: "RdWr"},
+ {name: "XCHGL", argLength: 3, reg: gpstorexchg, asm: "XCHGL", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true, symEffect: "RdWr"},
+ {name: "XCHGQ", argLength: 3, reg: gpstorexchg, asm: "XCHGQ", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true, symEffect: "RdWr"},
+
+ // Atomic adds.
+ // *(arg1+auxint+aux) += arg0. arg2=mem.
+ // Returns a tuple of <old contents of *(arg1+auxint+aux), memory>.
+ // Note: arg0 and arg1 are backwards compared to MOVLstore (to facilitate resultInArg0)!
+ {name: "XADDLlock", argLength: 3, reg: gpstorexchg, asm: "XADDL", typ: "(UInt32,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, hasSideEffects: true, symEffect: "RdWr"},
+ {name: "XADDQlock", argLength: 3, reg: gpstorexchg, asm: "XADDQ", typ: "(UInt64,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, hasSideEffects: true, symEffect: "RdWr"},
+ {name: "AddTupleFirst32", argLength: 2}, // arg1=tuple <x,y>. Returns <x+arg0,y>.
+ {name: "AddTupleFirst64", argLength: 2}, // arg1=tuple <x,y>. Returns <x+arg0,y>.
+
+ // Compare and swap.
+ // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory.
+ // if *(arg0+auxint+aux) == arg1 {
+ // *(arg0+auxint+aux) = arg2
+ // return (true, memory)
+ // } else {
+ // return (false, memory)
+ // }
+ // Note that these instructions also return the old value in AX, but we ignore it.
+ // TODO: have these return flags instead of bool. The current system generates:
+ // CMPXCHGQ ...
+ // SETEQ AX
+ // CMPB AX, $0
+ // JNE ...
+ // instead of just
+ // CMPXCHGQ ...
+ // JEQ ...
+ // but we can't do that because memory-using ops can't generate flags yet
+ // (flagalloc wants to move flag-generating instructions around).
+ {name: "CMPXCHGLlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGL", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
+ {name: "CMPXCHGQlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGQ", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
+
+ // Atomic memory updates.
+ {name: "ANDBlock", argLength: 3, reg: gpstore, asm: "ANDB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"}, // *(arg0+auxint+aux) &= arg1
+ {name: "ANDLlock", argLength: 3, reg: gpstore, asm: "ANDL", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"}, // *(arg0+auxint+aux) &= arg1
+ {name: "ORBlock", argLength: 3, reg: gpstore, asm: "ORB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"}, // *(arg0+auxint+aux) |= arg1
+ {name: "ORLlock", argLength: 3, reg: gpstore, asm: "ORL", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"}, // *(arg0+auxint+aux) |= arg1
+ }
+
+ var AMD64blocks = []blockData{
+ {name: "EQ", controls: 1},
+ {name: "NE", controls: 1},
+ {name: "LT", controls: 1},
+ {name: "LE", controls: 1},
+ {name: "GT", controls: 1},
+ {name: "GE", controls: 1},
+ {name: "OS", controls: 1},
+ {name: "OC", controls: 1},
+ {name: "ULT", controls: 1},
+ {name: "ULE", controls: 1},
+ {name: "UGT", controls: 1},
+ {name: "UGE", controls: 1},
+ {name: "EQF", controls: 1},
+ {name: "NEF", controls: 1},
+ {name: "ORD", controls: 1}, // FP, ordered comparison (parity zero)
+ {name: "NAN", controls: 1}, // FP, unordered comparison (parity one)
+ }
+
+ archs = append(archs, arch{
+ name: "AMD64",
+ pkg: "cmd/internal/obj/x86",
+ genfile: "../../amd64/ssa.go",
+ ops: AMD64ops,
+ blocks: AMD64blocks,
+ regnames: regNamesAMD64,
+ gpregmask: gp,
+ fpregmask: fp,
+ framepointerreg: int8(num["BP"]),
+ linkreg: -1, // not used
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64splitload.rules b/src/cmd/compile/internal/ssa/gen/AMD64splitload.rules
new file mode 100644
index 0000000..a50d509
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/AMD64splitload.rules
@@ -0,0 +1,45 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains rules used by flagalloc and addressingmodes to
+// split a flag-generating merged load op into separate load and op.
+// Unlike with the other rules files, not all of these
+// rules will be applied to all values.
+// Rather, flagalloc will request for rules to be applied
+// to a particular problematic value.
+// These are often the exact inverse of rules in AMD64.rules,
+// only with the conditions removed.
+//
+// For addressingmodes, certain single instructions are slower than the two instruction
+// split generated here (which is different from the inputs to addressingmodes).
+// For example:
+// (CMPBconstload c (ADDQ x y)) -> (CMPBconstloadidx1 c x y) -> (CMPB c (MOVBloadidx1 x y))
+
+(CMP(Q|L|W|B)load {sym} [off] ptr x mem) => (CMP(Q|L|W|B) (MOV(Q|L|W|B)load {sym} [off] ptr mem) x)
+
+(CMP(Q|L|W|B)constload {sym} [vo] ptr mem) && vo.Val() == 0 => (TEST(Q|L|W|B) x:(MOV(Q|L|W|B)load {sym} [vo.Off32()] ptr mem) x)
+
+(CMPQconstload {sym} [vo] ptr mem) && vo.Val() != 0 => (CMPQconst (MOVQload {sym} [vo.Off32()] ptr mem) [vo.Val32()])
+(CMPLconstload {sym} [vo] ptr mem) && vo.Val() != 0 => (CMPLconst (MOVLload {sym} [vo.Off32()] ptr mem) [vo.Val32()])
+(CMPWconstload {sym} [vo] ptr mem) && vo.Val() != 0 => (CMPWconst (MOVWload {sym} [vo.Off32()] ptr mem) [vo.Val16()])
+(CMPBconstload {sym} [vo] ptr mem) && vo.Val() != 0 => (CMPBconst (MOVBload {sym} [vo.Off32()] ptr mem) [vo.Val8()])
+
+(CMP(Q|L|W|B)loadidx1 {sym} [off] ptr idx x mem) => (CMP(Q|L|W|B) (MOV(Q|L|W|B)loadidx1 {sym} [off] ptr idx mem) x)
+(CMPQloadidx8 {sym} [off] ptr idx x mem) => (CMPQ (MOVQloadidx8 {sym} [off] ptr idx mem) x)
+(CMPLloadidx4 {sym} [off] ptr idx x mem) => (CMPL (MOVLloadidx4 {sym} [off] ptr idx mem) x)
+(CMPWloadidx2 {sym} [off] ptr idx x mem) => (CMPW (MOVWloadidx2 {sym} [off] ptr idx mem) x)
+
+(CMP(Q|L|W|B)constloadidx1 {sym} [vo] ptr idx mem) && vo.Val() == 0 => (TEST(Q|L|W|B) x:(MOV(Q|L|W|B)loadidx1 {sym} [vo.Off32()] ptr idx mem) x)
+(CMPQconstloadidx8 {sym} [vo] ptr idx mem) && vo.Val() == 0 => (TESTQ x:(MOVQloadidx8 {sym} [vo.Off32()] ptr idx mem) x)
+(CMPLconstloadidx4 {sym} [vo] ptr idx mem) && vo.Val() == 0 => (TESTL x:(MOVLloadidx4 {sym} [vo.Off32()] ptr idx mem) x)
+(CMPWconstloadidx2 {sym} [vo] ptr idx mem) && vo.Val() == 0 => (TESTW x:(MOVWloadidx2 {sym} [vo.Off32()] ptr idx mem) x)
+
+(CMPQconstloadidx1 {sym} [vo] ptr idx mem) && vo.Val() != 0 => (CMPQconst (MOVQloadidx1 {sym} [vo.Off32()] ptr idx mem) [vo.Val32()])
+(CMPLconstloadidx1 {sym} [vo] ptr idx mem) && vo.Val() != 0 => (CMPLconst (MOVLloadidx1 {sym} [vo.Off32()] ptr idx mem) [vo.Val32()])
+(CMPWconstloadidx1 {sym} [vo] ptr idx mem) && vo.Val() != 0 => (CMPWconst (MOVWloadidx1 {sym} [vo.Off32()] ptr idx mem) [vo.Val16()])
+(CMPBconstloadidx1 {sym} [vo] ptr idx mem) && vo.Val() != 0 => (CMPBconst (MOVBloadidx1 {sym} [vo.Off32()] ptr idx mem) [vo.Val8()])
+
+(CMPQconstloadidx8 {sym} [vo] ptr idx mem) && vo.Val() != 0 => (CMPQconst (MOVQloadidx8 {sym} [vo.Off32()] ptr idx mem) [vo.Val32()])
+(CMPLconstloadidx4 {sym} [vo] ptr idx mem) && vo.Val() != 0 => (CMPLconst (MOVLloadidx4 {sym} [vo.Off32()] ptr idx mem) [vo.Val32()])
+(CMPWconstloadidx2 {sym} [vo] ptr idx mem) && vo.Val() != 0 => (CMPWconst (MOVWloadidx2 {sym} [vo.Off32()] ptr idx mem) [vo.Val16()])
diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules
new file mode 100644
index 0000000..69989b0
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/ARM.rules
@@ -0,0 +1,1475 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+(Add(Ptr|32|16|8) ...) => (ADD ...)
+(Add(32|64)F ...) => (ADD(F|D) ...)
+(Add32carry ...) => (ADDS ...)
+(Add32withcarry ...) => (ADC ...)
+
+(Sub(Ptr|32|16|8) ...) => (SUB ...)
+(Sub(32|64)F ...) => (SUB(F|D) ...)
+(Sub32carry ...) => (SUBS ...)
+(Sub32withcarry ...) => (SBC ...)
+
+(Mul(32|16|8) ...) => (MUL ...)
+(Mul(32|64)F ...) => (MUL(F|D) ...)
+(Hmul(32|32u) ...) => (HMU(L|LU) ...)
+(Mul32uhilo ...) => (MULLU ...)
+
+(Div32 x y) =>
+ (SUB (XOR <typ.UInt32> // negate the result if one operand is negative
+ (Select0 <typ.UInt32> (CALLudiv
+ (SUB <typ.UInt32> (XOR x <typ.UInt32> (Signmask x)) (Signmask x)) // negate x if negative
+ (SUB <typ.UInt32> (XOR y <typ.UInt32> (Signmask y)) (Signmask y)))) // negate y if negative
+ (Signmask (XOR <typ.UInt32> x y))) (Signmask (XOR <typ.UInt32> x y)))
+(Div32u x y) => (Select0 <typ.UInt32> (CALLudiv x y))
+(Div16 x y) => (Div32 (SignExt16to32 x) (SignExt16to32 y))
+(Div16u x y) => (Div32u (ZeroExt16to32 x) (ZeroExt16to32 y))
+(Div8 x y) => (Div32 (SignExt8to32 x) (SignExt8to32 y))
+(Div8u x y) => (Div32u (ZeroExt8to32 x) (ZeroExt8to32 y))
+(Div(32|64)F ...) => (DIV(F|D) ...)
+
+(Mod32 x y) =>
+ (SUB (XOR <typ.UInt32> // negate the result if x is negative
+ (Select1 <typ.UInt32> (CALLudiv
+ (SUB <typ.UInt32> (XOR <typ.UInt32> x (Signmask x)) (Signmask x)) // negate x if negative
+ (SUB <typ.UInt32> (XOR <typ.UInt32> y (Signmask y)) (Signmask y)))) // negate y if negative
+ (Signmask x)) (Signmask x))
+(Mod32u x y) => (Select1 <typ.UInt32> (CALLudiv x y))
+(Mod16 x y) => (Mod32 (SignExt16to32 x) (SignExt16to32 y))
+(Mod16u x y) => (Mod32u (ZeroExt16to32 x) (ZeroExt16to32 y))
+(Mod8 x y) => (Mod32 (SignExt8to32 x) (SignExt8to32 y))
+(Mod8u x y) => (Mod32u (ZeroExt8to32 x) (ZeroExt8to32 y))
+
+// (x + y) / 2 with x>=y -> (x - y) / 2 + y
+(Avg32u <t> x y) => (ADD (SRLconst <t> (SUB <t> x y) [1]) y)
+
+(And(32|16|8) ...) => (AND ...)
+(Or(32|16|8) ...) => (OR ...)
+(Xor(32|16|8) ...) => (XOR ...)
+
+// unary ops
+(Neg(32|16|8) x) => (RSBconst [0] x)
+(Neg(32|64)F ...) => (NEG(F|D) ...)
+
+(Com(32|16|8) ...) => (MVN ...)
+
+(Sqrt ...) => (SQRTD ...)
+(Abs ...) => (ABSD ...)
+
+// TODO: optimize this for ARMv5 and ARMv6
+(Ctz32NonZero ...) => (Ctz32 ...)
+(Ctz16NonZero ...) => (Ctz32 ...)
+(Ctz8NonZero ...) => (Ctz32 ...)
+
+// count trailing zero for ARMv5 and ARMv6
+// 32 - CLZ(x&-x - 1)
+(Ctz32 <t> x) && objabi.GOARM<=6 =>
+ (RSBconst [32] (CLZ <t> (SUBconst <t> (AND <t> x (RSBconst <t> [0] x)) [1])))
+(Ctz16 <t> x) && objabi.GOARM<=6 =>
+ (RSBconst [32] (CLZ <t> (SUBconst <typ.UInt32> (AND <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x) (RSBconst <typ.UInt32> [0] (ORconst <typ.UInt32> [0x10000] x))) [1])))
+(Ctz8 <t> x) && objabi.GOARM<=6 =>
+ (RSBconst [32] (CLZ <t> (SUBconst <typ.UInt32> (AND <typ.UInt32> (ORconst <typ.UInt32> [0x100] x) (RSBconst <typ.UInt32> [0] (ORconst <typ.UInt32> [0x100] x))) [1])))
+
+// count trailing zero for ARMv7
+(Ctz32 <t> x) && objabi.GOARM==7 => (CLZ <t> (RBIT <t> x))
+(Ctz16 <t> x) && objabi.GOARM==7 => (CLZ <t> (RBIT <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x)))
+(Ctz8 <t> x) && objabi.GOARM==7 => (CLZ <t> (RBIT <typ.UInt32> (ORconst <typ.UInt32> [0x100] x)))
+
+// bit length
+(BitLen32 <t> x) => (RSBconst [32] (CLZ <t> x))
+
+// byte swap for ARMv5
+// let (a, b, c, d) be the bytes of x from high to low
+// t1 = x right rotate 16 bits -- (c, d, a, b )
+// t2 = x ^ t1 -- (a^c, b^d, a^c, b^d)
+// t3 = t2 &^ 0xff0000 -- (a^c, 0, a^c, b^d)
+// t4 = t3 >> 8 -- (0, a^c, 0, a^c)
+// t5 = x right rotate 8 bits -- (d, a, b, c )
+// result = t4 ^ t5 -- (d, c, b, a )
+// using shifted ops this can be done in 4 instructions.
+(Bswap32 <t> x) && objabi.GOARM==5 =>
+ (XOR <t>
+ (SRLconst <t> (BICconst <t> (XOR <t> x (SRRconst <t> [16] x)) [0xff0000]) [8])
+ (SRRconst <t> x [8]))
+
+// byte swap for ARMv6 and above
+(Bswap32 x) && objabi.GOARM>=6 => (REV x)
+
+// boolean ops -- booleans are represented with 0=false, 1=true
+(AndB ...) => (AND ...)
+(OrB ...) => (OR ...)
+(EqB x y) => (XORconst [1] (XOR <typ.Bool> x y))
+(NeqB ...) => (XOR ...)
+(Not x) => (XORconst [1] x)
+
+// shifts
+// hardware instruction uses only the low byte of the shift
+// we compare to 256 to ensure Go semantics for large shifts
+(Lsh32x32 x y) => (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
+(Lsh32x16 x y) => (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+(Lsh32x8 x y) => (SLL x (ZeroExt8to32 y))
+
+(Lsh16x32 x y) => (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
+(Lsh16x16 x y) => (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+(Lsh16x8 x y) => (SLL x (ZeroExt8to32 y))
+
+(Lsh8x32 x y) => (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
+(Lsh8x16 x y) => (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+(Lsh8x8 x y) => (SLL x (ZeroExt8to32 y))
+
+(Rsh32Ux32 x y) => (CMOVWHSconst (SRL <x.Type> x y) (CMPconst [256] y) [0])
+(Rsh32Ux16 x y) => (CMOVWHSconst (SRL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+(Rsh32Ux8 x y) => (SRL x (ZeroExt8to32 y))
+
+(Rsh16Ux32 x y) => (CMOVWHSconst (SRL <x.Type> (ZeroExt16to32 x) y) (CMPconst [256] y) [0])
+(Rsh16Ux16 x y) => (CMOVWHSconst (SRL <x.Type> (ZeroExt16to32 x) (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+(Rsh16Ux8 x y) => (SRL (ZeroExt16to32 x) (ZeroExt8to32 y))
+
+(Rsh8Ux32 x y) => (CMOVWHSconst (SRL <x.Type> (ZeroExt8to32 x) y) (CMPconst [256] y) [0])
+(Rsh8Ux16 x y) => (CMOVWHSconst (SRL <x.Type> (ZeroExt8to32 x) (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+(Rsh8Ux8 x y) => (SRL (ZeroExt8to32 x) (ZeroExt8to32 y))
+
+(Rsh32x32 x y) => (SRAcond x y (CMPconst [256] y))
+(Rsh32x16 x y) => (SRAcond x (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
+(Rsh32x8 x y) => (SRA x (ZeroExt8to32 y))
+
+(Rsh16x32 x y) => (SRAcond (SignExt16to32 x) y (CMPconst [256] y))
+(Rsh16x16 x y) => (SRAcond (SignExt16to32 x) (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
+(Rsh16x8 x y) => (SRA (SignExt16to32 x) (ZeroExt8to32 y))
+
+(Rsh8x32 x y) => (SRAcond (SignExt8to32 x) y (CMPconst [256] y))
+(Rsh8x16 x y) => (SRAcond (SignExt8to32 x) (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
+(Rsh8x8 x y) => (SRA (SignExt8to32 x) (ZeroExt8to32 y))
+
+// constant shifts
+// generic opt rewrites all constant shifts to shift by Const64
+(Lsh32x64 x (Const64 [c])) && uint64(c) < 32 => (SLLconst x [int32(c)])
+(Rsh32x64 x (Const64 [c])) && uint64(c) < 32 => (SRAconst x [int32(c)])
+(Rsh32Ux64 x (Const64 [c])) && uint64(c) < 32 => (SRLconst x [int32(c)])
+(Lsh16x64 x (Const64 [c])) && uint64(c) < 16 => (SLLconst x [int32(c)])
+(Rsh16x64 x (Const64 [c])) && uint64(c) < 16 => (SRAconst (SLLconst <typ.UInt32> x [16]) [int32(c+16)])
+(Rsh16Ux64 x (Const64 [c])) && uint64(c) < 16 => (SRLconst (SLLconst <typ.UInt32> x [16]) [int32(c+16)])
+(Lsh8x64 x (Const64 [c])) && uint64(c) < 8 => (SLLconst x [int32(c)])
+(Rsh8x64 x (Const64 [c])) && uint64(c) < 8 => (SRAconst (SLLconst <typ.UInt32> x [24]) [int32(c+24)])
+(Rsh8Ux64 x (Const64 [c])) && uint64(c) < 8 => (SRLconst (SLLconst <typ.UInt32> x [24]) [int32(c+24)])
+
+// large constant shifts
+(Lsh32x64 _ (Const64 [c])) && uint64(c) >= 32 => (Const32 [0])
+(Rsh32Ux64 _ (Const64 [c])) && uint64(c) >= 32 => (Const32 [0])
+(Lsh16x64 _ (Const64 [c])) && uint64(c) >= 16 => (Const16 [0])
+(Rsh16Ux64 _ (Const64 [c])) && uint64(c) >= 16 => (Const16 [0])
+(Lsh8x64 _ (Const64 [c])) && uint64(c) >= 8 => (Const8 [0])
+(Rsh8Ux64 _ (Const64 [c])) && uint64(c) >= 8 => (Const8 [0])
+
+// large constant signed right shift, we leave the sign bit
+(Rsh32x64 x (Const64 [c])) && uint64(c) >= 32 => (SRAconst x [31])
+(Rsh16x64 x (Const64 [c])) && uint64(c) >= 16 => (SRAconst (SLLconst <typ.UInt32> x [16]) [31])
+(Rsh8x64 x (Const64 [c])) && uint64(c) >= 8 => (SRAconst (SLLconst <typ.UInt32> x [24]) [31])
+
+// constants
+(Const(8|16|32) [val]) => (MOVWconst [int32(val)])
+(Const(32|64)F [val]) => (MOV(F|D)const [float64(val)])
+(ConstNil) => (MOVWconst [0])
+(ConstBool [b]) => (MOVWconst [b2i32(b)])
+
+// truncations
+// Because we ignore high parts of registers, truncates are just copies.
+(Trunc16to8 ...) => (Copy ...)
+(Trunc32to8 ...) => (Copy ...)
+(Trunc32to16 ...) => (Copy ...)
+
+// Zero-/Sign-extensions
+(ZeroExt8to16 ...) => (MOVBUreg ...)
+(ZeroExt8to32 ...) => (MOVBUreg ...)
+(ZeroExt16to32 ...) => (MOVHUreg ...)
+
+(SignExt8to16 ...) => (MOVBreg ...)
+(SignExt8to32 ...) => (MOVBreg ...)
+(SignExt16to32 ...) => (MOVHreg ...)
+
+(Signmask x) => (SRAconst x [31])
+(Zeromask x) => (SRAconst (RSBshiftRL <typ.Int32> x x [1]) [31]) // sign bit of uint32(x)>>1 - x
+(Slicemask <t> x) => (SRAconst (RSBconst <t> [0] x) [31])
+
+// float <-> int conversion
+(Cvt32to32F ...) => (MOVWF ...)
+(Cvt32to64F ...) => (MOVWD ...)
+(Cvt32Uto32F ...) => (MOVWUF ...)
+(Cvt32Uto64F ...) => (MOVWUD ...)
+(Cvt32Fto32 ...) => (MOVFW ...)
+(Cvt64Fto32 ...) => (MOVDW ...)
+(Cvt32Fto32U ...) => (MOVFWU ...)
+(Cvt64Fto32U ...) => (MOVDWU ...)
+(Cvt32Fto64F ...) => (MOVFD ...)
+(Cvt64Fto32F ...) => (MOVDF ...)
+
+(Round(32|64)F ...) => (Copy ...)
+
+(CvtBoolToUint8 ...) => (Copy ...)
+
+// fused-multiply-add
+(FMA x y z) => (FMULAD z x y)
+
+// comparisons
+(Eq8 x y) => (Equal (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Eq16 x y) => (Equal (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Eq32 x y) => (Equal (CMP x y))
+(EqPtr x y) => (Equal (CMP x y))
+(Eq(32|64)F x y) => (Equal (CMP(F|D) x y))
+
+(Neq8 x y) => (NotEqual (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Neq16 x y) => (NotEqual (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Neq32 x y) => (NotEqual (CMP x y))
+(NeqPtr x y) => (NotEqual (CMP x y))
+(Neq(32|64)F x y) => (NotEqual (CMP(F|D) x y))
+
+(Less8 x y) => (LessThan (CMP (SignExt8to32 x) (SignExt8to32 y)))
+(Less16 x y) => (LessThan (CMP (SignExt16to32 x) (SignExt16to32 y)))
+(Less32 x y) => (LessThan (CMP x y))
+(Less(32|64)F x y) => (GreaterThan (CMP(F|D) y x)) // reverse operands to work around NaN
+
+(Less8U x y) => (LessThanU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Less16U x y) => (LessThanU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Less32U x y) => (LessThanU (CMP x y))
+
+(Leq8 x y) => (LessEqual (CMP (SignExt8to32 x) (SignExt8to32 y)))
+(Leq16 x y) => (LessEqual (CMP (SignExt16to32 x) (SignExt16to32 y)))
+(Leq32 x y) => (LessEqual (CMP x y))
+(Leq(32|64)F x y) => (GreaterEqual (CMP(F|D) y x)) // reverse operands to work around NaN
+
+(Leq8U x y) => (LessEqualU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Leq16U x y) => (LessEqualU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Leq32U x y) => (LessEqualU (CMP x y))
+
+(OffPtr [off] ptr:(SP)) => (MOVWaddr [int32(off)] ptr)
+(OffPtr [off] ptr) => (ADDconst [int32(off)] ptr)
+
+(Addr {sym} base) => (MOVWaddr {sym} base)
+(LocalAddr {sym} base _) => (MOVWaddr {sym} base)
+
+// loads
+(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
+(Load <t> ptr mem) && (is8BitInt(t) && isSigned(t)) => (MOVBload ptr mem)
+(Load <t> ptr mem) && (is8BitInt(t) && !isSigned(t)) => (MOVBUload ptr mem)
+(Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) => (MOVHload ptr mem)
+(Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) => (MOVHUload ptr mem)
+(Load <t> ptr mem) && (is32BitInt(t) || isPtr(t)) => (MOVWload ptr mem)
+(Load <t> ptr mem) && is32BitFloat(t) => (MOVFload ptr mem)
+(Load <t> ptr mem) && is64BitFloat(t) => (MOVDload ptr mem)
+
+// stores
+(Store {t} ptr val mem) && t.Size() == 1 => (MOVBstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 2 => (MOVHstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && !is32BitFloat(val.Type) => (MOVWstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && is32BitFloat(val.Type) => (MOVFstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 && is64BitFloat(val.Type) => (MOVDstore ptr val mem)
+
+// zero instructions
+(Zero [0] _ mem) => mem
+(Zero [1] ptr mem) => (MOVBstore ptr (MOVWconst [0]) mem)
+(Zero [2] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore ptr (MOVWconst [0]) mem)
+(Zero [2] ptr mem) =>
+ (MOVBstore [1] ptr (MOVWconst [0])
+ (MOVBstore [0] ptr (MOVWconst [0]) mem))
+(Zero [4] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore ptr (MOVWconst [0]) mem)
+(Zero [4] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [2] ptr (MOVWconst [0])
+ (MOVHstore [0] ptr (MOVWconst [0]) mem))
+(Zero [4] ptr mem) =>
+ (MOVBstore [3] ptr (MOVWconst [0])
+ (MOVBstore [2] ptr (MOVWconst [0])
+ (MOVBstore [1] ptr (MOVWconst [0])
+ (MOVBstore [0] ptr (MOVWconst [0]) mem))))
+
+(Zero [3] ptr mem) =>
+ (MOVBstore [2] ptr (MOVWconst [0])
+ (MOVBstore [1] ptr (MOVWconst [0])
+ (MOVBstore [0] ptr (MOVWconst [0]) mem)))
+
+// Medium zeroing uses a duff device
+// 4 and 128 are magic constants, see runtime/mkduff.go
+(Zero [s] {t} ptr mem)
+ && s%4 == 0 && s > 4 && s <= 512
+ && t.Alignment()%4 == 0 && !config.noDuffDevice =>
+ (DUFFZERO [4 * (128 - s/4)] ptr (MOVWconst [0]) mem)
+
+// Large zeroing uses a loop
+(Zero [s] {t} ptr mem)
+ && (s > 512 || config.noDuffDevice) || t.Alignment()%4 != 0 =>
+ (LoweredZero [t.Alignment()]
+ ptr
+ (ADDconst <ptr.Type> ptr [int32(s-moveSize(t.Alignment(), config))])
+ (MOVWconst [0])
+ mem)
+
+// moves
+(Move [0] _ _ mem) => mem
+(Move [1] dst src mem) => (MOVBstore dst (MOVBUload src mem) mem)
+(Move [2] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore dst (MOVHUload src mem) mem)
+(Move [2] dst src mem) =>
+ (MOVBstore [1] dst (MOVBUload [1] src mem)
+ (MOVBstore dst (MOVBUload src mem) mem))
+(Move [4] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore dst (MOVWload src mem) mem)
+(Move [4] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [2] dst (MOVHUload [2] src mem)
+ (MOVHstore dst (MOVHUload src mem) mem))
+(Move [4] dst src mem) =>
+ (MOVBstore [3] dst (MOVBUload [3] src mem)
+ (MOVBstore [2] dst (MOVBUload [2] src mem)
+ (MOVBstore [1] dst (MOVBUload [1] src mem)
+ (MOVBstore dst (MOVBUload src mem) mem))))
+
+(Move [3] dst src mem) =>
+ (MOVBstore [2] dst (MOVBUload [2] src mem)
+ (MOVBstore [1] dst (MOVBUload [1] src mem)
+ (MOVBstore dst (MOVBUload src mem) mem)))
+
+// Medium move uses a duff device
+// 8 and 128 are magic constants, see runtime/mkduff.go
+(Move [s] {t} dst src mem)
+ && s%4 == 0 && s > 4 && s <= 512
+ && t.Alignment()%4 == 0 && !config.noDuffDevice && logLargeCopy(v, s) =>
+ (DUFFCOPY [8 * (128 - s/4)] dst src mem)
+
+// Large move uses a loop
+(Move [s] {t} dst src mem)
+ && ((s > 512 || config.noDuffDevice) || t.Alignment()%4 != 0) && logLargeCopy(v, s) =>
+ (LoweredMove [t.Alignment()]
+ dst
+ src
+ (ADDconst <src.Type> src [int32(s-moveSize(t.Alignment(), config))])
+ mem)
+
+// calls
+(StaticCall ...) => (CALLstatic ...)
+(ClosureCall ...) => (CALLclosure ...)
+(InterCall ...) => (CALLinter ...)
+
+// checks
+(NilCheck ...) => (LoweredNilCheck ...)
+(IsNonNil ptr) => (NotEqual (CMPconst [0] ptr))
+(IsInBounds idx len) => (LessThanU (CMP idx len))
+(IsSliceInBounds idx len) => (LessEqualU (CMP idx len))
+
+// pseudo-ops
+(GetClosurePtr ...) => (LoweredGetClosurePtr ...)
+(GetCallerSP ...) => (LoweredGetCallerSP ...)
+(GetCallerPC ...) => (LoweredGetCallerPC ...)
+
+// Absorb pseudo-ops into blocks.
+(If (Equal cc) yes no) => (EQ cc yes no)
+(If (NotEqual cc) yes no) => (NE cc yes no)
+(If (LessThan cc) yes no) => (LT cc yes no)
+(If (LessThanU cc) yes no) => (ULT cc yes no)
+(If (LessEqual cc) yes no) => (LE cc yes no)
+(If (LessEqualU cc) yes no) => (ULE cc yes no)
+(If (GreaterThan cc) yes no) => (GT cc yes no)
+(If (GreaterThanU cc) yes no) => (UGT cc yes no)
+(If (GreaterEqual cc) yes no) => (GE cc yes no)
+(If (GreaterEqualU cc) yes no) => (UGE cc yes no)
+
+(If cond yes no) => (NE (CMPconst [0] cond) yes no)
+
+// Absorb boolean tests into block
+(NE (CMPconst [0] (Equal cc)) yes no) => (EQ cc yes no)
+(NE (CMPconst [0] (NotEqual cc)) yes no) => (NE cc yes no)
+(NE (CMPconst [0] (LessThan cc)) yes no) => (LT cc yes no)
+(NE (CMPconst [0] (LessThanU cc)) yes no) => (ULT cc yes no)
+(NE (CMPconst [0] (LessEqual cc)) yes no) => (LE cc yes no)
+(NE (CMPconst [0] (LessEqualU cc)) yes no) => (ULE cc yes no)
+(NE (CMPconst [0] (GreaterThan cc)) yes no) => (GT cc yes no)
+(NE (CMPconst [0] (GreaterThanU cc)) yes no) => (UGT cc yes no)
+(NE (CMPconst [0] (GreaterEqual cc)) yes no) => (GE cc yes no)
+(NE (CMPconst [0] (GreaterEqualU cc)) yes no) => (UGE cc yes no)
+
+// Write barrier.
+(WB ...) => (LoweredWB ...)
+
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
+
+(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 0 => (LoweredPanicExtendA [kind] hi lo y mem)
+(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 1 => (LoweredPanicExtendB [kind] hi lo y mem)
+(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 2 => (LoweredPanicExtendC [kind] hi lo y mem)
+
+// Optimizations
+
+// fold offset into address
+(ADDconst [off1] (MOVWaddr [off2] {sym} ptr)) => (MOVWaddr [off1+off2] {sym} ptr)
+(SUBconst [off1] (MOVWaddr [off2] {sym} ptr)) => (MOVWaddr [off2-off1] {sym} ptr)
+
+// fold address into load/store
+(MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) => (MOVBload [off1+off2] {sym} ptr mem)
+(MOVBload [off1] {sym} (SUBconst [off2] ptr) mem) => (MOVBload [off1-off2] {sym} ptr mem)
+(MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem) => (MOVBUload [off1+off2] {sym} ptr mem)
+(MOVBUload [off1] {sym} (SUBconst [off2] ptr) mem) => (MOVBUload [off1-off2] {sym} ptr mem)
+(MOVHload [off1] {sym} (ADDconst [off2] ptr) mem) => (MOVHload [off1+off2] {sym} ptr mem)
+(MOVHload [off1] {sym} (SUBconst [off2] ptr) mem) => (MOVHload [off1-off2] {sym} ptr mem)
+(MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem) => (MOVHUload [off1+off2] {sym} ptr mem)
+(MOVHUload [off1] {sym} (SUBconst [off2] ptr) mem) => (MOVHUload [off1-off2] {sym} ptr mem)
+(MOVWload [off1] {sym} (ADDconst [off2] ptr) mem) => (MOVWload [off1+off2] {sym} ptr mem)
+(MOVWload [off1] {sym} (SUBconst [off2] ptr) mem) => (MOVWload [off1-off2] {sym} ptr mem)
+(MOVFload [off1] {sym} (ADDconst [off2] ptr) mem) => (MOVFload [off1+off2] {sym} ptr mem)
+(MOVFload [off1] {sym} (SUBconst [off2] ptr) mem) => (MOVFload [off1-off2] {sym} ptr mem)
+(MOVDload [off1] {sym} (ADDconst [off2] ptr) mem) => (MOVDload [off1+off2] {sym} ptr mem)
+(MOVDload [off1] {sym} (SUBconst [off2] ptr) mem) => (MOVDload [off1-off2] {sym} ptr mem)
+
+(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) => (MOVBstore [off1+off2] {sym} ptr val mem)
+(MOVBstore [off1] {sym} (SUBconst [off2] ptr) val mem) => (MOVBstore [off1-off2] {sym} ptr val mem)
+(MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem) => (MOVHstore [off1+off2] {sym} ptr val mem)
+(MOVHstore [off1] {sym} (SUBconst [off2] ptr) val mem) => (MOVHstore [off1-off2] {sym} ptr val mem)
+(MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem) => (MOVWstore [off1+off2] {sym} ptr val mem)
+(MOVWstore [off1] {sym} (SUBconst [off2] ptr) val mem) => (MOVWstore [off1-off2] {sym} ptr val mem)
+(MOVFstore [off1] {sym} (ADDconst [off2] ptr) val mem) => (MOVFstore [off1+off2] {sym} ptr val mem)
+(MOVFstore [off1] {sym} (SUBconst [off2] ptr) val mem) => (MOVFstore [off1-off2] {sym} ptr val mem)
+(MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) => (MOVDstore [off1+off2] {sym} ptr val mem)
+(MOVDstore [off1] {sym} (SUBconst [off2] ptr) val mem) => (MOVDstore [off1-off2] {sym} ptr val mem)
+
+(MOVBload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVBUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVFload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVFload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVDload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+
+(MOVBstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) =>
+ (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVHstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) =>
+ (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVWstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) =>
+ (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVFstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) =>
+ (MOVFstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVDstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) =>
+ (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+
+// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
+(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVBreg x)
+(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVBUreg x)
+(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVHreg x)
+(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVHUreg x)
+(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => x
+
+(MOVFload [off] {sym} ptr (MOVFstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => x
+(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => x
+
+(MOVWloadidx ptr idx (MOVWstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) => x
+(MOVWloadshiftLL ptr idx [c] (MOVWstoreshiftLL ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) => x
+(MOVWloadshiftRL ptr idx [c] (MOVWstoreshiftRL ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) => x
+(MOVWloadshiftRA ptr idx [c] (MOVWstoreshiftRA ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) => x
+(MOVBUloadidx ptr idx (MOVBstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) => (MOVBUreg x)
+(MOVBloadidx ptr idx (MOVBstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) => (MOVBreg x)
+(MOVHUloadidx ptr idx (MOVHstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) => (MOVHUreg x)
+(MOVHloadidx ptr idx (MOVHstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) => (MOVHreg x)
+
+// fold constant into arithmatic ops
+(ADD x (MOVWconst [c])) => (ADDconst [c] x)
+(SUB (MOVWconst [c]) x) => (RSBconst [c] x)
+(SUB x (MOVWconst [c])) => (SUBconst [c] x)
+(RSB (MOVWconst [c]) x) => (SUBconst [c] x)
+(RSB x (MOVWconst [c])) => (RSBconst [c] x)
+
+(ADDS x (MOVWconst [c])) => (ADDSconst [c] x)
+(SUBS x (MOVWconst [c])) => (SUBSconst [c] x)
+
+(ADC (MOVWconst [c]) x flags) => (ADCconst [c] x flags)
+(SBC (MOVWconst [c]) x flags) => (RSCconst [c] x flags)
+(SBC x (MOVWconst [c]) flags) => (SBCconst [c] x flags)
+
+(AND x (MOVWconst [c])) => (ANDconst [c] x)
+(OR x (MOVWconst [c])) => (ORconst [c] x)
+(XOR x (MOVWconst [c])) => (XORconst [c] x)
+(BIC x (MOVWconst [c])) => (BICconst [c] x)
+
+(SLL x (MOVWconst [c])) && 0 <= c && c < 32 => (SLLconst x [c])
+(SRL x (MOVWconst [c])) && 0 <= c && c < 32 => (SRLconst x [c])
+(SRA x (MOVWconst [c])) && 0 <= c && c < 32 => (SRAconst x [c])
+
+(CMP x (MOVWconst [c])) => (CMPconst [c] x)
+(CMP (MOVWconst [c]) x) => (InvertFlags (CMPconst [c] x))
+(CMN x (MOVWconst [c])) => (CMNconst [c] x)
+(TST x (MOVWconst [c])) => (TSTconst [c] x)
+(TEQ x (MOVWconst [c])) => (TEQconst [c] x)
+
+// Canonicalize the order of arguments to comparisons - helps with CSE.
+(CMP x y) && x.ID > y.ID => (InvertFlags (CMP y x))
+
+// don't extend after proper load
+// MOVWreg instruction is not emitted if src and dst registers are same, but it ensures the type.
+(MOVBreg x:(MOVBload _ _)) => (MOVWreg x)
+(MOVBUreg x:(MOVBUload _ _)) => (MOVWreg x)
+(MOVHreg x:(MOVBload _ _)) => (MOVWreg x)
+(MOVHreg x:(MOVBUload _ _)) => (MOVWreg x)
+(MOVHreg x:(MOVHload _ _)) => (MOVWreg x)
+(MOVHUreg x:(MOVBUload _ _)) => (MOVWreg x)
+(MOVHUreg x:(MOVHUload _ _)) => (MOVWreg x)
+
+// fold extensions and ANDs together
+(MOVBUreg (ANDconst [c] x)) => (ANDconst [c&0xff] x)
+(MOVHUreg (ANDconst [c] x)) => (ANDconst [c&0xffff] x)
+(MOVBreg (ANDconst [c] x)) && c & 0x80 == 0 => (ANDconst [c&0x7f] x)
+(MOVHreg (ANDconst [c] x)) && c & 0x8000 == 0 => (ANDconst [c&0x7fff] x)
+
+// fold double extensions
+(MOVBreg x:(MOVBreg _)) => (MOVWreg x)
+(MOVBUreg x:(MOVBUreg _)) => (MOVWreg x)
+(MOVHreg x:(MOVBreg _)) => (MOVWreg x)
+(MOVHreg x:(MOVBUreg _)) => (MOVWreg x)
+(MOVHreg x:(MOVHreg _)) => (MOVWreg x)
+(MOVHUreg x:(MOVBUreg _)) => (MOVWreg x)
+(MOVHUreg x:(MOVHUreg _)) => (MOVWreg x)
+
+// don't extend before store
+(MOVBstore [off] {sym} ptr (MOVBreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVBUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVHreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVHUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+
+// if a register move has only 1 use, just use the same register without emitting instruction
+// MOVWnop doesn't emit instruction, only for ensuring the type.
+(MOVWreg x) && x.Uses == 1 => (MOVWnop x)
+
+// mul by constant
+(MUL x (MOVWconst [c])) && int32(c) == -1 => (RSBconst [0] x)
+(MUL _ (MOVWconst [0])) => (MOVWconst [0])
+(MUL x (MOVWconst [1])) => x
+(MUL x (MOVWconst [c])) && isPowerOfTwo32(c) => (SLLconst [int32(log32(c))] x)
+(MUL x (MOVWconst [c])) && isPowerOfTwo32(c-1) && c >= 3 => (ADDshiftLL x x [int32(log32(c-1))])
+(MUL x (MOVWconst [c])) && isPowerOfTwo32(c+1) && c >= 7 => (RSBshiftLL x x [int32(log32(c+1))])
+(MUL x (MOVWconst [c])) && c%3 == 0 && isPowerOfTwo32(c/3) => (SLLconst [int32(log32(c/3))] (ADDshiftLL <x.Type> x x [1]))
+(MUL x (MOVWconst [c])) && c%5 == 0 && isPowerOfTwo32(c/5) => (SLLconst [int32(log32(c/5))] (ADDshiftLL <x.Type> x x [2]))
+(MUL x (MOVWconst [c])) && c%7 == 0 && isPowerOfTwo32(c/7) => (SLLconst [int32(log32(c/7))] (RSBshiftLL <x.Type> x x [3]))
+(MUL x (MOVWconst [c])) && c%9 == 0 && isPowerOfTwo32(c/9) => (SLLconst [int32(log32(c/9))] (ADDshiftLL <x.Type> x x [3]))
+
+(MULA x (MOVWconst [c]) a) && c == -1 => (SUB a x)
+(MULA _ (MOVWconst [0]) a) => a
+(MULA x (MOVWconst [1]) a) => (ADD x a)
+(MULA x (MOVWconst [c]) a) && isPowerOfTwo32(c) => (ADD (SLLconst <x.Type> [int32(log32(c))] x) a)
+(MULA x (MOVWconst [c]) a) && isPowerOfTwo32(c-1) && c >= 3 => (ADD (ADDshiftLL <x.Type> x x [int32(log32(c-1))]) a)
+(MULA x (MOVWconst [c]) a) && isPowerOfTwo32(c+1) && c >= 7 => (ADD (RSBshiftLL <x.Type> x x [int32(log32(c+1))]) a)
+(MULA x (MOVWconst [c]) a) && c%3 == 0 && isPowerOfTwo32(c/3) => (ADD (SLLconst <x.Type> [int32(log32(c/3))] (ADDshiftLL <x.Type> x x [1])) a)
+(MULA x (MOVWconst [c]) a) && c%5 == 0 && isPowerOfTwo32(c/5) => (ADD (SLLconst <x.Type> [int32(log32(c/5))] (ADDshiftLL <x.Type> x x [2])) a)
+(MULA x (MOVWconst [c]) a) && c%7 == 0 && isPowerOfTwo32(c/7) => (ADD (SLLconst <x.Type> [int32(log32(c/7))] (RSBshiftLL <x.Type> x x [3])) a)
+(MULA x (MOVWconst [c]) a) && c%9 == 0 && isPowerOfTwo32(c/9) => (ADD (SLLconst <x.Type> [int32(log32(c/9))] (ADDshiftLL <x.Type> x x [3])) a)
+
+(MULA (MOVWconst [c]) x a) && c == -1 => (SUB a x)
+(MULA (MOVWconst [0]) _ a) => a
+(MULA (MOVWconst [1]) x a) => (ADD x a)
+(MULA (MOVWconst [c]) x a) && isPowerOfTwo32(c) => (ADD (SLLconst <x.Type> [int32(log32(c))] x) a)
+(MULA (MOVWconst [c]) x a) && isPowerOfTwo32(c-1) && c >= 3 => (ADD (ADDshiftLL <x.Type> x x [int32(log32(c-1))]) a)
+(MULA (MOVWconst [c]) x a) && isPowerOfTwo32(c+1) && c >= 7 => (ADD (RSBshiftLL <x.Type> x x [int32(log32(c+1))]) a)
+(MULA (MOVWconst [c]) x a) && c%3 == 0 && isPowerOfTwo32(c/3) => (ADD (SLLconst <x.Type> [int32(log32(c/3))] (ADDshiftLL <x.Type> x x [1])) a)
+(MULA (MOVWconst [c]) x a) && c%5 == 0 && isPowerOfTwo32(c/5) => (ADD (SLLconst <x.Type> [int32(log32(c/5))] (ADDshiftLL <x.Type> x x [2])) a)
+(MULA (MOVWconst [c]) x a) && c%7 == 0 && isPowerOfTwo32(c/7) => (ADD (SLLconst <x.Type> [int32(log32(c/7))] (RSBshiftLL <x.Type> x x [3])) a)
+(MULA (MOVWconst [c]) x a) && c%9 == 0 && isPowerOfTwo32(c/9) => (ADD (SLLconst <x.Type> [int32(log32(c/9))] (ADDshiftLL <x.Type> x x [3])) a)
+
+(MULS x (MOVWconst [c]) a) && c == -1 => (ADD a x)
+(MULS _ (MOVWconst [0]) a) => a
+(MULS x (MOVWconst [1]) a) => (RSB x a)
+(MULS x (MOVWconst [c]) a) && isPowerOfTwo32(c) => (RSB (SLLconst <x.Type> [int32(log32(c))] x) a)
+(MULS x (MOVWconst [c]) a) && isPowerOfTwo32(c-1) && c >= 3 => (RSB (ADDshiftLL <x.Type> x x [int32(log32(c-1))]) a)
+(MULS x (MOVWconst [c]) a) && isPowerOfTwo32(c+1) && c >= 7 => (RSB (RSBshiftLL <x.Type> x x [int32(log32(c+1))]) a)
+(MULS x (MOVWconst [c]) a) && c%3 == 0 && isPowerOfTwo32(c/3) => (RSB (SLLconst <x.Type> [int32(log32(c/3))] (ADDshiftLL <x.Type> x x [1])) a)
+(MULS x (MOVWconst [c]) a) && c%5 == 0 && isPowerOfTwo32(c/5) => (RSB (SLLconst <x.Type> [int32(log32(c/5))] (ADDshiftLL <x.Type> x x [2])) a)
+(MULS x (MOVWconst [c]) a) && c%7 == 0 && isPowerOfTwo32(c/7) => (RSB (SLLconst <x.Type> [int32(log32(c/7))] (RSBshiftLL <x.Type> x x [3])) a)
+(MULS x (MOVWconst [c]) a) && c%9 == 0 && isPowerOfTwo32(c/9) => (RSB (SLLconst <x.Type> [int32(log32(c/9))] (ADDshiftLL <x.Type> x x [3])) a)
+
+(MULS (MOVWconst [c]) x a) && c == -1 => (ADD a x)
+(MULS (MOVWconst [0]) _ a) => a
+(MULS (MOVWconst [1]) x a) => (RSB x a)
+(MULS (MOVWconst [c]) x a) && isPowerOfTwo32(c) => (RSB (SLLconst <x.Type> [int32(log32(c))] x) a)
+(MULS (MOVWconst [c]) x a) && isPowerOfTwo32(c-1) && c >= 3 => (RSB (ADDshiftLL <x.Type> x x [int32(log32(c-1))]) a)
+(MULS (MOVWconst [c]) x a) && isPowerOfTwo32(c+1) && c >= 7 => (RSB (RSBshiftLL <x.Type> x x [int32(log32(c+1))]) a)
+(MULS (MOVWconst [c]) x a) && c%3 == 0 && isPowerOfTwo32(c/3) => (RSB (SLLconst <x.Type> [int32(log32(c/3))] (ADDshiftLL <x.Type> x x [1])) a)
+(MULS (MOVWconst [c]) x a) && c%5 == 0 && isPowerOfTwo32(c/5) => (RSB (SLLconst <x.Type> [int32(log32(c/5))] (ADDshiftLL <x.Type> x x [2])) a)
+(MULS (MOVWconst [c]) x a) && c%7 == 0 && isPowerOfTwo32(c/7) => (RSB (SLLconst <x.Type> [int32(log32(c/7))] (RSBshiftLL <x.Type> x x [3])) a)
+(MULS (MOVWconst [c]) x a) && c%9 == 0 && isPowerOfTwo32(c/9) => (RSB (SLLconst <x.Type> [int32(log32(c/9))] (ADDshiftLL <x.Type> x x [3])) a)
+
+// div by constant
+(Select0 (CALLudiv x (MOVWconst [1]))) => x
+(Select1 (CALLudiv _ (MOVWconst [1]))) => (MOVWconst [0])
+(Select0 (CALLudiv x (MOVWconst [c]))) && isPowerOfTwo32(c) => (SRLconst [int32(log32(c))] x)
+(Select1 (CALLudiv x (MOVWconst [c]))) && isPowerOfTwo32(c) => (ANDconst [c-1] x)
+
+// constant comparisons
+(CMPconst (MOVWconst [x]) [y]) => (FlagConstant [subFlags32(x,y)])
+(CMNconst (MOVWconst [x]) [y]) => (FlagConstant [addFlags32(x,y)])
+(TSTconst (MOVWconst [x]) [y]) => (FlagConstant [logicFlags32(x&y)])
+(TEQconst (MOVWconst [x]) [y]) => (FlagConstant [logicFlags32(x^y)])
+
+// other known comparisons
+(CMPconst (MOVBUreg _) [c]) && 0xff < c => (FlagConstant [subFlags32(0, 1)])
+(CMPconst (MOVHUreg _) [c]) && 0xffff < c => (FlagConstant [subFlags32(0, 1)])
+(CMPconst (ANDconst _ [m]) [n]) && 0 <= m && m < n => (FlagConstant [subFlags32(0, 1)])
+(CMPconst (SRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 32 && (1<<uint32(32-c)) <= uint32(n) => (FlagConstant [subFlags32(0, 1)])
+
+// absorb flag constants into branches
+(EQ (FlagConstant [fc]) yes no) && fc.eq() => (First yes no)
+(EQ (FlagConstant [fc]) yes no) && !fc.eq() => (First no yes)
+
+(NE (FlagConstant [fc]) yes no) && fc.ne() => (First yes no)
+(NE (FlagConstant [fc]) yes no) && !fc.ne() => (First no yes)
+
+(LT (FlagConstant [fc]) yes no) && fc.lt() => (First yes no)
+(LT (FlagConstant [fc]) yes no) && !fc.lt() => (First no yes)
+
+(LE (FlagConstant [fc]) yes no) && fc.le() => (First yes no)
+(LE (FlagConstant [fc]) yes no) && !fc.le() => (First no yes)
+
+(GT (FlagConstant [fc]) yes no) && fc.gt() => (First yes no)
+(GT (FlagConstant [fc]) yes no) && !fc.gt() => (First no yes)
+
+(GE (FlagConstant [fc]) yes no) && fc.ge() => (First yes no)
+(GE (FlagConstant [fc]) yes no) && !fc.ge() => (First no yes)
+
+(ULT (FlagConstant [fc]) yes no) && fc.ult() => (First yes no)
+(ULT (FlagConstant [fc]) yes no) && !fc.ult() => (First no yes)
+
+(ULE (FlagConstant [fc]) yes no) && fc.ule() => (First yes no)
+(ULE (FlagConstant [fc]) yes no) && !fc.ule() => (First no yes)
+
+(UGT (FlagConstant [fc]) yes no) && fc.ugt() => (First yes no)
+(UGT (FlagConstant [fc]) yes no) && !fc.ugt() => (First no yes)
+
+(UGE (FlagConstant [fc]) yes no) && fc.uge() => (First yes no)
+(UGE (FlagConstant [fc]) yes no) && !fc.uge() => (First no yes)
+
+(LTnoov (FlagConstant [fc]) yes no) && fc.ltNoov() => (First yes no)
+(LTnoov (FlagConstant [fc]) yes no) && !fc.ltNoov() => (First no yes)
+
+(LEnoov (FlagConstant [fc]) yes no) && fc.leNoov() => (First yes no)
+(LEnoov (FlagConstant [fc]) yes no) && !fc.leNoov() => (First no yes)
+
+(GTnoov (FlagConstant [fc]) yes no) && fc.gtNoov() => (First yes no)
+(GTnoov (FlagConstant [fc]) yes no) && !fc.gtNoov() => (First no yes)
+
+(GEnoov (FlagConstant [fc]) yes no) && fc.geNoov() => (First yes no)
+(GEnoov (FlagConstant [fc]) yes no) && !fc.geNoov() => (First no yes)
+
+// 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)
+(LTnoov (InvertFlags cmp) yes no) => (GTnoov cmp yes no)
+(GEnoov (InvertFlags cmp) yes no) => (LEnoov cmp yes no)
+(LEnoov (InvertFlags cmp) yes no) => (GEnoov cmp yes no)
+(GTnoov (InvertFlags cmp) yes no) => (LTnoov cmp yes no)
+
+// absorb flag constants into boolean values
+(Equal (FlagConstant [fc])) => (MOVWconst [b2i32(fc.eq())])
+(NotEqual (FlagConstant [fc])) => (MOVWconst [b2i32(fc.ne())])
+(LessThan (FlagConstant [fc])) => (MOVWconst [b2i32(fc.lt())])
+(LessThanU (FlagConstant [fc])) => (MOVWconst [b2i32(fc.ult())])
+(LessEqual (FlagConstant [fc])) => (MOVWconst [b2i32(fc.le())])
+(LessEqualU (FlagConstant [fc])) => (MOVWconst [b2i32(fc.ule())])
+(GreaterThan (FlagConstant [fc])) => (MOVWconst [b2i32(fc.gt())])
+(GreaterThanU (FlagConstant [fc])) => (MOVWconst [b2i32(fc.ugt())])
+(GreaterEqual (FlagConstant [fc])) => (MOVWconst [b2i32(fc.ge())])
+(GreaterEqualU (FlagConstant [fc])) => (MOVWconst [b2i32(fc.uge())])
+
+// absorb InvertFlags into boolean values
+(Equal (InvertFlags x)) => (Equal x)
+(NotEqual (InvertFlags x)) => (NotEqual x)
+(LessThan (InvertFlags x)) => (GreaterThan x)
+(LessThanU (InvertFlags x)) => (GreaterThanU x)
+(GreaterThan (InvertFlags x)) => (LessThan x)
+(GreaterThanU (InvertFlags x)) => (LessThanU x)
+(LessEqual (InvertFlags x)) => (GreaterEqual x)
+(LessEqualU (InvertFlags x)) => (GreaterEqualU x)
+(GreaterEqual (InvertFlags x)) => (LessEqual x)
+(GreaterEqualU (InvertFlags x)) => (LessEqualU x)
+
+// absorb flag constants into conditional instructions
+(CMOVWLSconst _ (FlagConstant [fc]) [c]) && fc.ule() => (MOVWconst [c])
+(CMOVWLSconst x (FlagConstant [fc]) [c]) && fc.ugt() => x
+
+(CMOVWHSconst _ (FlagConstant [fc]) [c]) && fc.uge() => (MOVWconst [c])
+(CMOVWHSconst x (FlagConstant [fc]) [c]) && fc.ult() => x
+
+(CMOVWLSconst x (InvertFlags flags) [c]) => (CMOVWHSconst x flags [c])
+(CMOVWHSconst x (InvertFlags flags) [c]) => (CMOVWLSconst x flags [c])
+
+(SRAcond x _ (FlagConstant [fc])) && fc.uge() => (SRAconst x [31])
+(SRAcond x y (FlagConstant [fc])) && fc.ult() => (SRA x y)
+
+// remove redundant *const ops
+(ADDconst [0] x) => x
+(SUBconst [0] x) => x
+(ANDconst [0] _) => (MOVWconst [0])
+(ANDconst [c] x) && int32(c)==-1 => x
+(ORconst [0] x) => x
+(ORconst [c] _) && int32(c)==-1 => (MOVWconst [-1])
+(XORconst [0] x) => x
+(BICconst [0] x) => x
+(BICconst [c] _) && int32(c)==-1 => (MOVWconst [0])
+
+// generic constant folding
+(ADDconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c)) => (SUBconst [-c] x)
+(SUBconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c)) => (ADDconst [-c] x)
+(ANDconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(^uint32(c)) => (BICconst [int32(^uint32(c))] x)
+(BICconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(^uint32(c)) => (ANDconst [int32(^uint32(c))] x)
+(ADDconst [c] x) && objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && uint32(-c)<=0xffff => (SUBconst [-c] x)
+(SUBconst [c] x) && objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && uint32(-c)<=0xffff => (ADDconst [-c] x)
+(ANDconst [c] x) && objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && ^uint32(c)<=0xffff => (BICconst [int32(^uint32(c))] x)
+(BICconst [c] x) && objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && ^uint32(c)<=0xffff => (ANDconst [int32(^uint32(c))] x)
+(ADDconst [c] (MOVWconst [d])) => (MOVWconst [c+d])
+(ADDconst [c] (ADDconst [d] x)) => (ADDconst [c+d] x)
+(ADDconst [c] (SUBconst [d] x)) => (ADDconst [c-d] x)
+(ADDconst [c] (RSBconst [d] x)) => (RSBconst [c+d] x)
+(ADCconst [c] (ADDconst [d] x) flags) => (ADCconst [c+d] x flags)
+(ADCconst [c] (SUBconst [d] x) flags) => (ADCconst [c-d] x flags)
+(SUBconst [c] (MOVWconst [d])) => (MOVWconst [d-c])
+(SUBconst [c] (SUBconst [d] x)) => (ADDconst [-c-d] x)
+(SUBconst [c] (ADDconst [d] x)) => (ADDconst [-c+d] x)
+(SUBconst [c] (RSBconst [d] x)) => (RSBconst [-c+d] x)
+(SBCconst [c] (ADDconst [d] x) flags) => (SBCconst [c-d] x flags)
+(SBCconst [c] (SUBconst [d] x) flags) => (SBCconst [c+d] x flags)
+(RSBconst [c] (MOVWconst [d])) => (MOVWconst [c-d])
+(RSBconst [c] (RSBconst [d] x)) => (ADDconst [c-d] x)
+(RSBconst [c] (ADDconst [d] x)) => (RSBconst [c-d] x)
+(RSBconst [c] (SUBconst [d] x)) => (RSBconst [c+d] x)
+(RSCconst [c] (ADDconst [d] x) flags) => (RSCconst [c-d] x flags)
+(RSCconst [c] (SUBconst [d] x) flags) => (RSCconst [c+d] x flags)
+(SLLconst [c] (MOVWconst [d])) => (MOVWconst [d<<uint64(c)])
+(SRLconst [c] (MOVWconst [d])) => (MOVWconst [int32(uint32(d)>>uint64(c))])
+(SRAconst [c] (MOVWconst [d])) => (MOVWconst [d>>uint64(c)])
+(MUL (MOVWconst [c]) (MOVWconst [d])) => (MOVWconst [c*d])
+(MULA (MOVWconst [c]) (MOVWconst [d]) a) => (ADDconst [c*d] a)
+(MULS (MOVWconst [c]) (MOVWconst [d]) a) => (SUBconst [c*d] a)
+(Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)/uint32(d))])
+(Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)%uint32(d))])
+(ANDconst [c] (MOVWconst [d])) => (MOVWconst [c&d])
+(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
+(ORconst [c] (MOVWconst [d])) => (MOVWconst [c|d])
+(ORconst [c] (ORconst [d] x)) => (ORconst [c|d] x)
+(XORconst [c] (MOVWconst [d])) => (MOVWconst [c^d])
+(XORconst [c] (XORconst [d] x)) => (XORconst [c^d] x)
+(BICconst [c] (MOVWconst [d])) => (MOVWconst [d&^c])
+(BICconst [c] (BICconst [d] x)) => (BICconst [c|d] x)
+(MVN (MOVWconst [c])) => (MOVWconst [^c])
+(MOVBreg (MOVWconst [c])) => (MOVWconst [int32(int8(c))])
+(MOVBUreg (MOVWconst [c])) => (MOVWconst [int32(uint8(c))])
+(MOVHreg (MOVWconst [c])) => (MOVWconst [int32(int16(c))])
+(MOVHUreg (MOVWconst [c])) => (MOVWconst [int32(uint16(c))])
+(MOVWreg (MOVWconst [c])) => (MOVWconst [c])
+// BFX: Width = c >> 8, LSB = c & 0xff, result = d << (32 - Width - LSB) >> (32 - Width)
+(BFX [c] (MOVWconst [d])) => (MOVWconst [d<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8))])
+(BFXU [c] (MOVWconst [d])) => (MOVWconst [int32(uint32(d)<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8)))])
+
+// absorb shifts into ops
+(ADD x (SLLconst [c] y)) => (ADDshiftLL x y [c])
+(ADD x (SRLconst [c] y)) => (ADDshiftRL x y [c])
+(ADD x (SRAconst [c] y)) => (ADDshiftRA x y [c])
+(ADD x (SLL y z)) => (ADDshiftLLreg x y z)
+(ADD x (SRL y z)) => (ADDshiftRLreg x y z)
+(ADD x (SRA y z)) => (ADDshiftRAreg x y z)
+(ADC x (SLLconst [c] y) flags) => (ADCshiftLL x y [c] flags)
+(ADC x (SRLconst [c] y) flags) => (ADCshiftRL x y [c] flags)
+(ADC x (SRAconst [c] y) flags) => (ADCshiftRA x y [c] flags)
+(ADC x (SLL y z) flags) => (ADCshiftLLreg x y z flags)
+(ADC x (SRL y z) flags) => (ADCshiftRLreg x y z flags)
+(ADC x (SRA y z) flags) => (ADCshiftRAreg x y z flags)
+(ADDS x (SLLconst [c] y)) => (ADDSshiftLL x y [c])
+(ADDS x (SRLconst [c] y)) => (ADDSshiftRL x y [c])
+(ADDS x (SRAconst [c] y)) => (ADDSshiftRA x y [c])
+(ADDS x (SLL y z)) => (ADDSshiftLLreg x y z)
+(ADDS x (SRL y z)) => (ADDSshiftRLreg x y z)
+(ADDS x (SRA y z)) => (ADDSshiftRAreg x y z)
+(SUB x (SLLconst [c] y)) => (SUBshiftLL x y [c])
+(SUB (SLLconst [c] y) x) => (RSBshiftLL x y [c])
+(SUB x (SRLconst [c] y)) => (SUBshiftRL x y [c])
+(SUB (SRLconst [c] y) x) => (RSBshiftRL x y [c])
+(SUB x (SRAconst [c] y)) => (SUBshiftRA x y [c])
+(SUB (SRAconst [c] y) x) => (RSBshiftRA x y [c])
+(SUB x (SLL y z)) => (SUBshiftLLreg x y z)
+(SUB (SLL y z) x) => (RSBshiftLLreg x y z)
+(SUB x (SRL y z)) => (SUBshiftRLreg x y z)
+(SUB (SRL y z) x) => (RSBshiftRLreg x y z)
+(SUB x (SRA y z)) => (SUBshiftRAreg x y z)
+(SUB (SRA y z) x) => (RSBshiftRAreg x y z)
+(SBC x (SLLconst [c] y) flags) => (SBCshiftLL x y [c] flags)
+(SBC (SLLconst [c] y) x flags) => (RSCshiftLL x y [c] flags)
+(SBC x (SRLconst [c] y) flags) => (SBCshiftRL x y [c] flags)
+(SBC (SRLconst [c] y) x flags) => (RSCshiftRL x y [c] flags)
+(SBC x (SRAconst [c] y) flags) => (SBCshiftRA x y [c] flags)
+(SBC (SRAconst [c] y) x flags) => (RSCshiftRA x y [c] flags)
+(SBC x (SLL y z) flags) => (SBCshiftLLreg x y z flags)
+(SBC (SLL y z) x flags) => (RSCshiftLLreg x y z flags)
+(SBC x (SRL y z) flags) => (SBCshiftRLreg x y z flags)
+(SBC (SRL y z) x flags) => (RSCshiftRLreg x y z flags)
+(SBC x (SRA y z) flags) => (SBCshiftRAreg x y z flags)
+(SBC (SRA y z) x flags) => (RSCshiftRAreg x y z flags)
+(SUBS x (SLLconst [c] y)) => (SUBSshiftLL x y [c])
+(SUBS (SLLconst [c] y) x) => (RSBSshiftLL x y [c])
+(SUBS x (SRLconst [c] y)) => (SUBSshiftRL x y [c])
+(SUBS (SRLconst [c] y) x) => (RSBSshiftRL x y [c])
+(SUBS x (SRAconst [c] y)) => (SUBSshiftRA x y [c])
+(SUBS (SRAconst [c] y) x) => (RSBSshiftRA x y [c])
+(SUBS x (SLL y z)) => (SUBSshiftLLreg x y z)
+(SUBS (SLL y z) x) => (RSBSshiftLLreg x y z)
+(SUBS x (SRL y z)) => (SUBSshiftRLreg x y z)
+(SUBS (SRL y z) x) => (RSBSshiftRLreg x y z)
+(SUBS x (SRA y z)) => (SUBSshiftRAreg x y z)
+(SUBS (SRA y z) x) => (RSBSshiftRAreg x y z)
+(RSB x (SLLconst [c] y)) => (RSBshiftLL x y [c])
+(RSB (SLLconst [c] y) x) => (SUBshiftLL x y [c])
+(RSB x (SRLconst [c] y)) => (RSBshiftRL x y [c])
+(RSB (SRLconst [c] y) x) => (SUBshiftRL x y [c])
+(RSB x (SRAconst [c] y)) => (RSBshiftRA x y [c])
+(RSB (SRAconst [c] y) x) => (SUBshiftRA x y [c])
+(RSB x (SLL y z)) => (RSBshiftLLreg x y z)
+(RSB (SLL y z) x) => (SUBshiftLLreg x y z)
+(RSB x (SRL y z)) => (RSBshiftRLreg x y z)
+(RSB (SRL y z) x) => (SUBshiftRLreg x y z)
+(RSB x (SRA y z)) => (RSBshiftRAreg x y z)
+(RSB (SRA y z) x) => (SUBshiftRAreg x y z)
+(AND x (SLLconst [c] y)) => (ANDshiftLL x y [c])
+(AND x (SRLconst [c] y)) => (ANDshiftRL x y [c])
+(AND x (SRAconst [c] y)) => (ANDshiftRA x y [c])
+(AND x (SLL y z)) => (ANDshiftLLreg x y z)
+(AND x (SRL y z)) => (ANDshiftRLreg x y z)
+(AND x (SRA y z)) => (ANDshiftRAreg x y z)
+(OR x (SLLconst [c] y)) => (ORshiftLL x y [c])
+(OR x (SRLconst [c] y)) => (ORshiftRL x y [c])
+(OR x (SRAconst [c] y)) => (ORshiftRA x y [c])
+(OR x (SLL y z)) => (ORshiftLLreg x y z)
+(OR x (SRL y z)) => (ORshiftRLreg x y z)
+(OR x (SRA y z)) => (ORshiftRAreg x y z)
+(XOR x (SLLconst [c] y)) => (XORshiftLL x y [c])
+(XOR x (SRLconst [c] y)) => (XORshiftRL x y [c])
+(XOR x (SRAconst [c] y)) => (XORshiftRA x y [c])
+(XOR x (SRRconst [c] y)) => (XORshiftRR x y [c])
+(XOR x (SLL y z)) => (XORshiftLLreg x y z)
+(XOR x (SRL y z)) => (XORshiftRLreg x y z)
+(XOR x (SRA y z)) => (XORshiftRAreg x y z)
+(BIC x (SLLconst [c] y)) => (BICshiftLL x y [c])
+(BIC x (SRLconst [c] y)) => (BICshiftRL x y [c])
+(BIC x (SRAconst [c] y)) => (BICshiftRA x y [c])
+(BIC x (SLL y z)) => (BICshiftLLreg x y z)
+(BIC x (SRL y z)) => (BICshiftRLreg x y z)
+(BIC x (SRA y z)) => (BICshiftRAreg x y z)
+(MVN (SLLconst [c] x)) => (MVNshiftLL x [c])
+(MVN (SRLconst [c] x)) => (MVNshiftRL x [c])
+(MVN (SRAconst [c] x)) => (MVNshiftRA x [c])
+(MVN (SLL x y)) => (MVNshiftLLreg x y)
+(MVN (SRL x y)) => (MVNshiftRLreg x y)
+(MVN (SRA x y)) => (MVNshiftRAreg x y)
+
+(CMP x (SLLconst [c] y)) => (CMPshiftLL x y [c])
+(CMP (SLLconst [c] y) x) => (InvertFlags (CMPshiftLL x y [c]))
+(CMP x (SRLconst [c] y)) => (CMPshiftRL x y [c])
+(CMP (SRLconst [c] y) x) => (InvertFlags (CMPshiftRL x y [c]))
+(CMP x (SRAconst [c] y)) => (CMPshiftRA x y [c])
+(CMP (SRAconst [c] y) x) => (InvertFlags (CMPshiftRA x y [c]))
+(CMP x (SLL y z)) => (CMPshiftLLreg x y z)
+(CMP (SLL y z) x) => (InvertFlags (CMPshiftLLreg x y z))
+(CMP x (SRL y z)) => (CMPshiftRLreg x y z)
+(CMP (SRL y z) x) => (InvertFlags (CMPshiftRLreg x y z))
+(CMP x (SRA y z)) => (CMPshiftRAreg x y z)
+(CMP (SRA y z) x) => (InvertFlags (CMPshiftRAreg x y z))
+(TST x (SLLconst [c] y)) => (TSTshiftLL x y [c])
+(TST x (SRLconst [c] y)) => (TSTshiftRL x y [c])
+(TST x (SRAconst [c] y)) => (TSTshiftRA x y [c])
+(TST x (SLL y z)) => (TSTshiftLLreg x y z)
+(TST x (SRL y z)) => (TSTshiftRLreg x y z)
+(TST x (SRA y z)) => (TSTshiftRAreg x y z)
+(TEQ x (SLLconst [c] y)) => (TEQshiftLL x y [c])
+(TEQ x (SRLconst [c] y)) => (TEQshiftRL x y [c])
+(TEQ x (SRAconst [c] y)) => (TEQshiftRA x y [c])
+(TEQ x (SLL y z)) => (TEQshiftLLreg x y z)
+(TEQ x (SRL y z)) => (TEQshiftRLreg x y z)
+(TEQ x (SRA y z)) => (TEQshiftRAreg x y z)
+(CMN x (SLLconst [c] y)) => (CMNshiftLL x y [c])
+(CMN x (SRLconst [c] y)) => (CMNshiftRL x y [c])
+(CMN x (SRAconst [c] y)) => (CMNshiftRA x y [c])
+(CMN x (SLL y z)) => (CMNshiftLLreg x y z)
+(CMN x (SRL y z)) => (CMNshiftRLreg x y z)
+(CMN x (SRA y z)) => (CMNshiftRAreg x y z)
+
+// prefer *const ops to *shift ops
+(ADDshiftLL (MOVWconst [c]) x [d]) => (ADDconst [c] (SLLconst <x.Type> x [d]))
+(ADDshiftRL (MOVWconst [c]) x [d]) => (ADDconst [c] (SRLconst <x.Type> x [d]))
+(ADDshiftRA (MOVWconst [c]) x [d]) => (ADDconst [c] (SRAconst <x.Type> x [d]))
+(ADCshiftLL (MOVWconst [c]) x [d] flags) => (ADCconst [c] (SLLconst <x.Type> x [d]) flags)
+(ADCshiftRL (MOVWconst [c]) x [d] flags) => (ADCconst [c] (SRLconst <x.Type> x [d]) flags)
+(ADCshiftRA (MOVWconst [c]) x [d] flags) => (ADCconst [c] (SRAconst <x.Type> x [d]) flags)
+(ADDSshiftLL (MOVWconst [c]) x [d]) => (ADDSconst [c] (SLLconst <x.Type> x [d]))
+(ADDSshiftRL (MOVWconst [c]) x [d]) => (ADDSconst [c] (SRLconst <x.Type> x [d]))
+(ADDSshiftRA (MOVWconst [c]) x [d]) => (ADDSconst [c] (SRAconst <x.Type> x [d]))
+(SUBshiftLL (MOVWconst [c]) x [d]) => (RSBconst [c] (SLLconst <x.Type> x [d]))
+(SUBshiftRL (MOVWconst [c]) x [d]) => (RSBconst [c] (SRLconst <x.Type> x [d]))
+(SUBshiftRA (MOVWconst [c]) x [d]) => (RSBconst [c] (SRAconst <x.Type> x [d]))
+(SBCshiftLL (MOVWconst [c]) x [d] flags) => (RSCconst [c] (SLLconst <x.Type> x [d]) flags)
+(SBCshiftRL (MOVWconst [c]) x [d] flags) => (RSCconst [c] (SRLconst <x.Type> x [d]) flags)
+(SBCshiftRA (MOVWconst [c]) x [d] flags) => (RSCconst [c] (SRAconst <x.Type> x [d]) flags)
+(SUBSshiftLL (MOVWconst [c]) x [d]) => (RSBSconst [c] (SLLconst <x.Type> x [d]))
+(SUBSshiftRL (MOVWconst [c]) x [d]) => (RSBSconst [c] (SRLconst <x.Type> x [d]))
+(SUBSshiftRA (MOVWconst [c]) x [d]) => (RSBSconst [c] (SRAconst <x.Type> x [d]))
+(RSBshiftLL (MOVWconst [c]) x [d]) => (SUBconst [c] (SLLconst <x.Type> x [d]))
+(RSBshiftRL (MOVWconst [c]) x [d]) => (SUBconst [c] (SRLconst <x.Type> x [d]))
+(RSBshiftRA (MOVWconst [c]) x [d]) => (SUBconst [c] (SRAconst <x.Type> x [d]))
+(RSCshiftLL (MOVWconst [c]) x [d] flags) => (SBCconst [c] (SLLconst <x.Type> x [d]) flags)
+(RSCshiftRL (MOVWconst [c]) x [d] flags) => (SBCconst [c] (SRLconst <x.Type> x [d]) flags)
+(RSCshiftRA (MOVWconst [c]) x [d] flags) => (SBCconst [c] (SRAconst <x.Type> x [d]) flags)
+(RSBSshiftLL (MOVWconst [c]) x [d]) => (SUBSconst [c] (SLLconst <x.Type> x [d]))
+(RSBSshiftRL (MOVWconst [c]) x [d]) => (SUBSconst [c] (SRLconst <x.Type> x [d]))
+(RSBSshiftRA (MOVWconst [c]) x [d]) => (SUBSconst [c] (SRAconst <x.Type> x [d]))
+(ANDshiftLL (MOVWconst [c]) x [d]) => (ANDconst [c] (SLLconst <x.Type> x [d]))
+(ANDshiftRL (MOVWconst [c]) x [d]) => (ANDconst [c] (SRLconst <x.Type> x [d]))
+(ANDshiftRA (MOVWconst [c]) x [d]) => (ANDconst [c] (SRAconst <x.Type> x [d]))
+(ORshiftLL (MOVWconst [c]) x [d]) => (ORconst [c] (SLLconst <x.Type> x [d]))
+(ORshiftRL (MOVWconst [c]) x [d]) => (ORconst [c] (SRLconst <x.Type> x [d]))
+(ORshiftRA (MOVWconst [c]) x [d]) => (ORconst [c] (SRAconst <x.Type> x [d]))
+(XORshiftLL (MOVWconst [c]) x [d]) => (XORconst [c] (SLLconst <x.Type> x [d]))
+(XORshiftRL (MOVWconst [c]) x [d]) => (XORconst [c] (SRLconst <x.Type> x [d]))
+(XORshiftRA (MOVWconst [c]) x [d]) => (XORconst [c] (SRAconst <x.Type> x [d]))
+(XORshiftRR (MOVWconst [c]) x [d]) => (XORconst [c] (SRRconst <x.Type> x [d]))
+(CMPshiftLL (MOVWconst [c]) x [d]) => (InvertFlags (CMPconst [c] (SLLconst <x.Type> x [d])))
+(CMPshiftRL (MOVWconst [c]) x [d]) => (InvertFlags (CMPconst [c] (SRLconst <x.Type> x [d])))
+(CMPshiftRA (MOVWconst [c]) x [d]) => (InvertFlags (CMPconst [c] (SRAconst <x.Type> x [d])))
+(TSTshiftLL (MOVWconst [c]) x [d]) => (TSTconst [c] (SLLconst <x.Type> x [d]))
+(TSTshiftRL (MOVWconst [c]) x [d]) => (TSTconst [c] (SRLconst <x.Type> x [d]))
+(TSTshiftRA (MOVWconst [c]) x [d]) => (TSTconst [c] (SRAconst <x.Type> x [d]))
+(TEQshiftLL (MOVWconst [c]) x [d]) => (TEQconst [c] (SLLconst <x.Type> x [d]))
+(TEQshiftRL (MOVWconst [c]) x [d]) => (TEQconst [c] (SRLconst <x.Type> x [d]))
+(TEQshiftRA (MOVWconst [c]) x [d]) => (TEQconst [c] (SRAconst <x.Type> x [d]))
+(CMNshiftLL (MOVWconst [c]) x [d]) => (CMNconst [c] (SLLconst <x.Type> x [d]))
+(CMNshiftRL (MOVWconst [c]) x [d]) => (CMNconst [c] (SRLconst <x.Type> x [d]))
+(CMNshiftRA (MOVWconst [c]) x [d]) => (CMNconst [c] (SRAconst <x.Type> x [d]))
+
+(ADDshiftLLreg (MOVWconst [c]) x y) => (ADDconst [c] (SLL <x.Type> x y))
+(ADDshiftRLreg (MOVWconst [c]) x y) => (ADDconst [c] (SRL <x.Type> x y))
+(ADDshiftRAreg (MOVWconst [c]) x y) => (ADDconst [c] (SRA <x.Type> x y))
+(ADCshiftLLreg (MOVWconst [c]) x y flags) => (ADCconst [c] (SLL <x.Type> x y) flags)
+(ADCshiftRLreg (MOVWconst [c]) x y flags) => (ADCconst [c] (SRL <x.Type> x y) flags)
+(ADCshiftRAreg (MOVWconst [c]) x y flags) => (ADCconst [c] (SRA <x.Type> x y) flags)
+(ADDSshiftLLreg (MOVWconst [c]) x y) => (ADDSconst [c] (SLL <x.Type> x y))
+(ADDSshiftRLreg (MOVWconst [c]) x y) => (ADDSconst [c] (SRL <x.Type> x y))
+(ADDSshiftRAreg (MOVWconst [c]) x y) => (ADDSconst [c] (SRA <x.Type> x y))
+(SUBshiftLLreg (MOVWconst [c]) x y) => (RSBconst [c] (SLL <x.Type> x y))
+(SUBshiftRLreg (MOVWconst [c]) x y) => (RSBconst [c] (SRL <x.Type> x y))
+(SUBshiftRAreg (MOVWconst [c]) x y) => (RSBconst [c] (SRA <x.Type> x y))
+(SBCshiftLLreg (MOVWconst [c]) x y flags) => (RSCconst [c] (SLL <x.Type> x y) flags)
+(SBCshiftRLreg (MOVWconst [c]) x y flags) => (RSCconst [c] (SRL <x.Type> x y) flags)
+(SBCshiftRAreg (MOVWconst [c]) x y flags) => (RSCconst [c] (SRA <x.Type> x y) flags)
+(SUBSshiftLLreg (MOVWconst [c]) x y) => (RSBSconst [c] (SLL <x.Type> x y))
+(SUBSshiftRLreg (MOVWconst [c]) x y) => (RSBSconst [c] (SRL <x.Type> x y))
+(SUBSshiftRAreg (MOVWconst [c]) x y) => (RSBSconst [c] (SRA <x.Type> x y))
+(RSBshiftLLreg (MOVWconst [c]) x y) => (SUBconst [c] (SLL <x.Type> x y))
+(RSBshiftRLreg (MOVWconst [c]) x y) => (SUBconst [c] (SRL <x.Type> x y))
+(RSBshiftRAreg (MOVWconst [c]) x y) => (SUBconst [c] (SRA <x.Type> x y))
+(RSCshiftLLreg (MOVWconst [c]) x y flags) => (SBCconst [c] (SLL <x.Type> x y) flags)
+(RSCshiftRLreg (MOVWconst [c]) x y flags) => (SBCconst [c] (SRL <x.Type> x y) flags)
+(RSCshiftRAreg (MOVWconst [c]) x y flags) => (SBCconst [c] (SRA <x.Type> x y) flags)
+(RSBSshiftLLreg (MOVWconst [c]) x y) => (SUBSconst [c] (SLL <x.Type> x y))
+(RSBSshiftRLreg (MOVWconst [c]) x y) => (SUBSconst [c] (SRL <x.Type> x y))
+(RSBSshiftRAreg (MOVWconst [c]) x y) => (SUBSconst [c] (SRA <x.Type> x y))
+(ANDshiftLLreg (MOVWconst [c]) x y) => (ANDconst [c] (SLL <x.Type> x y))
+(ANDshiftRLreg (MOVWconst [c]) x y) => (ANDconst [c] (SRL <x.Type> x y))
+(ANDshiftRAreg (MOVWconst [c]) x y) => (ANDconst [c] (SRA <x.Type> x y))
+(ORshiftLLreg (MOVWconst [c]) x y) => (ORconst [c] (SLL <x.Type> x y))
+(ORshiftRLreg (MOVWconst [c]) x y) => (ORconst [c] (SRL <x.Type> x y))
+(ORshiftRAreg (MOVWconst [c]) x y) => (ORconst [c] (SRA <x.Type> x y))
+(XORshiftLLreg (MOVWconst [c]) x y) => (XORconst [c] (SLL <x.Type> x y))
+(XORshiftRLreg (MOVWconst [c]) x y) => (XORconst [c] (SRL <x.Type> x y))
+(XORshiftRAreg (MOVWconst [c]) x y) => (XORconst [c] (SRA <x.Type> x y))
+(CMPshiftLLreg (MOVWconst [c]) x y) => (InvertFlags (CMPconst [c] (SLL <x.Type> x y)))
+(CMPshiftRLreg (MOVWconst [c]) x y) => (InvertFlags (CMPconst [c] (SRL <x.Type> x y)))
+(CMPshiftRAreg (MOVWconst [c]) x y) => (InvertFlags (CMPconst [c] (SRA <x.Type> x y)))
+(TSTshiftLLreg (MOVWconst [c]) x y) => (TSTconst [c] (SLL <x.Type> x y))
+(TSTshiftRLreg (MOVWconst [c]) x y) => (TSTconst [c] (SRL <x.Type> x y))
+(TSTshiftRAreg (MOVWconst [c]) x y) => (TSTconst [c] (SRA <x.Type> x y))
+(TEQshiftLLreg (MOVWconst [c]) x y) => (TEQconst [c] (SLL <x.Type> x y))
+(TEQshiftRLreg (MOVWconst [c]) x y) => (TEQconst [c] (SRL <x.Type> x y))
+(TEQshiftRAreg (MOVWconst [c]) x y) => (TEQconst [c] (SRA <x.Type> x y))
+(CMNshiftLLreg (MOVWconst [c]) x y) => (CMNconst [c] (SLL <x.Type> x y))
+(CMNshiftRLreg (MOVWconst [c]) x y) => (CMNconst [c] (SRL <x.Type> x y))
+(CMNshiftRAreg (MOVWconst [c]) x y) => (CMNconst [c] (SRA <x.Type> x y))
+
+// constant folding in *shift ops
+(ADDshiftLL x (MOVWconst [c]) [d]) => (ADDconst x [c<<uint64(d)])
+(ADDshiftRL x (MOVWconst [c]) [d]) => (ADDconst x [int32(uint32(c)>>uint64(d))])
+(ADDshiftRA x (MOVWconst [c]) [d]) => (ADDconst x [c>>uint64(d)])
+(ADCshiftLL x (MOVWconst [c]) [d] flags) => (ADCconst x [c<<uint64(d)] flags)
+(ADCshiftRL x (MOVWconst [c]) [d] flags) => (ADCconst x [int32(uint32(c)>>uint64(d))] flags)
+(ADCshiftRA x (MOVWconst [c]) [d] flags) => (ADCconst x [c>>uint64(d)] flags)
+(ADDSshiftLL x (MOVWconst [c]) [d]) => (ADDSconst x [c<<uint64(d)])
+(ADDSshiftRL x (MOVWconst [c]) [d]) => (ADDSconst x [int32(uint32(c)>>uint64(d))])
+(ADDSshiftRA x (MOVWconst [c]) [d]) => (ADDSconst x [c>>uint64(d)])
+(SUBshiftLL x (MOVWconst [c]) [d]) => (SUBconst x [c<<uint64(d)])
+(SUBshiftRL x (MOVWconst [c]) [d]) => (SUBconst x [int32(uint32(c)>>uint64(d))])
+(SUBshiftRA x (MOVWconst [c]) [d]) => (SUBconst x [c>>uint64(d)])
+(SBCshiftLL x (MOVWconst [c]) [d] flags) => (SBCconst x [c<<uint64(d)] flags)
+(SBCshiftRL x (MOVWconst [c]) [d] flags) => (SBCconst x [int32(uint32(c)>>uint64(d))] flags)
+(SBCshiftRA x (MOVWconst [c]) [d] flags) => (SBCconst x [c>>uint64(d)] flags)
+(SUBSshiftLL x (MOVWconst [c]) [d]) => (SUBSconst x [c<<uint64(d)])
+(SUBSshiftRL x (MOVWconst [c]) [d]) => (SUBSconst x [int32(uint32(c)>>uint64(d))])
+(SUBSshiftRA x (MOVWconst [c]) [d]) => (SUBSconst x [c>>uint64(d)])
+(RSBshiftLL x (MOVWconst [c]) [d]) => (RSBconst x [c<<uint64(d)])
+(RSBshiftRL x (MOVWconst [c]) [d]) => (RSBconst x [int32(uint32(c)>>uint64(d))])
+(RSBshiftRA x (MOVWconst [c]) [d]) => (RSBconst x [c>>uint64(d)])
+(RSCshiftLL x (MOVWconst [c]) [d] flags) => (RSCconst x [c<<uint64(d)] flags)
+(RSCshiftRL x (MOVWconst [c]) [d] flags) => (RSCconst x [int32(uint32(c)>>uint64(d))] flags)
+(RSCshiftRA x (MOVWconst [c]) [d] flags) => (RSCconst x [c>>uint64(d)] flags)
+(RSBSshiftLL x (MOVWconst [c]) [d]) => (RSBSconst x [c<<uint64(d)])
+(RSBSshiftRL x (MOVWconst [c]) [d]) => (RSBSconst x [int32(uint32(c)>>uint64(d))])
+(RSBSshiftRA x (MOVWconst [c]) [d]) => (RSBSconst x [c>>uint64(d)])
+(ANDshiftLL x (MOVWconst [c]) [d]) => (ANDconst x [c<<uint64(d)])
+(ANDshiftRL x (MOVWconst [c]) [d]) => (ANDconst x [int32(uint32(c)>>uint64(d))])
+(ANDshiftRA x (MOVWconst [c]) [d]) => (ANDconst x [c>>uint64(d)])
+(ORshiftLL x (MOVWconst [c]) [d]) => (ORconst x [c<<uint64(d)])
+(ORshiftRL x (MOVWconst [c]) [d]) => (ORconst x [int32(uint32(c)>>uint64(d))])
+(ORshiftRA x (MOVWconst [c]) [d]) => (ORconst x [c>>uint64(d)])
+(XORshiftLL x (MOVWconst [c]) [d]) => (XORconst x [c<<uint64(d)])
+(XORshiftRL x (MOVWconst [c]) [d]) => (XORconst x [int32(uint32(c)>>uint64(d))])
+(XORshiftRA x (MOVWconst [c]) [d]) => (XORconst x [c>>uint64(d)])
+(XORshiftRR x (MOVWconst [c]) [d]) => (XORconst x [int32(uint32(c)>>uint64(d)|uint32(c)<<uint64(32-d))])
+(BICshiftLL x (MOVWconst [c]) [d]) => (BICconst x [c<<uint64(d)])
+(BICshiftRL x (MOVWconst [c]) [d]) => (BICconst x [int32(uint32(c)>>uint64(d))])
+(BICshiftRA x (MOVWconst [c]) [d]) => (BICconst x [c>>uint64(d)])
+(MVNshiftLL (MOVWconst [c]) [d]) => (MOVWconst [^(c<<uint64(d))])
+(MVNshiftRL (MOVWconst [c]) [d]) => (MOVWconst [^int32(uint32(c)>>uint64(d))])
+(MVNshiftRA (MOVWconst [c]) [d]) => (MOVWconst [int32(c)>>uint64(d)])
+(CMPshiftLL x (MOVWconst [c]) [d]) => (CMPconst x [c<<uint64(d)])
+(CMPshiftRL x (MOVWconst [c]) [d]) => (CMPconst x [int32(uint32(c)>>uint64(d))])
+(CMPshiftRA x (MOVWconst [c]) [d]) => (CMPconst x [c>>uint64(d)])
+(TSTshiftLL x (MOVWconst [c]) [d]) => (TSTconst x [c<<uint64(d)])
+(TSTshiftRL x (MOVWconst [c]) [d]) => (TSTconst x [int32(uint32(c)>>uint64(d))])
+(TSTshiftRA x (MOVWconst [c]) [d]) => (TSTconst x [c>>uint64(d)])
+(TEQshiftLL x (MOVWconst [c]) [d]) => (TEQconst x [c<<uint64(d)])
+(TEQshiftRL x (MOVWconst [c]) [d]) => (TEQconst x [int32(uint32(c)>>uint64(d))])
+(TEQshiftRA x (MOVWconst [c]) [d]) => (TEQconst x [c>>uint64(d)])
+(CMNshiftLL x (MOVWconst [c]) [d]) => (CMNconst x [c<<uint64(d)])
+(CMNshiftRL x (MOVWconst [c]) [d]) => (CMNconst x [int32(uint32(c)>>uint64(d))])
+(CMNshiftRA x (MOVWconst [c]) [d]) => (CMNconst x [c>>uint64(d)])
+
+(ADDshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDshiftLL x y [c])
+(ADDshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDshiftRL x y [c])
+(ADDshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDshiftRA x y [c])
+(ADCshiftLLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (ADCshiftLL x y [c] flags)
+(ADCshiftRLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (ADCshiftRL x y [c] flags)
+(ADCshiftRAreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (ADCshiftRA x y [c] flags)
+(ADDSshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDSshiftLL x y [c])
+(ADDSshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDSshiftRL x y [c])
+(ADDSshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDSshiftRA x y [c])
+(SUBshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBshiftLL x y [c])
+(SUBshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBshiftRL x y [c])
+(SUBshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBshiftRA x y [c])
+(SBCshiftLLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (SBCshiftLL x y [c] flags)
+(SBCshiftRLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (SBCshiftRL x y [c] flags)
+(SBCshiftRAreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (SBCshiftRA x y [c] flags)
+(SUBSshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBSshiftLL x y [c])
+(SUBSshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBSshiftRL x y [c])
+(SUBSshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBSshiftRA x y [c])
+(RSBshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBshiftLL x y [c])
+(RSBshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBshiftRL x y [c])
+(RSBshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBshiftRA x y [c])
+(RSCshiftLLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (RSCshiftLL x y [c] flags)
+(RSCshiftRLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (RSCshiftRL x y [c] flags)
+(RSCshiftRAreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (RSCshiftRA x y [c] flags)
+(RSBSshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBSshiftLL x y [c])
+(RSBSshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBSshiftRL x y [c])
+(RSBSshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBSshiftRA x y [c])
+(ANDshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ANDshiftLL x y [c])
+(ANDshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ANDshiftRL x y [c])
+(ANDshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ANDshiftRA x y [c])
+(ORshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ORshiftLL x y [c])
+(ORshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ORshiftRL x y [c])
+(ORshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ORshiftRA x y [c])
+(XORshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (XORshiftLL x y [c])
+(XORshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (XORshiftRL x y [c])
+(XORshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (XORshiftRA x y [c])
+(BICshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (BICshiftLL x y [c])
+(BICshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (BICshiftRL x y [c])
+(BICshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (BICshiftRA x y [c])
+(MVNshiftLLreg x (MOVWconst [c])) && 0 <= c && c < 32 => (MVNshiftLL x [c])
+(MVNshiftRLreg x (MOVWconst [c])) && 0 <= c && c < 32 => (MVNshiftRL x [c])
+(MVNshiftRAreg x (MOVWconst [c])) && 0 <= c && c < 32 => (MVNshiftRA x [c])
+(CMPshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMPshiftLL x y [c])
+(CMPshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMPshiftRL x y [c])
+(CMPshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMPshiftRA x y [c])
+(TSTshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TSTshiftLL x y [c])
+(TSTshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TSTshiftRL x y [c])
+(TSTshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TSTshiftRA x y [c])
+(TEQshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TEQshiftLL x y [c])
+(TEQshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TEQshiftRL x y [c])
+(TEQshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TEQshiftRA x y [c])
+(CMNshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMNshiftLL x y [c])
+(CMNshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMNshiftRL x y [c])
+(CMNshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMNshiftRA x y [c])
+
+// Generate rotates
+(ADDshiftLL [c] (SRLconst x [32-c]) x) => (SRRconst [32-c] x)
+( ORshiftLL [c] (SRLconst x [32-c]) x) => (SRRconst [32-c] x)
+(XORshiftLL [c] (SRLconst x [32-c]) x) => (SRRconst [32-c] x)
+(ADDshiftRL [c] (SLLconst x [32-c]) x) => (SRRconst [ c] x)
+( ORshiftRL [c] (SLLconst x [32-c]) x) => (SRRconst [ c] x)
+(XORshiftRL [c] (SLLconst x [32-c]) x) => (SRRconst [ c] x)
+
+(RotateLeft32 x (MOVWconst [c])) => (SRRconst [-c&31] x)
+(RotateLeft16 <t> x (MOVWconst [c])) => (Or16 (Lsh16x32 <t> x (MOVWconst [c&15])) (Rsh16Ux32 <t> x (MOVWconst [-c&15])))
+(RotateLeft8 <t> x (MOVWconst [c])) => (Or8 (Lsh8x32 <t> x (MOVWconst [c&7])) (Rsh8Ux32 <t> x (MOVWconst [-c&7])))
+(RotateLeft32 x y) => (SRR x (RSBconst [0] <y.Type> y))
+
+// ((x>>8) | (x<<8)) -> (REV16 x), the type of x is uint16, "|" can also be "^" or "+".
+// UBFX instruction is supported by ARMv6T2, ARMv7 and above versions, REV16 is supported by
+// ARMv6 and above versions. So for ARMv6, we need to match SLLconst, SRLconst and ORshiftLL.
+((ADDshiftLL|ORshiftLL|XORshiftLL) <typ.UInt16> [8] (BFXU <typ.UInt16> [int32(armBFAuxInt(8, 8))] x) x) => (REV16 x)
+((ADDshiftLL|ORshiftLL|XORshiftLL) <typ.UInt16> [8] (SRLconst <typ.UInt16> [24] (SLLconst [16] x)) x) && objabi.GOARM>=6 => (REV16 x)
+
+// use indexed loads and stores
+(MOVWload [0] {sym} (ADD ptr idx) mem) && sym == nil => (MOVWloadidx ptr idx mem)
+(MOVWstore [0] {sym} (ADD ptr idx) val mem) && sym == nil => (MOVWstoreidx ptr idx val mem)
+(MOVWload [0] {sym} (ADDshiftLL ptr idx [c]) mem) && sym == nil => (MOVWloadshiftLL ptr idx [c] mem)
+(MOVWload [0] {sym} (ADDshiftRL ptr idx [c]) mem) && sym == nil => (MOVWloadshiftRL ptr idx [c] mem)
+(MOVWload [0] {sym} (ADDshiftRA ptr idx [c]) mem) && sym == nil => (MOVWloadshiftRA ptr idx [c] mem)
+(MOVWstore [0] {sym} (ADDshiftLL ptr idx [c]) val mem) && sym == nil => (MOVWstoreshiftLL ptr idx [c] val mem)
+(MOVWstore [0] {sym} (ADDshiftRL ptr idx [c]) val mem) && sym == nil => (MOVWstoreshiftRL ptr idx [c] val mem)
+(MOVWstore [0] {sym} (ADDshiftRA ptr idx [c]) val mem) && sym == nil => (MOVWstoreshiftRA ptr idx [c] val mem)
+(MOVBUload [0] {sym} (ADD ptr idx) mem) && sym == nil => (MOVBUloadidx ptr idx mem)
+(MOVBload [0] {sym} (ADD ptr idx) mem) && sym == nil => (MOVBloadidx ptr idx mem)
+(MOVBstore [0] {sym} (ADD ptr idx) val mem) && sym == nil => (MOVBstoreidx ptr idx val mem)
+(MOVHUload [0] {sym} (ADD ptr idx) mem) && sym == nil => (MOVHUloadidx ptr idx mem)
+(MOVHload [0] {sym} (ADD ptr idx) mem) && sym == nil => (MOVHloadidx ptr idx mem)
+(MOVHstore [0] {sym} (ADD ptr idx) val mem) && sym == nil => (MOVHstoreidx ptr idx val mem)
+
+// constant folding in indexed loads and stores
+(MOVWloadidx ptr (MOVWconst [c]) mem) => (MOVWload [c] ptr mem)
+(MOVWloadidx (MOVWconst [c]) ptr mem) => (MOVWload [c] ptr mem)
+(MOVBloadidx ptr (MOVWconst [c]) mem) => (MOVBload [c] ptr mem)
+(MOVBloadidx (MOVWconst [c]) ptr mem) => (MOVBload [c] ptr mem)
+(MOVBUloadidx ptr (MOVWconst [c]) mem) => (MOVBUload [c] ptr mem)
+(MOVBUloadidx (MOVWconst [c]) ptr mem) => (MOVBUload [c] ptr mem)
+(MOVHUloadidx ptr (MOVWconst [c]) mem) => (MOVHUload [c] ptr mem)
+(MOVHUloadidx (MOVWconst [c]) ptr mem) => (MOVHUload [c] ptr mem)
+(MOVHloadidx ptr (MOVWconst [c]) mem) => (MOVHload [c] ptr mem)
+(MOVHloadidx (MOVWconst [c]) ptr mem) => (MOVHload [c] ptr mem)
+
+(MOVWstoreidx ptr (MOVWconst [c]) val mem) => (MOVWstore [c] ptr val mem)
+(MOVWstoreidx (MOVWconst [c]) ptr val mem) => (MOVWstore [c] ptr val mem)
+(MOVBstoreidx ptr (MOVWconst [c]) val mem) => (MOVBstore [c] ptr val mem)
+(MOVBstoreidx (MOVWconst [c]) ptr val mem) => (MOVBstore [c] ptr val mem)
+(MOVHstoreidx ptr (MOVWconst [c]) val mem) => (MOVHstore [c] ptr val mem)
+(MOVHstoreidx (MOVWconst [c]) ptr val mem) => (MOVHstore [c] ptr val mem)
+
+(MOVWloadidx ptr (SLLconst idx [c]) mem) => (MOVWloadshiftLL ptr idx [c] mem)
+(MOVWloadidx (SLLconst idx [c]) ptr mem) => (MOVWloadshiftLL ptr idx [c] mem)
+(MOVWloadidx ptr (SRLconst idx [c]) mem) => (MOVWloadshiftRL ptr idx [c] mem)
+(MOVWloadidx (SRLconst idx [c]) ptr mem) => (MOVWloadshiftRL ptr idx [c] mem)
+(MOVWloadidx ptr (SRAconst idx [c]) mem) => (MOVWloadshiftRA ptr idx [c] mem)
+(MOVWloadidx (SRAconst idx [c]) ptr mem) => (MOVWloadshiftRA ptr idx [c] mem)
+
+(MOVWstoreidx ptr (SLLconst idx [c]) val mem) => (MOVWstoreshiftLL ptr idx [c] val mem)
+(MOVWstoreidx (SLLconst idx [c]) ptr val mem) => (MOVWstoreshiftLL ptr idx [c] val mem)
+(MOVWstoreidx ptr (SRLconst idx [c]) val mem) => (MOVWstoreshiftRL ptr idx [c] val mem)
+(MOVWstoreidx (SRLconst idx [c]) ptr val mem) => (MOVWstoreshiftRL ptr idx [c] val mem)
+(MOVWstoreidx ptr (SRAconst idx [c]) val mem) => (MOVWstoreshiftRA ptr idx [c] val mem)
+(MOVWstoreidx (SRAconst idx [c]) ptr val mem) => (MOVWstoreshiftRA ptr idx [c] val mem)
+
+(MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem) => (MOVWload [int32(uint32(c)<<uint64(d))] ptr mem)
+(MOVWloadshiftRL ptr (MOVWconst [c]) [d] mem) => (MOVWload [int32(uint32(c)>>uint64(d))] ptr mem)
+(MOVWloadshiftRA ptr (MOVWconst [c]) [d] mem) => (MOVWload [c>>uint64(d)] ptr mem)
+
+(MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem) => (MOVWstore [int32(uint32(c)<<uint64(d))] ptr val mem)
+(MOVWstoreshiftRL ptr (MOVWconst [c]) [d] val mem) => (MOVWstore [int32(uint32(c)>>uint64(d))] ptr val mem)
+(MOVWstoreshiftRA ptr (MOVWconst [c]) [d] val mem) => (MOVWstore [c>>uint64(d)] ptr val mem)
+
+// generic simplifications
+(ADD x (RSBconst [0] y)) => (SUB x y)
+(ADD <t> (RSBconst [c] x) (RSBconst [d] y)) => (RSBconst [c+d] (ADD <t> x y))
+(SUB x x) => (MOVWconst [0])
+(RSB x x) => (MOVWconst [0])
+(AND x x) => x
+(OR x x) => x
+(XOR x x) => (MOVWconst [0])
+(BIC x x) => (MOVWconst [0])
+
+(ADD (MUL x y) a) => (MULA x y a)
+(SUB a (MUL x y)) && objabi.GOARM == 7 => (MULS x y a)
+(RSB (MUL x y) a) && objabi.GOARM == 7 => (MULS x y a)
+
+(NEGF (MULF x y)) && objabi.GOARM >= 6 => (NMULF x y)
+(NEGD (MULD x y)) && objabi.GOARM >= 6 => (NMULD x y)
+(MULF (NEGF x) y) && objabi.GOARM >= 6 => (NMULF x y)
+(MULD (NEGD x) y) && objabi.GOARM >= 6 => (NMULD x y)
+(NMULF (NEGF x) y) => (MULF x y)
+(NMULD (NEGD x) y) => (MULD x y)
+
+// the result will overwrite the addend, since they are in the same register
+(ADDF a (MULF x y)) && a.Uses == 1 && objabi.GOARM >= 6 => (MULAF a x y)
+(ADDF a (NMULF x y)) && a.Uses == 1 && objabi.GOARM >= 6 => (MULSF a x y)
+(ADDD a (MULD x y)) && a.Uses == 1 && objabi.GOARM >= 6 => (MULAD a x y)
+(ADDD a (NMULD x y)) && a.Uses == 1 && objabi.GOARM >= 6 => (MULSD a x y)
+(SUBF a (MULF x y)) && a.Uses == 1 && objabi.GOARM >= 6 => (MULSF a x y)
+(SUBF a (NMULF x y)) && a.Uses == 1 && objabi.GOARM >= 6 => (MULAF a x y)
+(SUBD a (MULD x y)) && a.Uses == 1 && objabi.GOARM >= 6 => (MULSD a x y)
+(SUBD a (NMULD x y)) && a.Uses == 1 && objabi.GOARM >= 6 => (MULAD a x y)
+
+(AND x (MVN y)) => (BIC x y)
+
+// simplification with *shift ops
+(SUBshiftLL (SLLconst x [c]) x [c]) => (MOVWconst [0])
+(SUBshiftRL (SRLconst x [c]) x [c]) => (MOVWconst [0])
+(SUBshiftRA (SRAconst x [c]) x [c]) => (MOVWconst [0])
+(RSBshiftLL (SLLconst x [c]) x [c]) => (MOVWconst [0])
+(RSBshiftRL (SRLconst x [c]) x [c]) => (MOVWconst [0])
+(RSBshiftRA (SRAconst x [c]) x [c]) => (MOVWconst [0])
+(ANDshiftLL y:(SLLconst x [c]) x [c]) => y
+(ANDshiftRL y:(SRLconst x [c]) x [c]) => y
+(ANDshiftRA y:(SRAconst x [c]) x [c]) => y
+(ORshiftLL y:(SLLconst x [c]) x [c]) => y
+(ORshiftRL y:(SRLconst x [c]) x [c]) => y
+(ORshiftRA y:(SRAconst x [c]) x [c]) => y
+(XORshiftLL (SLLconst x [c]) x [c]) => (MOVWconst [0])
+(XORshiftRL (SRLconst x [c]) x [c]) => (MOVWconst [0])
+(XORshiftRA (SRAconst x [c]) x [c]) => (MOVWconst [0])
+(BICshiftLL (SLLconst x [c]) x [c]) => (MOVWconst [0])
+(BICshiftRL (SRLconst x [c]) x [c]) => (MOVWconst [0])
+(BICshiftRA (SRAconst x [c]) x [c]) => (MOVWconst [0])
+(AND x (MVNshiftLL y [c])) => (BICshiftLL x y [c])
+(AND x (MVNshiftRL y [c])) => (BICshiftRL x y [c])
+(AND x (MVNshiftRA y [c])) => (BICshiftRA x y [c])
+
+// floating point optimizations
+(CMPF x (MOVFconst [0])) => (CMPF0 x)
+(CMPD x (MOVDconst [0])) => (CMPD0 x)
+
+// bit extraction
+(SRAconst (SLLconst x [c]) [d]) && objabi.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31 => (BFX [(d-c)|(32-d)<<8] x)
+(SRLconst (SLLconst x [c]) [d]) && objabi.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31 => (BFXU [(d-c)|(32-d)<<8] x)
+
+// comparison simplification
+((LT|LE|EQ|NE|GE|GT) (CMP x (RSBconst [0] y))) => ((LT|LE|EQ|NE|GE|GT) (CMN x y)) // sense of carry bit not preserved
+((LT|LE|EQ|NE|GE|GT) (CMN x (RSBconst [0] y))) => ((LT|LE|EQ|NE|GE|GT) (CMP x y)) // sense of carry bit not preserved
+(EQ (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (EQ (CMP x y) yes no)
+(EQ (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (EQ (CMP a (MUL <x.Type> x y)) yes no)
+(EQ (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (EQ (CMPconst [c] x) yes no)
+(EQ (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 => (EQ (CMPshiftLL x y [c]) yes no)
+(EQ (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 => (EQ (CMPshiftRL x y [c]) yes no)
+(EQ (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 => (EQ (CMPshiftRA x y [c]) yes no)
+(EQ (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 => (EQ (CMPshiftLLreg x y z) yes no)
+(EQ (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 => (EQ (CMPshiftRLreg x y z) yes no)
+(EQ (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 => (EQ (CMPshiftRAreg x y z) yes no)
+(NE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (NE (CMP x y) yes no)
+(NE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (NE (CMP a (MUL <x.Type> x y)) yes no)
+(NE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (NE (CMPconst [c] x) yes no)
+(NE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 => (NE (CMPshiftLL x y [c]) yes no)
+(NE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 => (NE (CMPshiftRL x y [c]) yes no)
+(NE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 => (NE (CMPshiftRA x y [c]) yes no)
+(NE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 => (NE (CMPshiftLLreg x y z) yes no)
+(NE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 => (NE (CMPshiftRLreg x y z) yes no)
+(NE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 => (NE (CMPshiftRAreg x y z) yes no)
+(EQ (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 => (EQ (CMN x y) yes no)
+(EQ (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 => (EQ (CMN a (MUL <x.Type> x y)) yes no)
+(EQ (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 => (EQ (CMNconst [c] x) yes no)
+(EQ (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 => (EQ (CMNshiftLL x y [c]) yes no)
+(EQ (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 => (EQ (CMNshiftRL x y [c]) yes no)
+(EQ (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 => (EQ (CMNshiftRA x y [c]) yes no)
+(EQ (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 => (EQ (CMNshiftLLreg x y z) yes no)
+(EQ (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 => (EQ (CMNshiftRLreg x y z) yes no)
+(EQ (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 => (EQ (CMNshiftRAreg x y z) yes no)
+(NE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 => (NE (CMN x y) yes no)
+(NE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 => (NE (CMN a (MUL <x.Type> x y)) yes no)
+(NE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 => (NE (CMNconst [c] x) yes no)
+(NE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 => (NE (CMNshiftLL x y [c]) yes no)
+(NE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 => (NE (CMNshiftRL x y [c]) yes no)
+(NE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 => (NE (CMNshiftRA x y [c]) yes no)
+(NE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 => (NE (CMNshiftLLreg x y z) yes no)
+(NE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 => (NE (CMNshiftRLreg x y z) yes no)
+(NE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 => (NE (CMNshiftRAreg x y z) yes no)
+(EQ (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (EQ (TST x y) yes no)
+(EQ (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (EQ (TSTconst [c] x) yes no)
+(EQ (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (EQ (TSTshiftLL x y [c]) yes no)
+(EQ (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (EQ (TSTshiftRL x y [c]) yes no)
+(EQ (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (EQ (TSTshiftRA x y [c]) yes no)
+(EQ (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (EQ (TSTshiftLLreg x y z) yes no)
+(EQ (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (EQ (TSTshiftRLreg x y z) yes no)
+(EQ (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (EQ (TSTshiftRAreg x y z) yes no)
+(NE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (NE (TST x y) yes no)
+(NE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (NE (TSTconst [c] x) yes no)
+(NE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (NE (TSTshiftLL x y [c]) yes no)
+(NE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (NE (TSTshiftRL x y [c]) yes no)
+(NE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (NE (TSTshiftRA x y [c]) yes no)
+(NE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (NE (TSTshiftLLreg x y z) yes no)
+(NE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (NE (TSTshiftRLreg x y z) yes no)
+(NE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (NE (TSTshiftRAreg x y z) yes no)
+(EQ (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (EQ (TEQ x y) yes no)
+(EQ (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (EQ (TEQconst [c] x) yes no)
+(EQ (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (EQ (TEQshiftLL x y [c]) yes no)
+(EQ (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (EQ (TEQshiftRL x y [c]) yes no)
+(EQ (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (EQ (TEQshiftRA x y [c]) yes no)
+(EQ (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (EQ (TEQshiftLLreg x y z) yes no)
+(EQ (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (EQ (TEQshiftRLreg x y z) yes no)
+(EQ (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (EQ (TEQshiftRAreg x y z) yes no)
+(NE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (NE (TEQ x y) yes no)
+(NE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (NE (TEQconst [c] x) yes no)
+(NE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (NE (TEQshiftLL x y [c]) yes no)
+(NE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (NE (TEQshiftRL x y [c]) yes no)
+(NE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (NE (TEQshiftRA x y [c]) yes no)
+(NE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (NE (TEQshiftLLreg x y z) yes no)
+(NE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (NE (TEQshiftRLreg x y z) yes no)
+(NE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (NE (TEQshiftRAreg x y z) yes no)
+(LT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (LTnoov (CMP x y) yes no)
+(LT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (LTnoov (CMP a (MUL <x.Type> x y)) yes no)
+(LT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (LTnoov (CMPconst [c] x) yes no)
+(LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 => (LTnoov (CMPshiftLL x y [c]) yes no)
+(LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 => (LTnoov (CMPshiftRL x y [c]) yes no)
+(LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 => (LTnoov (CMPshiftRA x y [c]) yes no)
+(LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 => (LTnoov (CMPshiftLLreg x y z) yes no)
+(LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 => (LTnoov (CMPshiftRLreg x y z) yes no)
+(LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 => (LTnoov (CMPshiftRAreg x y z) yes no)
+(LE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (LEnoov (CMP x y) yes no)
+(LE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (LEnoov (CMP a (MUL <x.Type> x y)) yes no)
+(LE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (LEnoov (CMPconst [c] x) yes no)
+(LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 => (LEnoov (CMPshiftLL x y [c]) yes no)
+(LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 => (LEnoov (CMPshiftRL x y [c]) yes no)
+(LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 => (LEnoov (CMPshiftRA x y [c]) yes no)
+(LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMPshiftLLreg x y z) yes no)
+(LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMPshiftRLreg x y z) yes no)
+(LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMPshiftRAreg x y z) yes no)
+(LT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 => (LTnoov (CMN x y) yes no)
+(LT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 => (LTnoov (CMN a (MUL <x.Type> x y)) yes no)
+(LT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 => (LTnoov (CMNconst [c] x) yes no)
+(LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 => (LTnoov (CMNshiftLL x y [c]) yes no)
+(LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 => (LTnoov (CMNshiftRL x y [c]) yes no)
+(LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 => (LTnoov (CMNshiftRA x y [c]) yes no)
+(LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 => (LTnoov (CMNshiftLLreg x y z) yes no)
+(LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 => (LTnoov (CMNshiftRLreg x y z) yes no)
+(LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 => (LTnoov (CMNshiftRAreg x y z) yes no)
+(LE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 => (LEnoov (CMN x y) yes no)
+(LE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 => (LEnoov (CMN a (MUL <x.Type> x y)) yes no)
+(LE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 => (LEnoov (CMNconst [c] x) yes no)
+(LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 => (LEnoov (CMNshiftLL x y [c]) yes no)
+(LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 => (LEnoov (CMNshiftRL x y [c]) yes no)
+(LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 => (LEnoov (CMNshiftRA x y [c]) yes no)
+(LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMNshiftLLreg x y z) yes no)
+(LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMNshiftRLreg x y z) yes no)
+(LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMNshiftRAreg x y z) yes no)
+(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (LTnoov (TST x y) yes no)
+(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (LTnoov (TSTconst [c] x) yes no)
+(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (LTnoov (TSTshiftLL x y [c]) yes no)
+(LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (LTnoov (TSTshiftRL x y [c]) yes no)
+(LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (LTnoov (TSTshiftRA x y [c]) yes no)
+(LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TSTshiftLLreg x y z) yes no)
+(LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TSTshiftRLreg x y z) yes no)
+(LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (LTnoov (TSTshiftRAreg x y z) yes no)
+(LE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (LEnoov (TST x y) yes no)
+(LE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (LEnoov (TSTconst [c] x) yes no)
+(LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (LEnoov (TSTshiftLL x y [c]) yes no)
+(LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (LEnoov (TSTshiftRL x y [c]) yes no)
+(LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (LEnoov (TSTshiftRA x y [c]) yes no)
+(LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TSTshiftLLreg x y z) yes no)
+(LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TSTshiftRLreg x y z) yes no)
+(LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (LEnoov (TSTshiftRAreg x y z) yes no)
+(LT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (LTnoov (TEQ x y) yes no)
+(LT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (LTnoov (TEQconst [c] x) yes no)
+(LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (LTnoov (TEQshiftLL x y [c]) yes no)
+(LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (LTnoov (TEQshiftRL x y [c]) yes no)
+(LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (LTnoov (TEQshiftRA x y [c]) yes no)
+(LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TEQshiftLLreg x y z) yes no)
+(LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TEQshiftRLreg x y z) yes no)
+(LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (LTnoov (TEQshiftRAreg x y z) yes no)
+(LE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (LEnoov (TEQ x y) yes no)
+(LE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (LEnoov (TEQconst [c] x) yes no)
+(LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (LEnoov (TEQshiftLL x y [c]) yes no)
+(LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (LEnoov (TEQshiftRL x y [c]) yes no)
+(LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (LEnoov (TEQshiftRA x y [c]) yes no)
+(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TEQshiftLLreg x y z) yes no)
+(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TEQshiftRLreg x y z) yes no)
+(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (LEnoov (TEQshiftRAreg x y z) yes no)
+(GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (GTnoov (CMP x y) yes no)
+(GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (GTnoov (CMP a (MUL <x.Type> x y)) yes no)
+(GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (GTnoov (CMPconst [c] x) yes no)
+(GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 => (GTnoov (CMPshiftLL x y [c]) yes no)
+(GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 => (GTnoov (CMPshiftRL x y [c]) yes no)
+(GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 => (GTnoov (CMPshiftRA x y [c]) yes no)
+(GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 => (GTnoov (CMPshiftLLreg x y z) yes no)
+(GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 => (GTnoov (CMPshiftRLreg x y z) yes no)
+(GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 => (GTnoov (CMPshiftRAreg x y z) yes no)
+(GE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (GEnoov (CMP x y) yes no)
+(GE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (GEnoov (CMP a (MUL <x.Type> x y)) yes no)
+(GE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (GEnoov (CMPconst [c] x) yes no)
+(GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 => (GEnoov (CMPshiftLL x y [c]) yes no)
+(GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 => (GEnoov (CMPshiftRL x y [c]) yes no)
+(GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 => (GEnoov (CMPshiftRA x y [c]) yes no)
+(GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMPshiftLLreg x y z) yes no)
+(GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMPshiftRLreg x y z) yes no)
+(GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMPshiftRAreg x y z) yes no)
+(GT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 => (GTnoov (CMN x y) yes no)
+(GT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 => (GTnoov (CMNconst [c] x) yes no)
+(GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 => (GTnoov (CMNshiftLL x y [c]) yes no)
+(GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 => (GTnoov (CMNshiftRL x y [c]) yes no)
+(GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 => (GTnoov (CMNshiftRA x y [c]) yes no)
+(GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 => (GTnoov (CMNshiftLLreg x y z) yes no)
+(GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 => (GTnoov (CMNshiftRLreg x y z) yes no)
+(GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 => (GTnoov (CMNshiftRAreg x y z) yes no)
+(GE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 => (GEnoov (CMN x y) yes no)
+(GE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 => (GEnoov (CMN a (MUL <x.Type> x y)) yes no)
+(GE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 => (GEnoov (CMNconst [c] x) yes no)
+(GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 => (GEnoov (CMNshiftLL x y [c]) yes no)
+(GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 => (GEnoov (CMNshiftRL x y [c]) yes no)
+(GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 => (GEnoov (CMNshiftRA x y [c]) yes no)
+(GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMNshiftLLreg x y z) yes no)
+(GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMNshiftRLreg x y z) yes no)
+(GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMNshiftRAreg x y z) yes no)
+(GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 => (GTnoov (CMN a (MUL <x.Type> x y)) yes no)
+(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (GTnoov (TST x y) yes no)
+(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (GTnoov (TSTconst [c] x) yes no)
+(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (GTnoov (TSTshiftLL x y [c]) yes no)
+(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (GTnoov (TSTshiftRL x y [c]) yes no)
+(GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (GTnoov (TSTshiftRA x y [c]) yes no)
+(GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TSTshiftLLreg x y z) yes no)
+(GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TSTshiftRLreg x y z) yes no)
+(GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (GTnoov (TSTshiftRAreg x y z) yes no)
+(GE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (GEnoov (TST x y) yes no)
+(GE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (GEnoov (TSTconst [c] x) yes no)
+(GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (GEnoov (TSTshiftLL x y [c]) yes no)
+(GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (GEnoov (TSTshiftRL x y [c]) yes no)
+(GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (GEnoov (TSTshiftRA x y [c]) yes no)
+(GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TSTshiftLLreg x y z) yes no)
+(GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TSTshiftRLreg x y z) yes no)
+(GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (GEnoov (TSTshiftRAreg x y z) yes no)
+(GT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (GTnoov (TEQ x y) yes no)
+(GT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (GTnoov (TEQconst [c] x) yes no)
+(GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (GTnoov (TEQshiftLL x y [c]) yes no)
+(GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (GTnoov (TEQshiftRL x y [c]) yes no)
+(GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (GTnoov (TEQshiftRA x y [c]) yes no)
+(GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TEQshiftLLreg x y z) yes no)
+(GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TEQshiftRLreg x y z) yes no)
+(GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (GTnoov (TEQshiftRAreg x y z) yes no)
+(GE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (GEnoov (TEQ x y) yes no)
+(GE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (GEnoov (TEQconst [c] x) yes no)
+(GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (GEnoov (TEQshiftLL x y [c]) yes no)
+(GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (GEnoov (TEQshiftRL x y [c]) yes no)
+(GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (GEnoov (TEQshiftRA x y [c]) yes no)
+(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TEQshiftLLreg x y z) yes no)
+(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TEQshiftRLreg x y z) yes no)
+(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (GEnoov (TEQshiftRAreg x y z) yes no)
+
+(MOVBUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVWconst [int32(read8(sym, int64(off)))])
+(MOVHUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVWconst [int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+(MOVWload [off] {sym} (SB) _) && symIsRO(sym) => (MOVWconst [int32(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules
new file mode 100644
index 0000000..80b4005
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules
@@ -0,0 +1,2789 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+(Add(Ptr|64|32|16|8) ...) => (ADD ...)
+(Add(32F|64F) ...) => (FADD(S|D) ...)
+
+(Sub(Ptr|64|32|16|8) ...) => (SUB ...)
+(Sub(32F|64F) ...) => (FSUB(S|D) ...)
+
+(Mul64 ...) => (MUL ...)
+(Mul(32|16|8) ...) => (MULW ...)
+(Mul(32F|64F) ...) => (FMUL(S|D) ...)
+
+(Hmul64 ...) => (MULH ...)
+(Hmul64u ...) => (UMULH ...)
+(Hmul32 x y) => (SRAconst (MULL <typ.Int64> x y) [32])
+(Hmul32u x y) => (SRAconst (UMULL <typ.UInt64> x y) [32])
+(Mul64uhilo ...) => (LoweredMuluhilo ...)
+
+(Div64 [false] x y) => (DIV x y)
+(Div64u ...) => (UDIV ...)
+(Div32 [false] x y) => (DIVW x y)
+(Div32u ...) => (UDIVW ...)
+(Div16 [false] x y) => (DIVW (SignExt16to32 x) (SignExt16to32 y))
+(Div16u x y) => (UDIVW (ZeroExt16to32 x) (ZeroExt16to32 y))
+(Div8 x y) => (DIVW (SignExt8to32 x) (SignExt8to32 y))
+(Div8u x y) => (UDIVW (ZeroExt8to32 x) (ZeroExt8to32 y))
+(Div32F ...) => (FDIVS ...)
+(Div64F ...) => (FDIVD ...)
+
+(Mod64 x y) => (MOD x y)
+(Mod64u ...) => (UMOD ...)
+(Mod32 x y) => (MODW x y)
+(Mod32u ...) => (UMODW ...)
+(Mod16 x y) => (MODW (SignExt16to32 x) (SignExt16to32 y))
+(Mod16u x y) => (UMODW (ZeroExt16to32 x) (ZeroExt16to32 y))
+(Mod8 x y) => (MODW (SignExt8to32 x) (SignExt8to32 y))
+(Mod8u x y) => (UMODW (ZeroExt8to32 x) (ZeroExt8to32 y))
+
+// (x + y) / 2 with x>=y => (x - y) / 2 + y
+(Avg64u <t> x y) => (ADD (SRLconst <t> (SUB <t> x y) [1]) y)
+
+(And(64|32|16|8) ...) => (AND ...)
+(Or(64|32|16|8) ...) => (OR ...)
+(Xor(64|32|16|8) ...) => (XOR ...)
+
+// unary ops
+(Neg(64|32|16|8) ...) => (NEG ...)
+(Neg(32F|64F) ...) => (FNEG(S|D) ...)
+(Com(64|32|16|8) ...) => (MVN ...)
+
+// math package intrinsics
+(Abs ...) => (FABSD ...)
+(Sqrt ...) => (FSQRTD ...)
+(Ceil ...) => (FRINTPD ...)
+(Floor ...) => (FRINTMD ...)
+(Round ...) => (FRINTAD ...)
+(RoundToEven ...) => (FRINTND ...)
+(Trunc ...) => (FRINTZD ...)
+(FMA x y z) => (FMADDD z x y)
+
+// lowering rotates
+(RotateLeft8 <t> x (MOVDconst [c])) => (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
+(RotateLeft16 <t> x (MOVDconst [c])) => (Or16 (Lsh16x64 <t> x (MOVDconst [c&15])) (Rsh16Ux64 <t> x (MOVDconst [-c&15])))
+(RotateLeft32 x y) => (RORW x (NEG <y.Type> y))
+(RotateLeft64 x y) => (ROR x (NEG <y.Type> y))
+
+(Ctz(64|32|16|8)NonZero ...) => (Ctz(64|32|32|32) ...)
+
+(Ctz64 <t> x) => (CLZ (RBIT <t> x))
+(Ctz32 <t> x) => (CLZW (RBITW <t> x))
+(Ctz16 <t> x) => (CLZW <t> (RBITW <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x)))
+(Ctz8 <t> x) => (CLZW <t> (RBITW <typ.UInt32> (ORconst <typ.UInt32> [0x100] x)))
+
+(PopCount64 <t> x) => (FMOVDfpgp <t> (VUADDLV <typ.Float64> (VCNT <typ.Float64> (FMOVDgpfp <typ.Float64> x))))
+(PopCount32 <t> x) => (FMOVDfpgp <t> (VUADDLV <typ.Float64> (VCNT <typ.Float64> (FMOVDgpfp <typ.Float64> (ZeroExt32to64 x)))))
+(PopCount16 <t> x) => (FMOVDfpgp <t> (VUADDLV <typ.Float64> (VCNT <typ.Float64> (FMOVDgpfp <typ.Float64> (ZeroExt16to64 x)))))
+
+// Load args directly into the register class where it will be used.
+(FMOVDgpfp <t> (Arg [off] {sym})) => @b.Func.Entry (Arg <t> [off] {sym})
+(FMOVDfpgp <t> (Arg [off] {sym})) => @b.Func.Entry (Arg <t> [off] {sym})
+
+// Similarly for stores, if we see a store after FPR <=> GPR move, then redirect store to use the other register set.
+(MOVDstore [off] {sym} ptr (FMOVDfpgp val) mem) => (FMOVDstore [off] {sym} ptr val mem)
+(FMOVDstore [off] {sym} ptr (FMOVDgpfp val) mem) => (MOVDstore [off] {sym} ptr val mem)
+(MOVWstore [off] {sym} ptr (FMOVSfpgp val) mem) => (FMOVSstore [off] {sym} ptr val mem)
+(FMOVSstore [off] {sym} ptr (FMOVSgpfp val) mem) => (MOVWstore [off] {sym} ptr val mem)
+
+// float <=> int register moves, with no conversion.
+// These come up when compiling math.{Float64bits, Float64frombits, Float32bits, Float32frombits}.
+(MOVDload [off] {sym} ptr (FMOVDstore [off] {sym} ptr val _)) => (FMOVDfpgp val)
+(FMOVDload [off] {sym} ptr (MOVDstore [off] {sym} ptr val _)) => (FMOVDgpfp val)
+(MOVWUload [off] {sym} ptr (FMOVSstore [off] {sym} ptr val _)) => (FMOVSfpgp val)
+(FMOVSload [off] {sym} ptr (MOVWstore [off] {sym} ptr val _)) => (FMOVSgpfp val)
+
+(BitLen64 x) => (SUB (MOVDconst [64]) (CLZ <typ.Int> x))
+(BitLen32 x) => (SUB (MOVDconst [32]) (CLZW <typ.Int> x))
+
+(Bswap64 ...) => (REV ...)
+(Bswap32 ...) => (REVW ...)
+
+(BitRev64 ...) => (RBIT ...)
+(BitRev32 ...) => (RBITW ...)
+(BitRev16 x) => (SRLconst [48] (RBIT <typ.UInt64> x))
+(BitRev8 x) => (SRLconst [56] (RBIT <typ.UInt64> x))
+
+// In fact, UMOD will be translated into UREM instruction, and UREM is originally translated into
+// UDIV and MSUB instructions. But if there is already an identical UDIV instruction just before or
+// after UREM (case like quo, rem := z/y, z%y), then the second UDIV instruction becomes redundant.
+// The purpose of this rule is to have this extra UDIV instruction removed in CSE pass.
+(UMOD <typ.UInt64> x y) => (MSUB <typ.UInt64> x y (UDIV <typ.UInt64> x y))
+(UMODW <typ.UInt32> x y) => (MSUBW <typ.UInt32> x y (UDIVW <typ.UInt32> x y))
+
+// 64-bit addition with carry.
+(Select0 (Add64carry x y c)) => (Select0 <typ.UInt64> (ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] c))))
+(Select1 (Add64carry x y c)) => (ADCzerocarry <typ.UInt64> (Select1 <types.TypeFlags> (ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] c)))))
+
+// 64-bit subtraction with borrowing.
+(Select0 (Sub64borrow x y bo)) => (Select0 <typ.UInt64> (SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags bo))))
+(Select1 (Sub64borrow x y bo)) => (NEG <typ.UInt64> (NGCzerocarry <typ.UInt64> (Select1 <types.TypeFlags> (SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags bo))))))
+
+// boolean ops -- booleans are represented with 0=false, 1=true
+(AndB ...) => (AND ...)
+(OrB ...) => (OR ...)
+(EqB x y) => (XOR (MOVDconst [1]) (XOR <typ.Bool> x y))
+(NeqB ...) => (XOR ...)
+(Not x) => (XOR (MOVDconst [1]) x)
+
+// shifts
+// hardware instruction uses only the low 6 bits of the shift
+// we compare to 64 to ensure Go semantics for large shifts
+// Rules about rotates with non-const shift are based on the following rules,
+// if the following rules change, please also modify the rules based on them.
+(Lsh64x64 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
+(Lsh64x32 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+(Lsh64x16 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+(Lsh64x8 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+
+(Lsh32x64 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
+(Lsh32x32 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+(Lsh32x16 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+(Lsh32x8 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+
+(Lsh16x64 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
+(Lsh16x32 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+(Lsh16x16 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+(Lsh16x8 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+
+(Lsh8x64 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
+(Lsh8x32 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+(Lsh8x16 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+(Lsh8x8 <t> x y) => (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+
+(Rsh64Ux64 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
+(Rsh64Ux32 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+(Rsh64Ux16 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+(Rsh64Ux8 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+
+(Rsh32Ux64 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt32to64 x) y) (Const64 <t> [0]) (CMPconst [64] y))
+(Rsh32Ux32 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt32to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+(Rsh32Ux16 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt32to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+(Rsh32Ux8 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt32to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+
+(Rsh16Ux64 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt16to64 x) y) (Const64 <t> [0]) (CMPconst [64] y))
+(Rsh16Ux32 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt16to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+(Rsh16Ux16 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt16to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+(Rsh16Ux8 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt16to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+
+(Rsh8Ux64 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt8to64 x) y) (Const64 <t> [0]) (CMPconst [64] y))
+(Rsh8Ux32 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt8to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+(Rsh8Ux16 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt8to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+(Rsh8Ux8 <t> x y) => (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt8to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+
+(Rsh64x64 x y) => (SRA x (CSEL [OpARM64LessThanU] <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
+(Rsh64x32 x y) => (SRA x (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
+(Rsh64x16 x y) => (SRA x (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
+(Rsh64x8 x y) => (SRA x (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
+
+(Rsh32x64 x y) => (SRA (SignExt32to64 x) (CSEL [OpARM64LessThanU] <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
+(Rsh32x32 x y) => (SRA (SignExt32to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
+(Rsh32x16 x y) => (SRA (SignExt32to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
+(Rsh32x8 x y) => (SRA (SignExt32to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
+
+(Rsh16x64 x y) => (SRA (SignExt16to64 x) (CSEL [OpARM64LessThanU] <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
+(Rsh16x32 x y) => (SRA (SignExt16to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
+(Rsh16x16 x y) => (SRA (SignExt16to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
+(Rsh16x8 x y) => (SRA (SignExt16to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
+
+(Rsh8x64 x y) => (SRA (SignExt8to64 x) (CSEL [OpARM64LessThanU] <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
+(Rsh8x32 x y) => (SRA (SignExt8to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
+(Rsh8x16 x y) => (SRA (SignExt8to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
+(Rsh8x8 x y) => (SRA (SignExt8to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
+
+// constants
+(Const(64|32|16|8) [val]) => (MOVDconst [int64(val)])
+(Const(32F|64F) [val]) => (FMOV(S|D)const [float64(val)])
+(ConstNil) => (MOVDconst [0])
+(ConstBool [b]) => (MOVDconst [b2i(b)])
+
+(Slicemask <t> x) => (SRAconst (NEG <t> x) [63])
+
+// truncations
+// Because we ignore high parts of registers, truncates are just copies.
+(Trunc16to8 ...) => (Copy ...)
+(Trunc32to8 ...) => (Copy ...)
+(Trunc32to16 ...) => (Copy ...)
+(Trunc64to8 ...) => (Copy ...)
+(Trunc64to16 ...) => (Copy ...)
+(Trunc64to32 ...) => (Copy ...)
+
+// Zero-/Sign-extensions
+(ZeroExt8to16 ...) => (MOVBUreg ...)
+(ZeroExt8to32 ...) => (MOVBUreg ...)
+(ZeroExt16to32 ...) => (MOVHUreg ...)
+(ZeroExt8to64 ...) => (MOVBUreg ...)
+(ZeroExt16to64 ...) => (MOVHUreg ...)
+(ZeroExt32to64 ...) => (MOVWUreg ...)
+
+(SignExt8to16 ...) => (MOVBreg ...)
+(SignExt8to32 ...) => (MOVBreg ...)
+(SignExt16to32 ...) => (MOVHreg ...)
+(SignExt8to64 ...) => (MOVBreg ...)
+(SignExt16to64 ...) => (MOVHreg ...)
+(SignExt32to64 ...) => (MOVWreg ...)
+
+// float <=> int conversion
+(Cvt32to32F ...) => (SCVTFWS ...)
+(Cvt32to64F ...) => (SCVTFWD ...)
+(Cvt64to32F ...) => (SCVTFS ...)
+(Cvt64to64F ...) => (SCVTFD ...)
+(Cvt32Uto32F ...) => (UCVTFWS ...)
+(Cvt32Uto64F ...) => (UCVTFWD ...)
+(Cvt64Uto32F ...) => (UCVTFS ...)
+(Cvt64Uto64F ...) => (UCVTFD ...)
+(Cvt32Fto32 ...) => (FCVTZSSW ...)
+(Cvt64Fto32 ...) => (FCVTZSDW ...)
+(Cvt32Fto64 ...) => (FCVTZSS ...)
+(Cvt64Fto64 ...) => (FCVTZSD ...)
+(Cvt32Fto32U ...) => (FCVTZUSW ...)
+(Cvt64Fto32U ...) => (FCVTZUDW ...)
+(Cvt32Fto64U ...) => (FCVTZUS ...)
+(Cvt64Fto64U ...) => (FCVTZUD ...)
+(Cvt32Fto64F ...) => (FCVTSD ...)
+(Cvt64Fto32F ...) => (FCVTDS ...)
+
+(CvtBoolToUint8 ...) => (Copy ...)
+
+(Round32F ...) => (LoweredRound32F ...)
+(Round64F ...) => (LoweredRound64F ...)
+
+// comparisons
+(Eq8 x y) => (Equal (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Eq16 x y) => (Equal (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Eq32 x y) => (Equal (CMPW x y))
+(Eq64 x y) => (Equal (CMP x y))
+(EqPtr x y) => (Equal (CMP x y))
+(Eq32F x y) => (Equal (FCMPS x y))
+(Eq64F x y) => (Equal (FCMPD x y))
+
+(Neq8 x y) => (NotEqual (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Neq16 x y) => (NotEqual (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Neq32 x y) => (NotEqual (CMPW x y))
+(Neq64 x y) => (NotEqual (CMP x y))
+(NeqPtr x y) => (NotEqual (CMP x y))
+(Neq32F x y) => (NotEqual (FCMPS x y))
+(Neq64F x y) => (NotEqual (FCMPD x y))
+
+(Less8 x y) => (LessThan (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+(Less16 x y) => (LessThan (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+(Less32 x y) => (LessThan (CMPW x y))
+(Less64 x y) => (LessThan (CMP x y))
+
+// Set condition flags for floating-point comparisons "x < y"
+// and "x <= y". Because if either or both of the operands are
+// NaNs, all three of (x < y), (x == y) and (x > y) are false,
+// and ARM Manual says FCMP instruction sets PSTATE.<N,Z,C,V>
+// of this case to (0, 0, 1, 1).
+(Less32F x y) => (LessThanF (FCMPS x y))
+(Less64F x y) => (LessThanF (FCMPD x y))
+
+// For an unsigned integer x, the following rules are useful when combining branch
+// 0 < x => x != 0
+// x <= 0 => x == 0
+// x < 1 => x == 0
+// 1 <= x => x != 0
+(Less(8U|16U|32U|64U) zero:(MOVDconst [0]) x) => (Neq(8|16|32|64) zero x)
+(Leq(8U|16U|32U|64U) x zero:(MOVDconst [0])) => (Eq(8|16|32|64) x zero)
+(Less(8U|16U|32U|64U) x (MOVDconst [1])) => (Eq(8|16|32|64) x (MOVDconst [0]))
+(Leq(8U|16U|32U|64U) (MOVDconst [1]) x) => (Neq(8|16|32|64) (MOVDconst [0]) x)
+
+(Less8U x y) => (LessThanU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Less16U x y) => (LessThanU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Less32U x y) => (LessThanU (CMPW x y))
+(Less64U x y) => (LessThanU (CMP x y))
+
+(Leq8 x y) => (LessEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+(Leq16 x y) => (LessEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+(Leq32 x y) => (LessEqual (CMPW x y))
+(Leq64 x y) => (LessEqual (CMP x y))
+
+// Refer to the comments for op Less64F above.
+(Leq32F x y) => (LessEqualF (FCMPS x y))
+(Leq64F x y) => (LessEqualF (FCMPD x y))
+
+(Leq8U x y) => (LessEqualU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Leq16U x y) => (LessEqualU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Leq32U x y) => (LessEqualU (CMPW x y))
+(Leq64U x y) => (LessEqualU (CMP x y))
+
+// Optimize comparison between a floating-point value and 0.0 with "FCMP $(0.0), Fn"
+(FCMPS x (FMOVSconst [0])) => (FCMPS0 x)
+(FCMPS (FMOVSconst [0]) x) => (InvertFlags (FCMPS0 x))
+(FCMPD x (FMOVDconst [0])) => (FCMPD0 x)
+(FCMPD (FMOVDconst [0]) x) => (InvertFlags (FCMPD0 x))
+
+// CSEL needs a flag-generating argument. Synthesize a CMPW if necessary.
+(CondSelect x y boolval) && flagArg(boolval) != nil => (CSEL [boolval.Op] x y flagArg(boolval))
+(CondSelect x y boolval) && flagArg(boolval) == nil => (CSEL [OpARM64NotEqual] x y (CMPWconst [0] boolval))
+
+(OffPtr [off] ptr:(SP)) && is32Bit(off) => (MOVDaddr [int32(off)] ptr)
+(OffPtr [off] ptr) => (ADDconst [off] ptr)
+
+(Addr {sym} base) => (MOVDaddr {sym} base)
+(LocalAddr {sym} base _) => (MOVDaddr {sym} base)
+
+// loads
+(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
+(Load <t> ptr mem) && (is8BitInt(t) && isSigned(t)) => (MOVBload ptr mem)
+(Load <t> ptr mem) && (is8BitInt(t) && !isSigned(t)) => (MOVBUload ptr mem)
+(Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) => (MOVHload ptr mem)
+(Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) => (MOVHUload ptr mem)
+(Load <t> ptr mem) && (is32BitInt(t) && isSigned(t)) => (MOVWload ptr mem)
+(Load <t> ptr mem) && (is32BitInt(t) && !isSigned(t)) => (MOVWUload ptr mem)
+(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) => (MOVDload ptr mem)
+(Load <t> ptr mem) && is32BitFloat(t) => (FMOVSload ptr mem)
+(Load <t> ptr mem) && is64BitFloat(t) => (FMOVDload ptr mem)
+
+// stores
+(Store {t} ptr val mem) && t.Size() == 1 => (MOVBstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 2 => (MOVHstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && !is32BitFloat(val.Type) => (MOVWstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 && !is64BitFloat(val.Type) => (MOVDstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && is32BitFloat(val.Type) => (FMOVSstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 && is64BitFloat(val.Type) => (FMOVDstore ptr val mem)
+
+// zeroing
+(Zero [0] _ mem) => mem
+(Zero [1] ptr mem) => (MOVBstore ptr (MOVDconst [0]) mem)
+(Zero [2] ptr mem) => (MOVHstore ptr (MOVDconst [0]) mem)
+(Zero [4] ptr mem) => (MOVWstore ptr (MOVDconst [0]) mem)
+(Zero [8] ptr mem) => (MOVDstore ptr (MOVDconst [0]) mem)
+
+(Zero [3] ptr mem) =>
+ (MOVBstore [2] ptr (MOVDconst [0])
+ (MOVHstore ptr (MOVDconst [0]) mem))
+(Zero [5] ptr mem) =>
+ (MOVBstore [4] ptr (MOVDconst [0])
+ (MOVWstore ptr (MOVDconst [0]) mem))
+(Zero [6] ptr mem) =>
+ (MOVHstore [4] ptr (MOVDconst [0])
+ (MOVWstore ptr (MOVDconst [0]) mem))
+(Zero [7] ptr mem) =>
+ (MOVBstore [6] ptr (MOVDconst [0])
+ (MOVHstore [4] ptr (MOVDconst [0])
+ (MOVWstore ptr (MOVDconst [0]) mem)))
+(Zero [9] ptr mem) =>
+ (MOVBstore [8] ptr (MOVDconst [0])
+ (MOVDstore ptr (MOVDconst [0]) mem))
+(Zero [10] ptr mem) =>
+ (MOVHstore [8] ptr (MOVDconst [0])
+ (MOVDstore ptr (MOVDconst [0]) mem))
+(Zero [11] ptr mem) =>
+ (MOVBstore [10] ptr (MOVDconst [0])
+ (MOVHstore [8] ptr (MOVDconst [0])
+ (MOVDstore ptr (MOVDconst [0]) mem)))
+(Zero [12] ptr mem) =>
+ (MOVWstore [8] ptr (MOVDconst [0])
+ (MOVDstore ptr (MOVDconst [0]) mem))
+(Zero [13] ptr mem) =>
+ (MOVBstore [12] ptr (MOVDconst [0])
+ (MOVWstore [8] ptr (MOVDconst [0])
+ (MOVDstore ptr (MOVDconst [0]) mem)))
+(Zero [14] ptr mem) =>
+ (MOVHstore [12] ptr (MOVDconst [0])
+ (MOVWstore [8] ptr (MOVDconst [0])
+ (MOVDstore ptr (MOVDconst [0]) mem)))
+(Zero [15] ptr mem) =>
+ (MOVBstore [14] ptr (MOVDconst [0])
+ (MOVHstore [12] ptr (MOVDconst [0])
+ (MOVWstore [8] ptr (MOVDconst [0])
+ (MOVDstore ptr (MOVDconst [0]) mem))))
+(Zero [16] ptr mem) =>
+ (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem)
+
+(Zero [32] ptr mem) =>
+ (STP [16] ptr (MOVDconst [0]) (MOVDconst [0])
+ (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem))
+
+(Zero [48] ptr mem) =>
+ (STP [32] ptr (MOVDconst [0]) (MOVDconst [0])
+ (STP [16] ptr (MOVDconst [0]) (MOVDconst [0])
+ (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem)))
+
+(Zero [64] ptr mem) =>
+ (STP [48] ptr (MOVDconst [0]) (MOVDconst [0])
+ (STP [32] ptr (MOVDconst [0]) (MOVDconst [0])
+ (STP [16] ptr (MOVDconst [0]) (MOVDconst [0])
+ (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem))))
+
+// strip off fractional word zeroing
+(Zero [s] ptr mem) && s%16 != 0 && s%16 <= 8 && s > 16 =>
+ (Zero [8]
+ (OffPtr <ptr.Type> ptr [s-8])
+ (Zero [s-s%16] ptr mem))
+(Zero [s] ptr mem) && s%16 != 0 && s%16 > 8 && s > 16 =>
+ (Zero [16]
+ (OffPtr <ptr.Type> ptr [s-16])
+ (Zero [s-s%16] ptr mem))
+
+// medium zeroing uses a duff device
+// 4, 16, and 64 are magic constants, see runtime/mkduff.go
+(Zero [s] ptr mem)
+ && s%16 == 0 && s > 64 && s <= 16*64
+ && !config.noDuffDevice =>
+ (DUFFZERO [4 * (64 - s/16)] ptr mem)
+
+// large zeroing uses a loop
+(Zero [s] ptr mem)
+ && s%16 == 0 && (s > 16*64 || config.noDuffDevice) =>
+ (LoweredZero
+ ptr
+ (ADDconst <ptr.Type> [s-16] ptr)
+ mem)
+
+// moves
+(Move [0] _ _ mem) => mem
+(Move [1] dst src mem) => (MOVBstore dst (MOVBUload src mem) mem)
+(Move [2] dst src mem) => (MOVHstore dst (MOVHUload src mem) mem)
+(Move [4] dst src mem) => (MOVWstore dst (MOVWUload src mem) mem)
+(Move [8] dst src mem) => (MOVDstore dst (MOVDload src mem) mem)
+
+(Move [3] dst src mem) =>
+ (MOVBstore [2] dst (MOVBUload [2] src mem)
+ (MOVHstore dst (MOVHUload src mem) mem))
+(Move [5] dst src mem) =>
+ (MOVBstore [4] dst (MOVBUload [4] src mem)
+ (MOVWstore dst (MOVWUload src mem) mem))
+(Move [6] dst src mem) =>
+ (MOVHstore [4] dst (MOVHUload [4] src mem)
+ (MOVWstore dst (MOVWUload src mem) mem))
+(Move [7] dst src mem) =>
+ (MOVBstore [6] dst (MOVBUload [6] src mem)
+ (MOVHstore [4] dst (MOVHUload [4] src mem)
+ (MOVWstore dst (MOVWUload src mem) mem)))
+(Move [12] dst src mem) =>
+ (MOVWstore [8] dst (MOVWUload [8] src mem)
+ (MOVDstore dst (MOVDload src mem) mem))
+(Move [16] dst src mem) =>
+ (MOVDstore [8] dst (MOVDload [8] src mem)
+ (MOVDstore dst (MOVDload src mem) mem))
+(Move [24] dst src mem) =>
+ (MOVDstore [16] dst (MOVDload [16] src mem)
+ (MOVDstore [8] dst (MOVDload [8] src mem)
+ (MOVDstore dst (MOVDload src mem) mem)))
+
+// strip off fractional word move
+(Move [s] dst src mem) && s%8 != 0 && s > 8 =>
+ (Move [s%8]
+ (OffPtr <dst.Type> dst [s-s%8])
+ (OffPtr <src.Type> src [s-s%8])
+ (Move [s-s%8] dst src mem))
+
+// medium move uses a duff device
+(Move [s] dst src mem)
+ && s > 32 && s <= 16*64 && s%16 == 8
+ && !config.noDuffDevice && logLargeCopy(v, s) =>
+ (MOVDstore [int32(s-8)] dst (MOVDload [int32(s-8)] src mem)
+ (DUFFCOPY <types.TypeMem> [8*(64-(s-8)/16)] dst src mem))
+(Move [s] dst src mem)
+ && s > 32 && s <= 16*64 && s%16 == 0
+ && !config.noDuffDevice && logLargeCopy(v, s) =>
+ (DUFFCOPY [8 * (64 - s/16)] dst src mem)
+// 8 is the number of bytes to encode:
+//
+// LDP.P 16(R16), (R26, R27)
+// STP.P (R26, R27), 16(R17)
+//
+// 64 is number of these blocks. See runtime/duff_arm64.s:duffcopy
+
+// large move uses a loop
+(Move [s] dst src mem)
+ && s > 24 && s%8 == 0 && logLargeCopy(v, s) =>
+ (LoweredMove
+ dst
+ src
+ (ADDconst <src.Type> src [s-8])
+ mem)
+
+// calls
+(StaticCall ...) => (CALLstatic ...)
+(ClosureCall ...) => (CALLclosure ...)
+(InterCall ...) => (CALLinter ...)
+
+// checks
+(NilCheck ...) => (LoweredNilCheck ...)
+(IsNonNil ptr) => (NotEqual (CMPconst [0] ptr))
+(IsInBounds idx len) => (LessThanU (CMP idx len))
+(IsSliceInBounds idx len) => (LessEqualU (CMP idx len))
+
+// pseudo-ops
+(GetClosurePtr ...) => (LoweredGetClosurePtr ...)
+(GetCallerSP ...) => (LoweredGetCallerSP ...)
+(GetCallerPC ...) => (LoweredGetCallerPC ...)
+
+// Absorb pseudo-ops into blocks.
+(If (Equal cc) yes no) => (EQ cc yes no)
+(If (NotEqual cc) yes no) => (NE cc yes no)
+(If (LessThan cc) yes no) => (LT cc yes no)
+(If (LessThanU cc) yes no) => (ULT cc yes no)
+(If (LessEqual cc) yes no) => (LE cc yes no)
+(If (LessEqualU cc) yes no) => (ULE cc yes no)
+(If (GreaterThan cc) yes no) => (GT cc yes no)
+(If (GreaterThanU cc) yes no) => (UGT cc yes no)
+(If (GreaterEqual cc) yes no) => (GE cc yes no)
+(If (GreaterEqualU cc) yes no) => (UGE cc yes no)
+(If (LessThanF cc) yes no) => (FLT cc yes no)
+(If (LessEqualF cc) yes no) => (FLE cc yes no)
+(If (GreaterThanF cc) yes no) => (FGT cc yes no)
+(If (GreaterEqualF cc) yes no) => (FGE cc yes no)
+
+(If cond yes no) => (NZ cond yes no)
+
+// atomic intrinsics
+// Note: these ops do not accept offset.
+(AtomicLoad8 ...) => (LDARB ...)
+(AtomicLoad32 ...) => (LDARW ...)
+(AtomicLoad64 ...) => (LDAR ...)
+(AtomicLoadPtr ...) => (LDAR ...)
+
+(AtomicStore8 ...) => (STLRB ...)
+(AtomicStore32 ...) => (STLRW ...)
+(AtomicStore64 ...) => (STLR ...)
+(AtomicStorePtrNoWB ...) => (STLR ...)
+
+(AtomicExchange(32|64) ...) => (LoweredAtomicExchange(32|64) ...)
+(AtomicAdd(32|64) ...) => (LoweredAtomicAdd(32|64) ...)
+(AtomicCompareAndSwap(32|64) ...) => (LoweredAtomicCas(32|64) ...)
+
+(AtomicAdd(32|64)Variant ...) => (LoweredAtomicAdd(32|64)Variant ...)
+(AtomicExchange(32|64)Variant ...) => (LoweredAtomicExchange(32|64)Variant ...)
+(AtomicCompareAndSwap(32|64)Variant ...) => (LoweredAtomicCas(32|64)Variant ...)
+
+// Currently the updated value is not used, but we need a register to temporarily hold it.
+(AtomicAnd8 ptr val mem) => (Select1 (LoweredAtomicAnd8 ptr val mem))
+(AtomicAnd32 ptr val mem) => (Select1 (LoweredAtomicAnd32 ptr val mem))
+(AtomicOr8 ptr val mem) => (Select1 (LoweredAtomicOr8 ptr val mem))
+(AtomicOr32 ptr val mem) => (Select1 (LoweredAtomicOr32 ptr val mem))
+
+(AtomicAnd8Variant ptr val mem) => (Select1 (LoweredAtomicAnd8Variant ptr val mem))
+(AtomicAnd32Variant ptr val mem) => (Select1 (LoweredAtomicAnd32Variant ptr val mem))
+(AtomicOr8Variant ptr val mem) => (Select1 (LoweredAtomicOr8Variant ptr val mem))
+(AtomicOr32Variant ptr val mem) => (Select1 (LoweredAtomicOr32Variant ptr val mem))
+
+// Write barrier.
+(WB ...) => (LoweredWB ...)
+
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
+
+// Optimizations
+
+// Absorb boolean tests into block
+(NZ (Equal cc) yes no) => (EQ cc yes no)
+(NZ (NotEqual cc) yes no) => (NE cc yes no)
+(NZ (LessThan cc) yes no) => (LT cc yes no)
+(NZ (LessThanU cc) yes no) => (ULT cc yes no)
+(NZ (LessEqual cc) yes no) => (LE cc yes no)
+(NZ (LessEqualU cc) yes no) => (ULE cc yes no)
+(NZ (GreaterThan cc) yes no) => (GT cc yes no)
+(NZ (GreaterThanU cc) yes no) => (UGT cc yes no)
+(NZ (GreaterEqual cc) yes no) => (GE cc yes no)
+(NZ (GreaterEqualU cc) yes no) => (UGE cc yes no)
+(NZ (LessThanF cc) yes no) => (FLT cc yes no)
+(NZ (LessEqualF cc) yes no) => (FLE cc yes no)
+(NZ (GreaterThanF cc) yes no) => (FGT cc yes no)
+(NZ (GreaterEqualF cc) yes no) => (FGE cc yes no)
+
+(EQ (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (EQ (TSTWconst [int32(c)] y) yes no)
+(NE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (NE (TSTWconst [int32(c)] y) yes no)
+(LT (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LT (TSTWconst [int32(c)] y) yes no)
+(LE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LE (TSTWconst [int32(c)] y) yes no)
+(GT (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GT (TSTWconst [int32(c)] y) yes no)
+(GE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GE (TSTWconst [int32(c)] y) yes no)
+
+(EQ (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (EQ (TST x y) yes no)
+(NE (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (NE (TST x y) yes no)
+(LT (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (LT (TST x y) yes no)
+(LE (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (LE (TST x y) yes no)
+(GT (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (GT (TST x y) yes no)
+(GE (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (GE (TST x y) yes no)
+
+(EQ (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (EQ (TSTW x y) yes no)
+(NE (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (NE (TSTW x y) yes no)
+(LT (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (LT (TSTW x y) yes no)
+(LE (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (LE (TSTW x y) yes no)
+(GT (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (GT (TSTW x y) yes no)
+(GE (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (GE (TSTW x y) yes no)
+
+(EQ (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (EQ (TSTconst [c] y) yes no)
+(NE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (NE (TSTconst [c] y) yes no)
+(LT (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LT (TSTconst [c] y) yes no)
+(LE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LE (TSTconst [c] y) yes no)
+(GT (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GT (TSTconst [c] y) yes no)
+(GE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GE (TSTconst [c] y) yes no)
+
+(EQ (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (EQ (CMNconst [c] y) yes no)
+(NE (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (NE (CMNconst [c] y) yes no)
+(LT (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (LTnoov (CMNconst [c] y) yes no)
+(LE (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (LEnoov (CMNconst [c] y) yes no)
+(GT (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (GTnoov (CMNconst [c] y) yes no)
+(GE (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (GEnoov (CMNconst [c] y) yes no)
+
+(EQ (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (EQ (CMNWconst [int32(c)] y) yes no)
+(NE (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (NE (CMNWconst [int32(c)] y) yes no)
+(LT (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (LTnoov (CMNWconst [int32(c)] y) yes no)
+(LE (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (LEnoov (CMNWconst [int32(c)] y) yes no)
+(GT (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (GTnoov (CMNWconst [int32(c)] y) yes no)
+(GE (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (GEnoov (CMNWconst [int32(c)] y) yes no)
+
+(EQ (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (EQ (CMN x y) yes no)
+(NE (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (NE (CMN x y) yes no)
+(LT (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (LTnoov (CMN x y) yes no)
+(LE (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (LEnoov (CMN x y) yes no)
+(GT (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (GTnoov (CMN x y) yes no)
+(GE (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (GEnoov (CMN x y) yes no)
+
+(EQ (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (EQ (CMNW x y) yes no)
+(NE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (NE (CMNW x y) yes no)
+(LT (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (LTnoov (CMNW x y) yes no)
+(LE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (LEnoov (CMNW x y) yes no)
+(GT (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (GTnoov (CMNW x y) yes no)
+(GE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (GEnoov (CMNW x y) yes no)
+
+(EQ (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMN x y) yes no)
+(NE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMN x y) yes no)
+(LT (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (LT (CMN x y) yes no)
+(LE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (LE (CMN x y) yes no)
+(GT (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (GT (CMN x y) yes no)
+(GE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (GE (CMN x y) yes no)
+
+(EQ (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMNW x y) yes no)
+(NE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMNW x y) yes no)
+(LT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (LT (CMNW x y) yes no)
+(LE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (LE (CMNW x y) yes no)
+(GT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (GT (CMNW x y) yes no)
+(GE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (GE (CMNW x y) yes no)
+
+(EQ (CMPconst [0] x) yes no) => (Z x yes no)
+(NE (CMPconst [0] x) yes no) => (NZ x yes no)
+(EQ (CMPWconst [0] x) yes no) => (ZW x yes no)
+(NE (CMPWconst [0] x) yes no) => (NZW x yes no)
+
+(EQ (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 => (EQ (CMN a (MUL <x.Type> x y)) yes no)
+(NE (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 => (NE (CMN a (MUL <x.Type> x y)) yes no)
+(LT (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 => (LTnoov (CMN a (MUL <x.Type> x y)) yes no)
+(LE (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 => (LEnoov (CMN a (MUL <x.Type> x y)) yes no)
+(GT (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 => (GTnoov (CMN a (MUL <x.Type> x y)) yes no)
+(GE (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 => (GEnoov (CMN a (MUL <x.Type> x y)) yes no)
+
+(EQ (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 => (EQ (CMP a (MUL <x.Type> x y)) yes no)
+(NE (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 => (NE (CMP a (MUL <x.Type> x y)) yes no)
+(LE (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 => (LEnoov (CMP a (MUL <x.Type> x y)) yes no)
+(LT (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 => (LTnoov (CMP a (MUL <x.Type> x y)) yes no)
+(GE (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 => (GEnoov (CMP a (MUL <x.Type> x y)) yes no)
+(GT (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 => (GTnoov (CMP a (MUL <x.Type> x y)) yes no)
+
+(EQ (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 => (EQ (CMNW a (MULW <x.Type> x y)) yes no)
+(NE (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 => (NE (CMNW a (MULW <x.Type> x y)) yes no)
+(LE (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 => (LEnoov (CMNW a (MULW <x.Type> x y)) yes no)
+(LT (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 => (LTnoov (CMNW a (MULW <x.Type> x y)) yes no)
+(GE (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 => (GEnoov (CMNW a (MULW <x.Type> x y)) yes no)
+(GT (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 => (GTnoov (CMNW a (MULW <x.Type> x y)) yes no)
+
+(EQ (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 => (EQ (CMPW a (MULW <x.Type> x y)) yes no)
+(NE (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 => (NE (CMPW a (MULW <x.Type> x y)) yes no)
+(LE (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 => (LEnoov (CMPW a (MULW <x.Type> x y)) yes no)
+(LT (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 => (LTnoov (CMPW a (MULW <x.Type> x y)) yes no)
+(GE (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 => (GEnoov (CMPW a (MULW <x.Type> x y)) yes no)
+(GT (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 => (GTnoov (CMPW a (MULW <x.Type> x y)) yes no)
+
+// Absorb bit-tests into block
+(Z (ANDconst [c] x) yes no) && oneBit(c) => (TBZ [int64(ntz64(c))] x yes no)
+(NZ (ANDconst [c] x) yes no) && oneBit(c) => (TBNZ [int64(ntz64(c))] x yes no)
+(ZW (ANDconst [c] x) yes no) && oneBit(int64(uint32(c))) => (TBZ [int64(ntz64(int64(uint32(c))))] x yes no)
+(NZW (ANDconst [c] x) yes no) && oneBit(int64(uint32(c))) => (TBNZ [int64(ntz64(int64(uint32(c))))] x yes no)
+(EQ (TSTconst [c] x) yes no) && oneBit(c) => (TBZ [int64(ntz64(c))] x yes no)
+(NE (TSTconst [c] x) yes no) && oneBit(c) => (TBNZ [int64(ntz64(c))] x yes no)
+(EQ (TSTWconst [c] x) yes no) && oneBit(int64(uint32(c))) => (TBZ [int64(ntz64(int64(uint32(c))))] x yes no)
+(NE (TSTWconst [c] x) yes no) && oneBit(int64(uint32(c))) => (TBNZ [int64(ntz64(int64(uint32(c))))] x yes no)
+
+// Test sign-bit for signed comparisons against zero
+(GE (CMPWconst [0] x) yes no) => (TBZ [31] x yes no)
+(GE (CMPconst [0] x) yes no) => (TBZ [63] x yes no)
+(LT (CMPWconst [0] x) yes no) => (TBNZ [31] x yes no)
+(LT (CMPconst [0] x) yes no) => (TBNZ [63] x yes no)
+
+// fold offset into address
+(ADDconst [off1] (MOVDaddr [off2] {sym} ptr)) && is32Bit(off1+int64(off2)) =>
+ (MOVDaddr [int32(off1)+off2] {sym} ptr)
+
+// fold address into load/store
+(MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVBload [off1+int32(off2)] {sym} ptr mem)
+(MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVBUload [off1+int32(off2)] {sym} ptr mem)
+(MOVHload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVHload [off1+int32(off2)] {sym} ptr mem)
+(MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVHUload [off1+int32(off2)] {sym} ptr mem)
+(MOVWload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVWload [off1+int32(off2)] {sym} ptr mem)
+(MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVWUload [off1+int32(off2)] {sym} ptr mem)
+(MOVDload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVDload [off1+int32(off2)] {sym} ptr mem)
+(FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (FMOVSload [off1+int32(off2)] {sym} ptr mem)
+(FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (FMOVDload [off1+int32(off2)] {sym} ptr mem)
+
+// register indexed load
+(MOVDload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVDloadidx ptr idx mem)
+(MOVWUload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVWUloadidx ptr idx mem)
+(MOVWload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVWloadidx ptr idx mem)
+(MOVHUload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVHUloadidx ptr idx mem)
+(MOVHload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVHloadidx ptr idx mem)
+(MOVBUload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVBUloadidx ptr idx mem)
+(MOVBload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVBloadidx ptr idx mem)
+(FMOVSload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (FMOVSloadidx ptr idx mem)
+(FMOVDload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (FMOVDloadidx ptr idx mem)
+(MOVDloadidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVDload [int32(c)] ptr mem)
+(MOVDloadidx (MOVDconst [c]) ptr mem) && is32Bit(c) => (MOVDload [int32(c)] ptr mem)
+(MOVWUloadidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVWUload [int32(c)] ptr mem)
+(MOVWUloadidx (MOVDconst [c]) ptr mem) && is32Bit(c) => (MOVWUload [int32(c)] ptr mem)
+(MOVWloadidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVWload [int32(c)] ptr mem)
+(MOVWloadidx (MOVDconst [c]) ptr mem) && is32Bit(c) => (MOVWload [int32(c)] ptr mem)
+(MOVHUloadidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVHUload [int32(c)] ptr mem)
+(MOVHUloadidx (MOVDconst [c]) ptr mem) && is32Bit(c) => (MOVHUload [int32(c)] ptr mem)
+(MOVHloadidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVHload [int32(c)] ptr mem)
+(MOVHloadidx (MOVDconst [c]) ptr mem) && is32Bit(c) => (MOVHload [int32(c)] ptr mem)
+(MOVBUloadidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVBUload [int32(c)] ptr mem)
+(MOVBUloadidx (MOVDconst [c]) ptr mem) && is32Bit(c) => (MOVBUload [int32(c)] ptr mem)
+(MOVBloadidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVBload [int32(c)] ptr mem)
+(MOVBloadidx (MOVDconst [c]) ptr mem) && is32Bit(c) => (MOVBload [int32(c)] ptr mem)
+(FMOVSloadidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (FMOVSload [int32(c)] ptr mem)
+(FMOVSloadidx (MOVDconst [c]) ptr mem) && is32Bit(c) => (FMOVSload [int32(c)] ptr mem)
+(FMOVDloadidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (FMOVDload [int32(c)] ptr mem)
+(FMOVDloadidx (MOVDconst [c]) ptr mem) && is32Bit(c) => (FMOVDload [int32(c)] ptr mem)
+
+// shifted register indexed load
+(MOVDload [off] {sym} (ADDshiftLL [3] ptr idx) mem) && off == 0 && sym == nil => (MOVDloadidx8 ptr idx mem)
+(MOVWUload [off] {sym} (ADDshiftLL [2] ptr idx) mem) && off == 0 && sym == nil => (MOVWUloadidx4 ptr idx mem)
+(MOVWload [off] {sym} (ADDshiftLL [2] ptr idx) mem) && off == 0 && sym == nil => (MOVWloadidx4 ptr idx mem)
+(MOVHUload [off] {sym} (ADDshiftLL [1] ptr idx) mem) && off == 0 && sym == nil => (MOVHUloadidx2 ptr idx mem)
+(MOVHload [off] {sym} (ADDshiftLL [1] ptr idx) mem) && off == 0 && sym == nil => (MOVHloadidx2 ptr idx mem)
+(MOVDloadidx ptr (SLLconst [3] idx) mem) => (MOVDloadidx8 ptr idx mem)
+(MOVWloadidx ptr (SLLconst [2] idx) mem) => (MOVWloadidx4 ptr idx mem)
+(MOVWUloadidx ptr (SLLconst [2] idx) mem) => (MOVWUloadidx4 ptr idx mem)
+(MOVHloadidx ptr (SLLconst [1] idx) mem) => (MOVHloadidx2 ptr idx mem)
+(MOVHUloadidx ptr (SLLconst [1] idx) mem) => (MOVHUloadidx2 ptr idx mem)
+(MOVHloadidx ptr (ADD idx idx) mem) => (MOVHloadidx2 ptr idx mem)
+(MOVHUloadidx ptr (ADD idx idx) mem) => (MOVHUloadidx2 ptr idx mem)
+(MOVDloadidx (SLLconst [3] idx) ptr mem) => (MOVDloadidx8 ptr idx mem)
+(MOVWloadidx (SLLconst [2] idx) ptr mem) => (MOVWloadidx4 ptr idx mem)
+(MOVWUloadidx (SLLconst [2] idx) ptr mem) => (MOVWUloadidx4 ptr idx mem)
+(MOVHloadidx (ADD idx idx) ptr mem) => (MOVHloadidx2 ptr idx mem)
+(MOVHUloadidx (ADD idx idx) ptr mem) => (MOVHUloadidx2 ptr idx mem)
+(MOVDloadidx8 ptr (MOVDconst [c]) mem) && is32Bit(c<<3) => (MOVDload [int32(c)<<3] ptr mem)
+(MOVWUloadidx4 ptr (MOVDconst [c]) mem) && is32Bit(c<<2) => (MOVWUload [int32(c)<<2] ptr mem)
+(MOVWloadidx4 ptr (MOVDconst [c]) mem) && is32Bit(c<<2) => (MOVWload [int32(c)<<2] ptr mem)
+(MOVHUloadidx2 ptr (MOVDconst [c]) mem) && is32Bit(c<<1) => (MOVHUload [int32(c)<<1] ptr mem)
+(MOVHloadidx2 ptr (MOVDconst [c]) mem) && is32Bit(c<<1) => (MOVHload [int32(c)<<1] ptr mem)
+
+(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVBstore [off1+int32(off2)] {sym} ptr val mem)
+(MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVHstore [off1+int32(off2)] {sym} ptr val mem)
+(MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVWstore [off1+int32(off2)] {sym} ptr val mem)
+(MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVDstore [off1+int32(off2)] {sym} ptr val mem)
+(STP [off1] {sym} (ADDconst [off2] ptr) val1 val2 mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (STP [off1+int32(off2)] {sym} ptr val1 val2 mem)
+(FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (FMOVSstore [off1+int32(off2)] {sym} ptr val mem)
+(FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (FMOVDstore [off1+int32(off2)] {sym} ptr val mem)
+(MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVBstorezero [off1+int32(off2)] {sym} ptr mem)
+(MOVHstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVHstorezero [off1+int32(off2)] {sym} ptr mem)
+(MOVWstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVWstorezero [off1+int32(off2)] {sym} ptr mem)
+(MOVDstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVDstorezero [off1+int32(off2)] {sym} ptr mem)
+(MOVQstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVQstorezero [off1+int32(off2)] {sym} ptr mem)
+
+// register indexed store
+(MOVDstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil => (MOVDstoreidx ptr idx val mem)
+(MOVWstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil => (MOVWstoreidx ptr idx val mem)
+(MOVHstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil => (MOVHstoreidx ptr idx val mem)
+(MOVBstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil => (MOVBstoreidx ptr idx val mem)
+(FMOVDstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil => (FMOVDstoreidx ptr idx val mem)
+(FMOVSstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil => (FMOVSstoreidx ptr idx val mem)
+(MOVDstoreidx ptr (MOVDconst [c]) val mem) && is32Bit(c) => (MOVDstore [int32(c)] ptr val mem)
+(MOVDstoreidx (MOVDconst [c]) idx val mem) && is32Bit(c) => (MOVDstore [int32(c)] idx val mem)
+(MOVWstoreidx ptr (MOVDconst [c]) val mem) && is32Bit(c) => (MOVWstore [int32(c)] ptr val mem)
+(MOVWstoreidx (MOVDconst [c]) idx val mem) && is32Bit(c) => (MOVWstore [int32(c)] idx val mem)
+(MOVHstoreidx ptr (MOVDconst [c]) val mem) && is32Bit(c) => (MOVHstore [int32(c)] ptr val mem)
+(MOVHstoreidx (MOVDconst [c]) idx val mem) && is32Bit(c) => (MOVHstore [int32(c)] idx val mem)
+(MOVBstoreidx ptr (MOVDconst [c]) val mem) && is32Bit(c) => (MOVBstore [int32(c)] ptr val mem)
+(MOVBstoreidx (MOVDconst [c]) idx val mem) && is32Bit(c) => (MOVBstore [int32(c)] idx val mem)
+(FMOVDstoreidx ptr (MOVDconst [c]) val mem) && is32Bit(c) => (FMOVDstore [int32(c)] ptr val mem)
+(FMOVDstoreidx (MOVDconst [c]) idx val mem) && is32Bit(c) => (FMOVDstore [int32(c)] idx val mem)
+(FMOVSstoreidx ptr (MOVDconst [c]) val mem) && is32Bit(c) => (FMOVSstore [int32(c)] ptr val mem)
+(FMOVSstoreidx (MOVDconst [c]) idx val mem) && is32Bit(c) => (FMOVSstore [int32(c)] idx val mem)
+
+// shifted register indexed store
+(MOVDstore [off] {sym} (ADDshiftLL [3] ptr idx) val mem) && off == 0 && sym == nil => (MOVDstoreidx8 ptr idx val mem)
+(MOVWstore [off] {sym} (ADDshiftLL [2] ptr idx) val mem) && off == 0 && sym == nil => (MOVWstoreidx4 ptr idx val mem)
+(MOVHstore [off] {sym} (ADDshiftLL [1] ptr idx) val mem) && off == 0 && sym == nil => (MOVHstoreidx2 ptr idx val mem)
+(MOVDstoreidx ptr (SLLconst [3] idx) val mem) => (MOVDstoreidx8 ptr idx val mem)
+(MOVWstoreidx ptr (SLLconst [2] idx) val mem) => (MOVWstoreidx4 ptr idx val mem)
+(MOVHstoreidx ptr (SLLconst [1] idx) val mem) => (MOVHstoreidx2 ptr idx val mem)
+(MOVHstoreidx ptr (ADD idx idx) val mem) => (MOVHstoreidx2 ptr idx val mem)
+(MOVDstoreidx (SLLconst [3] idx) ptr val mem) => (MOVDstoreidx8 ptr idx val mem)
+(MOVWstoreidx (SLLconst [2] idx) ptr val mem) => (MOVWstoreidx4 ptr idx val mem)
+(MOVHstoreidx (SLLconst [1] idx) ptr val mem) => (MOVHstoreidx2 ptr idx val mem)
+(MOVHstoreidx (ADD idx idx) ptr val mem) => (MOVHstoreidx2 ptr idx val mem)
+(MOVDstoreidx8 ptr (MOVDconst [c]) val mem) && is32Bit(c<<3) => (MOVDstore [int32(c)<<3] ptr val mem)
+(MOVWstoreidx4 ptr (MOVDconst [c]) val mem) && is32Bit(c<<2) => (MOVWstore [int32(c)<<2] ptr val mem)
+(MOVHstoreidx2 ptr (MOVDconst [c]) val mem) && is32Bit(c<<1) => (MOVHstore [int32(c)<<1] ptr val mem)
+
+(MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+
+(MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(STP [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val1 val2 mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (STP [off1+off2] {mergeSym(sym1,sym2)} ptr val1 val2 mem)
+(FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVQstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) =>
+ (MOVQstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+
+// store zero
+(MOVBstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVBstorezero [off] {sym} ptr mem)
+(MOVHstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVHstorezero [off] {sym} ptr mem)
+(MOVWstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVWstorezero [off] {sym} ptr mem)
+(MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVDstorezero [off] {sym} ptr mem)
+(STP [off] {sym} ptr (MOVDconst [0]) (MOVDconst [0]) mem) => (MOVQstorezero [off] {sym} ptr mem)
+
+// register indexed store zero
+(MOVDstorezero [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVDstorezeroidx ptr idx mem)
+(MOVWstorezero [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVWstorezeroidx ptr idx mem)
+(MOVHstorezero [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVHstorezeroidx ptr idx mem)
+(MOVBstorezero [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil => (MOVBstorezeroidx ptr idx mem)
+(MOVDstoreidx ptr idx (MOVDconst [0]) mem) => (MOVDstorezeroidx ptr idx mem)
+(MOVWstoreidx ptr idx (MOVDconst [0]) mem) => (MOVWstorezeroidx ptr idx mem)
+(MOVHstoreidx ptr idx (MOVDconst [0]) mem) => (MOVHstorezeroidx ptr idx mem)
+(MOVBstoreidx ptr idx (MOVDconst [0]) mem) => (MOVBstorezeroidx ptr idx mem)
+(MOVDstorezeroidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVDstorezero [int32(c)] ptr mem)
+(MOVDstorezeroidx (MOVDconst [c]) idx mem) && is32Bit(c) => (MOVDstorezero [int32(c)] idx mem)
+(MOVWstorezeroidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVWstorezero [int32(c)] ptr mem)
+(MOVWstorezeroidx (MOVDconst [c]) idx mem) && is32Bit(c) => (MOVWstorezero [int32(c)] idx mem)
+(MOVHstorezeroidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVHstorezero [int32(c)] ptr mem)
+(MOVHstorezeroidx (MOVDconst [c]) idx mem) && is32Bit(c) => (MOVHstorezero [int32(c)] idx mem)
+(MOVBstorezeroidx ptr (MOVDconst [c]) mem) && is32Bit(c) => (MOVBstorezero [int32(c)] ptr mem)
+(MOVBstorezeroidx (MOVDconst [c]) idx mem) && is32Bit(c) => (MOVBstorezero [int32(c)] idx mem)
+
+// shifted register indexed store zero
+(MOVDstorezero [off] {sym} (ADDshiftLL [3] ptr idx) mem) && off == 0 && sym == nil => (MOVDstorezeroidx8 ptr idx mem)
+(MOVWstorezero [off] {sym} (ADDshiftLL [2] ptr idx) mem) && off == 0 && sym == nil => (MOVWstorezeroidx4 ptr idx mem)
+(MOVHstorezero [off] {sym} (ADDshiftLL [1] ptr idx) mem) && off == 0 && sym == nil => (MOVHstorezeroidx2 ptr idx mem)
+(MOVDstorezeroidx ptr (SLLconst [3] idx) mem) => (MOVDstorezeroidx8 ptr idx mem)
+(MOVWstorezeroidx ptr (SLLconst [2] idx) mem) => (MOVWstorezeroidx4 ptr idx mem)
+(MOVHstorezeroidx ptr (SLLconst [1] idx) mem) => (MOVHstorezeroidx2 ptr idx mem)
+(MOVHstorezeroidx ptr (ADD idx idx) mem) => (MOVHstorezeroidx2 ptr idx mem)
+(MOVDstorezeroidx (SLLconst [3] idx) ptr mem) => (MOVDstorezeroidx8 ptr idx mem)
+(MOVWstorezeroidx (SLLconst [2] idx) ptr mem) => (MOVWstorezeroidx4 ptr idx mem)
+(MOVHstorezeroidx (SLLconst [1] idx) ptr mem) => (MOVHstorezeroidx2 ptr idx mem)
+(MOVHstorezeroidx (ADD idx idx) ptr mem) => (MOVHstorezeroidx2 ptr idx mem)
+(MOVDstoreidx8 ptr idx (MOVDconst [0]) mem) => (MOVDstorezeroidx8 ptr idx mem)
+(MOVWstoreidx4 ptr idx (MOVDconst [0]) mem) => (MOVWstorezeroidx4 ptr idx mem)
+(MOVHstoreidx2 ptr idx (MOVDconst [0]) mem) => (MOVHstorezeroidx2 ptr idx mem)
+(MOVDstorezeroidx8 ptr (MOVDconst [c]) mem) && is32Bit(c<<3) => (MOVDstorezero [int32(c<<3)] ptr mem)
+(MOVWstorezeroidx4 ptr (MOVDconst [c]) mem) && is32Bit(c<<2) => (MOVWstorezero [int32(c<<2)] ptr mem)
+(MOVHstorezeroidx2 ptr (MOVDconst [c]) mem) && is32Bit(c<<1) => (MOVHstorezero [int32(c<<1)] ptr mem)
+
+// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
+// these seem to have bad interaction with other rules, resulting in slower code
+//(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBreg x)
+//(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBUreg x)
+//(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHreg x)
+//(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHUreg x)
+//(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWreg x)
+//(MOVWUload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWUreg x)
+//(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
+//(FMOVSload [off] {sym} ptr (FMOVSstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
+//(FMOVDload [off] {sym} ptr (FMOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
+
+(MOVBload [off] {sym} ptr (MOVBstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVDconst [0])
+(MOVBUload [off] {sym} ptr (MOVBstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVDconst [0])
+(MOVHload [off] {sym} ptr (MOVHstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVDconst [0])
+(MOVHUload [off] {sym} ptr (MOVHstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVDconst [0])
+(MOVWload [off] {sym} ptr (MOVWstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVDconst [0])
+(MOVWUload [off] {sym} ptr (MOVWstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVDconst [0])
+(MOVDload [off] {sym} ptr (MOVDstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVDconst [0])
+
+(MOVBloadidx ptr idx (MOVBstorezeroidx ptr2 idx2 _))
+ && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) => (MOVDconst [0])
+(MOVBUloadidx ptr idx (MOVBstorezeroidx ptr2 idx2 _))
+ && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) => (MOVDconst [0])
+(MOVHloadidx ptr idx (MOVHstorezeroidx ptr2 idx2 _))
+ && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) => (MOVDconst [0])
+(MOVHUloadidx ptr idx (MOVHstorezeroidx ptr2 idx2 _))
+ && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) => (MOVDconst [0])
+(MOVWloadidx ptr idx (MOVWstorezeroidx ptr2 idx2 _))
+ && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) => (MOVDconst [0])
+(MOVWUloadidx ptr idx (MOVWstorezeroidx ptr2 idx2 _))
+ && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) => (MOVDconst [0])
+(MOVDloadidx ptr idx (MOVDstorezeroidx ptr2 idx2 _))
+ && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) => (MOVDconst [0])
+
+(MOVHloadidx2 ptr idx (MOVHstorezeroidx2 ptr2 idx2 _)) && isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) => (MOVDconst [0])
+(MOVHUloadidx2 ptr idx (MOVHstorezeroidx2 ptr2 idx2 _)) && isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) => (MOVDconst [0])
+(MOVWloadidx4 ptr idx (MOVWstorezeroidx4 ptr2 idx2 _)) && isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) => (MOVDconst [0])
+(MOVWUloadidx4 ptr idx (MOVWstorezeroidx4 ptr2 idx2 _)) && isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) => (MOVDconst [0])
+(MOVDloadidx8 ptr idx (MOVDstorezeroidx8 ptr2 idx2 _)) && isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) => (MOVDconst [0])
+
+// don't extend after proper load
+(MOVBreg x:(MOVBload _ _)) => (MOVDreg x)
+(MOVBUreg x:(MOVBUload _ _)) => (MOVDreg x)
+(MOVHreg x:(MOVBload _ _)) => (MOVDreg x)
+(MOVHreg x:(MOVBUload _ _)) => (MOVDreg x)
+(MOVHreg x:(MOVHload _ _)) => (MOVDreg x)
+(MOVHUreg x:(MOVBUload _ _)) => (MOVDreg x)
+(MOVHUreg x:(MOVHUload _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVBload _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVBUload _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVHload _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVHUload _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVWload _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVBUload _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVHUload _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVWUload _ _)) => (MOVDreg x)
+(MOVBreg x:(MOVBloadidx _ _ _)) => (MOVDreg x)
+(MOVBUreg x:(MOVBUloadidx _ _ _)) => (MOVDreg x)
+(MOVHreg x:(MOVBloadidx _ _ _)) => (MOVDreg x)
+(MOVHreg x:(MOVBUloadidx _ _ _)) => (MOVDreg x)
+(MOVHreg x:(MOVHloadidx _ _ _)) => (MOVDreg x)
+(MOVHUreg x:(MOVBUloadidx _ _ _)) => (MOVDreg x)
+(MOVHUreg x:(MOVHUloadidx _ _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVBloadidx _ _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVBUloadidx _ _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVHloadidx _ _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVHUloadidx _ _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVWloadidx _ _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVBUloadidx _ _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVHUloadidx _ _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVWUloadidx _ _ _)) => (MOVDreg x)
+(MOVHreg x:(MOVHloadidx2 _ _ _)) => (MOVDreg x)
+(MOVHUreg x:(MOVHUloadidx2 _ _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVHloadidx2 _ _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVHUloadidx2 _ _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVWloadidx4 _ _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVHUloadidx2 _ _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVWUloadidx4 _ _ _)) => (MOVDreg x)
+
+// fold double extensions
+(MOVBreg x:(MOVBreg _)) => (MOVDreg x)
+(MOVBUreg x:(MOVBUreg _)) => (MOVDreg x)
+(MOVHreg x:(MOVBreg _)) => (MOVDreg x)
+(MOVHreg x:(MOVBUreg _)) => (MOVDreg x)
+(MOVHreg x:(MOVHreg _)) => (MOVDreg x)
+(MOVHUreg x:(MOVBUreg _)) => (MOVDreg x)
+(MOVHUreg x:(MOVHUreg _)) => (MOVDreg x)
+(MOVWreg x:(MOVBreg _)) => (MOVDreg x)
+(MOVWreg x:(MOVBUreg _)) => (MOVDreg x)
+(MOVWreg x:(MOVHreg _)) => (MOVDreg x)
+(MOVWreg x:(MOVWreg _)) => (MOVDreg x)
+(MOVWUreg x:(MOVBUreg _)) => (MOVDreg x)
+(MOVWUreg x:(MOVHUreg _)) => (MOVDreg x)
+(MOVWUreg x:(MOVWUreg _)) => (MOVDreg x)
+
+// don't extend before store
+(MOVBstore [off] {sym} ptr (MOVBreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVBUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVHreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVHUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVWreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVWreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOVWreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
+(MOVBstoreidx ptr idx (MOVBreg x) mem) => (MOVBstoreidx ptr idx x mem)
+(MOVBstoreidx ptr idx (MOVBUreg x) mem) => (MOVBstoreidx ptr idx x mem)
+(MOVBstoreidx ptr idx (MOVHreg x) mem) => (MOVBstoreidx ptr idx x mem)
+(MOVBstoreidx ptr idx (MOVHUreg x) mem) => (MOVBstoreidx ptr idx x mem)
+(MOVBstoreidx ptr idx (MOVWreg x) mem) => (MOVBstoreidx ptr idx x mem)
+(MOVBstoreidx ptr idx (MOVWUreg x) mem) => (MOVBstoreidx ptr idx x mem)
+(MOVHstoreidx ptr idx (MOVHreg x) mem) => (MOVHstoreidx ptr idx x mem)
+(MOVHstoreidx ptr idx (MOVHUreg x) mem) => (MOVHstoreidx ptr idx x mem)
+(MOVHstoreidx ptr idx (MOVWreg x) mem) => (MOVHstoreidx ptr idx x mem)
+(MOVHstoreidx ptr idx (MOVWUreg x) mem) => (MOVHstoreidx ptr idx x mem)
+(MOVWstoreidx ptr idx (MOVWreg x) mem) => (MOVWstoreidx ptr idx x mem)
+(MOVWstoreidx ptr idx (MOVWUreg x) mem) => (MOVWstoreidx ptr idx x mem)
+(MOVHstoreidx2 ptr idx (MOVHreg x) mem) => (MOVHstoreidx2 ptr idx x mem)
+(MOVHstoreidx2 ptr idx (MOVHUreg x) mem) => (MOVHstoreidx2 ptr idx x mem)
+(MOVHstoreidx2 ptr idx (MOVWreg x) mem) => (MOVHstoreidx2 ptr idx x mem)
+(MOVHstoreidx2 ptr idx (MOVWUreg x) mem) => (MOVHstoreidx2 ptr idx x mem)
+(MOVWstoreidx4 ptr idx (MOVWreg x) mem) => (MOVWstoreidx4 ptr idx x mem)
+(MOVWstoreidx4 ptr idx (MOVWUreg x) mem) => (MOVWstoreidx4 ptr idx x mem)
+
+// if a register move has only 1 use, just use the same register without emitting instruction
+// MOVDnop doesn't emit instruction, only for ensuring the type.
+(MOVDreg x) && x.Uses == 1 => (MOVDnop x)
+
+// fold constant into arithmatic ops
+(ADD x (MOVDconst [c])) => (ADDconst [c] x)
+(SUB x (MOVDconst [c])) => (SUBconst [c] x)
+(AND x (MOVDconst [c])) => (ANDconst [c] x)
+(OR x (MOVDconst [c])) => (ORconst [c] x)
+(XOR x (MOVDconst [c])) => (XORconst [c] x)
+(TST x (MOVDconst [c])) => (TSTconst [c] x)
+(TSTW x (MOVDconst [c])) => (TSTWconst [int32(c)] x)
+(CMN x (MOVDconst [c])) => (CMNconst [c] x)
+(CMNW x (MOVDconst [c])) => (CMNWconst [int32(c)] x)
+(BIC x (MOVDconst [c])) => (ANDconst [^c] x)
+(EON x (MOVDconst [c])) => (XORconst [^c] x)
+(ORN x (MOVDconst [c])) => (ORconst [^c] x)
+
+(SLL x (MOVDconst [c])) => (SLLconst x [c&63]) // Note: I don't think we ever generate bad constant shifts (i.e. c>=64)
+(SRL x (MOVDconst [c])) => (SRLconst x [c&63])
+(SRA x (MOVDconst [c])) => (SRAconst x [c&63])
+
+(CMP x (MOVDconst [c])) => (CMPconst [c] x)
+(CMP (MOVDconst [c]) x) => (InvertFlags (CMPconst [c] x))
+(CMPW x (MOVDconst [c])) => (CMPWconst [int32(c)] x)
+(CMPW (MOVDconst [c]) x) => (InvertFlags (CMPWconst [int32(c)] x))
+
+// Canonicalize the order of arguments to comparisons - helps with CSE.
+((CMP|CMPW) x y) && x.ID > y.ID => (InvertFlags ((CMP|CMPW) y x))
+
+// mul-neg => mneg
+(NEG (MUL x y)) => (MNEG x y)
+(NEG (MULW x y)) => (MNEGW x y)
+(MUL (NEG x) y) => (MNEG x y)
+(MULW (NEG x) y) => (MNEGW x y)
+
+// madd/msub
+(ADD a l:(MUL x y)) && l.Uses==1 && clobber(l) => (MADD a x y)
+(SUB a l:(MUL x y)) && l.Uses==1 && clobber(l) => (MSUB a x y)
+(ADD a l:(MNEG x y)) && l.Uses==1 && clobber(l) => (MSUB a x y)
+(SUB a l:(MNEG x y)) && l.Uses==1 && clobber(l) => (MADD a x y)
+
+(ADD a l:(MULW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) => (MADDW a x y)
+(SUB a l:(MULW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) => (MSUBW a x y)
+(ADD a l:(MNEGW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) => (MSUBW a x y)
+(SUB a l:(MNEGW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) => (MADDW a x y)
+
+// optimize ADCSflags, SBCSflags and friends
+(ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] (ADCzerocarry <typ.UInt64> c)))) => (ADCSflags x y c)
+(ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] (MOVDconst [0])))) => (ADDSflags x y)
+(SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags (NEG <typ.UInt64> (NGCzerocarry <typ.UInt64> bo))))) => (SBCSflags x y bo)
+(SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags (MOVDconst [0])))) => (SUBSflags x y)
+
+// mul by constant
+(MUL x (MOVDconst [-1])) => (NEG x)
+(MUL _ (MOVDconst [0])) => (MOVDconst [0])
+(MUL x (MOVDconst [1])) => x
+(MUL x (MOVDconst [c])) && isPowerOfTwo64(c) => (SLLconst [log64(c)] x)
+(MUL x (MOVDconst [c])) && isPowerOfTwo64(c-1) && c >= 3 => (ADDshiftLL x x [log64(c-1)])
+(MUL x (MOVDconst [c])) && isPowerOfTwo64(c+1) && c >= 7 => (ADDshiftLL (NEG <x.Type> x) x [log64(c+1)])
+(MUL x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo64(c/3) => (SLLconst [log64(c/3)] (ADDshiftLL <x.Type> x x [1]))
+(MUL x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo64(c/5) => (SLLconst [log64(c/5)] (ADDshiftLL <x.Type> x x [2]))
+(MUL x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo64(c/7) => (SLLconst [log64(c/7)] (ADDshiftLL <x.Type> (NEG <x.Type> x) x [3]))
+(MUL x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo64(c/9) => (SLLconst [log64(c/9)] (ADDshiftLL <x.Type> x x [3]))
+
+(MULW x (MOVDconst [c])) && int32(c)==-1 => (NEG x)
+(MULW _ (MOVDconst [c])) && int32(c)==0 => (MOVDconst [0])
+(MULW x (MOVDconst [c])) && int32(c)==1 => x
+(MULW x (MOVDconst [c])) && isPowerOfTwo64(c) => (SLLconst [log64(c)] x)
+(MULW x (MOVDconst [c])) && isPowerOfTwo64(c-1) && int32(c) >= 3 => (ADDshiftLL x x [log64(c-1)])
+(MULW x (MOVDconst [c])) && isPowerOfTwo64(c+1) && int32(c) >= 7 => (ADDshiftLL (NEG <x.Type> x) x [log64(c+1)])
+(MULW x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c) => (SLLconst [log64(c/3)] (ADDshiftLL <x.Type> x x [1]))
+(MULW x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c) => (SLLconst [log64(c/5)] (ADDshiftLL <x.Type> x x [2]))
+(MULW x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c) => (SLLconst [log64(c/7)] (ADDshiftLL <x.Type> (NEG <x.Type> x) x [3]))
+(MULW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c) => (SLLconst [log64(c/9)] (ADDshiftLL <x.Type> x x [3]))
+
+// mneg by constant
+(MNEG x (MOVDconst [-1])) => x
+(MNEG _ (MOVDconst [0])) => (MOVDconst [0])
+(MNEG x (MOVDconst [1])) => (NEG x)
+(MNEG x (MOVDconst [c])) && isPowerOfTwo64(c) => (NEG (SLLconst <x.Type> [log64(c)] x))
+(MNEG x (MOVDconst [c])) && isPowerOfTwo64(c-1) && c >= 3 => (NEG (ADDshiftLL <x.Type> x x [log64(c-1)]))
+(MNEG x (MOVDconst [c])) && isPowerOfTwo64(c+1) && c >= 7 => (NEG (ADDshiftLL <x.Type> (NEG <x.Type> x) x [log64(c+1)]))
+(MNEG x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo64(c/3) => (SLLconst <x.Type> [log64(c/3)] (SUBshiftLL <x.Type> x x [2]))
+(MNEG x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo64(c/5) => (NEG (SLLconst <x.Type> [log64(c/5)] (ADDshiftLL <x.Type> x x [2])))
+(MNEG x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo64(c/7) => (SLLconst <x.Type> [log64(c/7)] (SUBshiftLL <x.Type> x x [3]))
+(MNEG x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo64(c/9) => (NEG (SLLconst <x.Type> [log64(c/9)] (ADDshiftLL <x.Type> x x [3])))
+
+
+(MNEGW x (MOVDconst [c])) && int32(c)==-1 => x
+(MNEGW _ (MOVDconst [c])) && int32(c)==0 => (MOVDconst [0])
+(MNEGW x (MOVDconst [c])) && int32(c)==1 => (NEG x)
+(MNEGW x (MOVDconst [c])) && isPowerOfTwo64(c) => (NEG (SLLconst <x.Type> [log64(c)] x))
+(MNEGW x (MOVDconst [c])) && isPowerOfTwo64(c-1) && int32(c) >= 3 => (NEG (ADDshiftLL <x.Type> x x [log64(c-1)]))
+(MNEGW x (MOVDconst [c])) && isPowerOfTwo64(c+1) && int32(c) >= 7 => (NEG (ADDshiftLL <x.Type> (NEG <x.Type> x) x [log64(c+1)]))
+(MNEGW x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c) => (SLLconst <x.Type> [log64(c/3)] (SUBshiftLL <x.Type> x x [2]))
+(MNEGW x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c) => (NEG (SLLconst <x.Type> [log64(c/5)] (ADDshiftLL <x.Type> x x [2])))
+(MNEGW x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c) => (SLLconst <x.Type> [log64(c/7)] (SUBshiftLL <x.Type> x x [3]))
+(MNEGW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c) => (NEG (SLLconst <x.Type> [log64(c/9)] (ADDshiftLL <x.Type> x x [3])))
+
+
+(MADD a x (MOVDconst [-1])) => (SUB a x)
+(MADD a _ (MOVDconst [0])) => a
+(MADD a x (MOVDconst [1])) => (ADD a x)
+(MADD a x (MOVDconst [c])) && isPowerOfTwo64(c) => (ADDshiftLL a x [log64(c)])
+(MADD a x (MOVDconst [c])) && isPowerOfTwo64(c-1) && c>=3 => (ADD a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+(MADD a x (MOVDconst [c])) && isPowerOfTwo64(c+1) && c>=7 => (SUB a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+(MADD a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo64(c/3) => (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+(MADD a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo64(c/5) => (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+(MADD a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo64(c/7) => (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+(MADD a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo64(c/9) => (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+
+(MADD a (MOVDconst [-1]) x) => (SUB a x)
+(MADD a (MOVDconst [0]) _) => a
+(MADD a (MOVDconst [1]) x) => (ADD a x)
+(MADD a (MOVDconst [c]) x) && isPowerOfTwo64(c) => (ADDshiftLL a x [log64(c)])
+(MADD a (MOVDconst [c]) x) && isPowerOfTwo64(c-1) && c>=3 => (ADD a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+(MADD a (MOVDconst [c]) x) && isPowerOfTwo64(c+1) && c>=7 => (SUB a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+(MADD a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo64(c/3) => (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+(MADD a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo64(c/5) => (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+(MADD a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo64(c/7) => (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+(MADD a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo64(c/9) => (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+
+(MADDW a x (MOVDconst [c])) && int32(c)==-1 => (SUB a x)
+(MADDW a _ (MOVDconst [c])) && int32(c)==0 => a
+(MADDW a x (MOVDconst [c])) && int32(c)==1 => (ADD a x)
+(MADDW a x (MOVDconst [c])) && isPowerOfTwo64(c) => (ADDshiftLL a x [log64(c)])
+(MADDW a x (MOVDconst [c])) && isPowerOfTwo64(c-1) && int32(c)>=3 => (ADD a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+(MADDW a x (MOVDconst [c])) && isPowerOfTwo64(c+1) && int32(c)>=7 => (SUB a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+(MADDW a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c) => (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+(MADDW a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c) => (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+(MADDW a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c) => (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+(MADDW a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c) => (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+
+(MADDW a (MOVDconst [c]) x) && int32(c)==-1 => (SUB a x)
+(MADDW a (MOVDconst [c]) _) && int32(c)==0 => a
+(MADDW a (MOVDconst [c]) x) && int32(c)==1 => (ADD a x)
+(MADDW a (MOVDconst [c]) x) && isPowerOfTwo64(c) => (ADDshiftLL a x [log64(c)])
+(MADDW a (MOVDconst [c]) x) && isPowerOfTwo64(c-1) && int32(c)>=3 => (ADD a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+(MADDW a (MOVDconst [c]) x) && isPowerOfTwo64(c+1) && int32(c)>=7 => (SUB a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+(MADDW a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c) => (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+(MADDW a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c) => (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+(MADDW a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c) => (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+(MADDW a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c) => (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+
+(MSUB a x (MOVDconst [-1])) => (ADD a x)
+(MSUB a _ (MOVDconst [0])) => a
+(MSUB a x (MOVDconst [1])) => (SUB a x)
+(MSUB a x (MOVDconst [c])) && isPowerOfTwo64(c) => (SUBshiftLL a x [log64(c)])
+(MSUB a x (MOVDconst [c])) && isPowerOfTwo64(c-1) && c>=3 => (SUB a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+(MSUB a x (MOVDconst [c])) && isPowerOfTwo64(c+1) && c>=7 => (ADD a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+(MSUB a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo64(c/3) => (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+(MSUB a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo64(c/5) => (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+(MSUB a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo64(c/7) => (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+(MSUB a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo64(c/9) => (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+
+(MSUB a (MOVDconst [-1]) x) => (ADD a x)
+(MSUB a (MOVDconst [0]) _) => a
+(MSUB a (MOVDconst [1]) x) => (SUB a x)
+(MSUB a (MOVDconst [c]) x) && isPowerOfTwo64(c) => (SUBshiftLL a x [log64(c)])
+(MSUB a (MOVDconst [c]) x) && isPowerOfTwo64(c-1) && c>=3 => (SUB a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+(MSUB a (MOVDconst [c]) x) && isPowerOfTwo64(c+1) && c>=7 => (ADD a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+(MSUB a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo64(c/3) => (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+(MSUB a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo64(c/5) => (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+(MSUB a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo64(c/7) => (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+(MSUB a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo64(c/9) => (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+
+(MSUBW a x (MOVDconst [c])) && int32(c)==-1 => (ADD a x)
+(MSUBW a _ (MOVDconst [c])) && int32(c)==0 => a
+(MSUBW a x (MOVDconst [c])) && int32(c)==1 => (SUB a x)
+(MSUBW a x (MOVDconst [c])) && isPowerOfTwo64(c) => (SUBshiftLL a x [log64(c)])
+(MSUBW a x (MOVDconst [c])) && isPowerOfTwo64(c-1) && int32(c)>=3 => (SUB a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+(MSUBW a x (MOVDconst [c])) && isPowerOfTwo64(c+1) && int32(c)>=7 => (ADD a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+(MSUBW a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c) => (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+(MSUBW a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c) => (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+(MSUBW a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c) => (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+(MSUBW a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c) => (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+
+(MSUBW a (MOVDconst [c]) x) && int32(c)==-1 => (ADD a x)
+(MSUBW a (MOVDconst [c]) _) && int32(c)==0 => a
+(MSUBW a (MOVDconst [c]) x) && int32(c)==1 => (SUB a x)
+(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo64(c) => (SUBshiftLL a x [log64(c)])
+(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo64(c-1) && int32(c)>=3 => (SUB a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo64(c+1) && int32(c)>=7 => (ADD a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+(MSUBW a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c) => (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+(MSUBW a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c) => (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+(MSUBW a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c) => (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+(MSUBW a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c) => (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+
+// div by constant
+(UDIV x (MOVDconst [1])) => x
+(UDIV x (MOVDconst [c])) && isPowerOfTwo64(c) => (SRLconst [log64(c)] x)
+(UDIVW x (MOVDconst [c])) && uint32(c)==1 => x
+(UDIVW x (MOVDconst [c])) && isPowerOfTwo64(c) && is32Bit(c) => (SRLconst [log64(c)] x)
+(UMOD _ (MOVDconst [1])) => (MOVDconst [0])
+(UMOD x (MOVDconst [c])) && isPowerOfTwo64(c) => (ANDconst [c-1] x)
+(UMODW _ (MOVDconst [c])) && uint32(c)==1 => (MOVDconst [0])
+(UMODW x (MOVDconst [c])) && isPowerOfTwo64(c) && is32Bit(c) => (ANDconst [c-1] x)
+
+// generic simplifications
+(ADD x (NEG y)) => (SUB x y)
+(SUB x x) => (MOVDconst [0])
+(AND x x) => x
+(OR x x) => x
+(XOR x x) => (MOVDconst [0])
+(BIC x x) => (MOVDconst [0])
+(EON x x) => (MOVDconst [-1])
+(ORN x x) => (MOVDconst [-1])
+(AND x (MVN y)) => (BIC x y)
+(XOR x (MVN y)) => (EON x y)
+(OR x (MVN y)) => (ORN x y)
+(MVN (XOR x y)) => (EON x y)
+(CSEL [cc] x (MOVDconst [0]) flag) => (CSEL0 [cc] x flag)
+(CSEL [cc] (MOVDconst [0]) y flag) => (CSEL0 [arm64Negate(cc)] y flag)
+(SUB x (SUB y z)) => (SUB (ADD <v.Type> x z) y)
+(SUB (SUB x y) z) => (SUB x (ADD <y.Type> y z))
+
+// remove redundant *const ops
+(ADDconst [0] x) => x
+(SUBconst [0] x) => x
+(ANDconst [0] _) => (MOVDconst [0])
+(ANDconst [-1] x) => x
+(ORconst [0] x) => x
+(ORconst [-1] _) => (MOVDconst [-1])
+(XORconst [0] x) => x
+(XORconst [-1] x) => (MVN x)
+
+// generic constant folding
+(ADDconst [c] (MOVDconst [d])) => (MOVDconst [c+d])
+(ADDconst [c] (ADDconst [d] x)) => (ADDconst [c+d] x)
+(ADDconst [c] (SUBconst [d] x)) => (ADDconst [c-d] x)
+(SUBconst [c] (MOVDconst [d])) => (MOVDconst [d-c])
+(SUBconst [c] (SUBconst [d] x)) => (ADDconst [-c-d] x)
+(SUBconst [c] (ADDconst [d] x)) => (ADDconst [-c+d] x)
+(SLLconst [c] (MOVDconst [d])) => (MOVDconst [d<<uint64(c)])
+(SRLconst [c] (MOVDconst [d])) => (MOVDconst [int64(uint64(d)>>uint64(c))])
+(SRAconst [c] (MOVDconst [d])) => (MOVDconst [d>>uint64(c)])
+(MUL (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c*d])
+(MULW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(int32(c)*int32(d))])
+(MNEG (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [-c*d])
+(MNEGW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [-int64(int32(c)*int32(d))])
+(MADD (MOVDconst [c]) x y) => (ADDconst [c] (MUL <x.Type> x y))
+(MADDW (MOVDconst [c]) x y) => (ADDconst [c] (MULW <x.Type> x y))
+(MSUB (MOVDconst [c]) x y) => (ADDconst [c] (MNEG <x.Type> x y))
+(MSUBW (MOVDconst [c]) x y) => (ADDconst [c] (MNEGW <x.Type> x y))
+(MADD a (MOVDconst [c]) (MOVDconst [d])) => (ADDconst [c*d] a)
+(MADDW a (MOVDconst [c]) (MOVDconst [d])) => (ADDconst [int64(int32(c)*int32(d))] a)
+(MSUB a (MOVDconst [c]) (MOVDconst [d])) => (SUBconst [c*d] a)
+(MSUBW a (MOVDconst [c]) (MOVDconst [d])) => (SUBconst [int64(int32(c)*int32(d))] a)
+(DIV (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [c/d])
+(UDIV (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint64(c)/uint64(d))])
+(DIVW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(int32(c)/int32(d))])
+(UDIVW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint32(c)/uint32(d))])
+(MOD (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [c%d])
+(UMOD (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint64(c)%uint64(d))])
+(MODW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(int32(c)%int32(d))])
+(UMODW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint32(c)%uint32(d))])
+(ANDconst [c] (MOVDconst [d])) => (MOVDconst [c&d])
+(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
+(ANDconst [c] (MOVWUreg x)) => (ANDconst [c&(1<<32-1)] x)
+(ANDconst [c] (MOVHUreg x)) => (ANDconst [c&(1<<16-1)] x)
+(ANDconst [c] (MOVBUreg x)) => (ANDconst [c&(1<<8-1)] x)
+(MOVWUreg (ANDconst [c] x)) => (ANDconst [c&(1<<32-1)] x)
+(MOVHUreg (ANDconst [c] x)) => (ANDconst [c&(1<<16-1)] x)
+(MOVBUreg (ANDconst [c] x)) => (ANDconst [c&(1<<8-1)] x)
+(ORconst [c] (MOVDconst [d])) => (MOVDconst [c|d])
+(ORconst [c] (ORconst [d] x)) => (ORconst [c|d] x)
+(XORconst [c] (MOVDconst [d])) => (MOVDconst [c^d])
+(XORconst [c] (XORconst [d] x)) => (XORconst [c^d] x)
+(MVN (MOVDconst [c])) => (MOVDconst [^c])
+(NEG (MOVDconst [c])) => (MOVDconst [-c])
+(MOVBreg (MOVDconst [c])) => (MOVDconst [int64(int8(c))])
+(MOVBUreg (MOVDconst [c])) => (MOVDconst [int64(uint8(c))])
+(MOVHreg (MOVDconst [c])) => (MOVDconst [int64(int16(c))])
+(MOVHUreg (MOVDconst [c])) => (MOVDconst [int64(uint16(c))])
+(MOVWreg (MOVDconst [c])) => (MOVDconst [int64(int32(c))])
+(MOVWUreg (MOVDconst [c])) => (MOVDconst [int64(uint32(c))])
+(MOVDreg (MOVDconst [c])) => (MOVDconst [c])
+
+// constant comparisons
+(CMPconst (MOVDconst [x]) [y]) => (FlagConstant [subFlags64(x,y)])
+(CMPWconst (MOVDconst [x]) [y]) => (FlagConstant [subFlags32(int32(x),y)])
+(TSTconst (MOVDconst [x]) [y]) => (FlagConstant [logicFlags64(x&y)])
+(TSTWconst (MOVDconst [x]) [y]) => (FlagConstant [logicFlags32(int32(x)&y)])
+(CMNconst (MOVDconst [x]) [y]) => (FlagConstant [addFlags64(x,y)])
+(CMNWconst (MOVDconst [x]) [y]) => (FlagConstant [addFlags32(int32(x),y)])
+
+// other known comparisons
+(CMPconst (MOVBUreg _) [c]) && 0xff < c => (FlagConstant [subFlags64(0,1)])
+(CMPconst (MOVHUreg _) [c]) && 0xffff < c => (FlagConstant [subFlags64(0,1)])
+(CMPconst (MOVWUreg _) [c]) && 0xffffffff < c => (FlagConstant [subFlags64(0,1)])
+(CMPconst (ANDconst _ [m]) [n]) && 0 <= m && m < n => (FlagConstant [subFlags64(0,1)])
+(CMPconst (SRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 63 && (1<<uint64(64-c)) <= uint64(n) => (FlagConstant [subFlags64(0,1)])
+(CMPWconst (MOVBUreg _) [c]) && 0xff < c => (FlagConstant [subFlags64(0,1)])
+(CMPWconst (MOVHUreg _) [c]) && 0xffff < c => (FlagConstant [subFlags64(0,1)])
+
+// absorb flag constants into branches
+(EQ (FlagConstant [fc]) yes no) && fc.eq() => (First yes no)
+(EQ (FlagConstant [fc]) yes no) && !fc.eq() => (First no yes)
+
+(NE (FlagConstant [fc]) yes no) && fc.ne() => (First yes no)
+(NE (FlagConstant [fc]) yes no) && !fc.ne() => (First no yes)
+
+(LT (FlagConstant [fc]) yes no) && fc.lt() => (First yes no)
+(LT (FlagConstant [fc]) yes no) && !fc.lt() => (First no yes)
+
+(LE (FlagConstant [fc]) yes no) && fc.le() => (First yes no)
+(LE (FlagConstant [fc]) yes no) && !fc.le() => (First no yes)
+
+(GT (FlagConstant [fc]) yes no) && fc.gt() => (First yes no)
+(GT (FlagConstant [fc]) yes no) && !fc.gt() => (First no yes)
+
+(GE (FlagConstant [fc]) yes no) && fc.ge() => (First yes no)
+(GE (FlagConstant [fc]) yes no) && !fc.ge() => (First no yes)
+
+(ULT (FlagConstant [fc]) yes no) && fc.ult() => (First yes no)
+(ULT (FlagConstant [fc]) yes no) && !fc.ult() => (First no yes)
+
+(ULE (FlagConstant [fc]) yes no) && fc.ule() => (First yes no)
+(ULE (FlagConstant [fc]) yes no) && !fc.ule() => (First no yes)
+
+(UGT (FlagConstant [fc]) yes no) && fc.ugt() => (First yes no)
+(UGT (FlagConstant [fc]) yes no) && !fc.ugt() => (First no yes)
+
+(UGE (FlagConstant [fc]) yes no) && fc.uge() => (First yes no)
+(UGE (FlagConstant [fc]) yes no) && !fc.uge() => (First no yes)
+
+(LTnoov (FlagConstant [fc]) yes no) && fc.ltNoov() => (First yes no)
+(LTnoov (FlagConstant [fc]) yes no) && !fc.ltNoov() => (First no yes)
+
+(LEnoov (FlagConstant [fc]) yes no) && fc.leNoov() => (First yes no)
+(LEnoov (FlagConstant [fc]) yes no) && !fc.leNoov() => (First no yes)
+
+(GTnoov (FlagConstant [fc]) yes no) && fc.gtNoov() => (First yes no)
+(GTnoov (FlagConstant [fc]) yes no) && !fc.gtNoov() => (First no yes)
+
+(GEnoov (FlagConstant [fc]) yes no) && fc.geNoov() => (First yes no)
+(GEnoov (FlagConstant [fc]) yes no) && !fc.geNoov() => (First no yes)
+
+(Z (MOVDconst [0]) yes no) => (First yes no)
+(Z (MOVDconst [c]) yes no) && c != 0 => (First no yes)
+(NZ (MOVDconst [0]) yes no) => (First no yes)
+(NZ (MOVDconst [c]) yes no) && c != 0 => (First yes no)
+(ZW (MOVDconst [c]) yes no) && int32(c) == 0 => (First yes no)
+(ZW (MOVDconst [c]) yes no) && int32(c) != 0 => (First no yes)
+(NZW (MOVDconst [c]) yes no) && int32(c) == 0 => (First no yes)
+(NZW (MOVDconst [c]) yes no) && int32(c) != 0 => (First yes no)
+
+// 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)
+(FLT (InvertFlags cmp) yes no) => (FGT cmp yes no)
+(FGT (InvertFlags cmp) yes no) => (FLT cmp yes no)
+(FLE (InvertFlags cmp) yes no) => (FGE cmp yes no)
+(FGE (InvertFlags cmp) yes no) => (FLE cmp yes no)
+(LTnoov (InvertFlags cmp) yes no) => (GTnoov cmp yes no)
+(GEnoov (InvertFlags cmp) yes no) => (LEnoov cmp yes no)
+(LEnoov (InvertFlags cmp) yes no) => (GEnoov cmp yes no)
+(GTnoov (InvertFlags cmp) yes no) => (LTnoov cmp yes no)
+
+// absorb InvertFlags into CSEL(0)
+(CSEL [cc] x y (InvertFlags cmp)) => (CSEL [arm64Invert(cc)] x y cmp)
+(CSEL0 [cc] x (InvertFlags cmp)) => (CSEL0 [arm64Invert(cc)] x cmp)
+
+// absorb flag constants into boolean values
+(Equal (FlagConstant [fc])) => (MOVDconst [b2i(fc.eq())])
+(NotEqual (FlagConstant [fc])) => (MOVDconst [b2i(fc.ne())])
+(LessThan (FlagConstant [fc])) => (MOVDconst [b2i(fc.lt())])
+(LessThanU (FlagConstant [fc])) => (MOVDconst [b2i(fc.ult())])
+(LessEqual (FlagConstant [fc])) => (MOVDconst [b2i(fc.le())])
+(LessEqualU (FlagConstant [fc])) => (MOVDconst [b2i(fc.ule())])
+(GreaterThan (FlagConstant [fc])) => (MOVDconst [b2i(fc.gt())])
+(GreaterThanU (FlagConstant [fc])) => (MOVDconst [b2i(fc.ugt())])
+(GreaterEqual (FlagConstant [fc])) => (MOVDconst [b2i(fc.ge())])
+(GreaterEqualU (FlagConstant [fc])) => (MOVDconst [b2i(fc.uge())])
+
+// absorb InvertFlags into boolean values
+(Equal (InvertFlags x)) => (Equal x)
+(NotEqual (InvertFlags x)) => (NotEqual x)
+(LessThan (InvertFlags x)) => (GreaterThan x)
+(LessThanU (InvertFlags x)) => (GreaterThanU x)
+(GreaterThan (InvertFlags x)) => (LessThan x)
+(GreaterThanU (InvertFlags x)) => (LessThanU x)
+(LessEqual (InvertFlags x)) => (GreaterEqual x)
+(LessEqualU (InvertFlags x)) => (GreaterEqualU x)
+(GreaterEqual (InvertFlags x)) => (LessEqual x)
+(GreaterEqualU (InvertFlags x)) => (LessEqualU x)
+(LessThanF (InvertFlags x)) => (GreaterThanF x)
+(LessEqualF (InvertFlags x)) => (GreaterEqualF x)
+(GreaterThanF (InvertFlags x)) => (LessThanF x)
+(GreaterEqualF (InvertFlags x)) => (LessEqualF x)
+
+// Boolean-generating instructions always
+// zero upper bit of the register; no need to zero-extend
+(MOVBUreg x) && x.Type.IsBoolean() => (MOVDreg x)
+
+// absorb flag constants into conditional instructions
+(CSEL [cc] x _ flag) && ccARM64Eval(cc, flag) > 0 => x
+(CSEL [cc] _ y flag) && ccARM64Eval(cc, flag) < 0 => y
+(CSEL0 [cc] x flag) && ccARM64Eval(cc, flag) > 0 => x
+(CSEL0 [cc] _ flag) && ccARM64Eval(cc, flag) < 0 => (MOVDconst [0])
+
+// absorb flags back into boolean CSEL
+(CSEL [cc] x y (CMPWconst [0] boolval)) && cc == OpARM64NotEqual && flagArg(boolval) != nil =>
+ (CSEL [boolval.Op] x y flagArg(boolval))
+(CSEL [cc] x y (CMPWconst [0] boolval)) && cc == OpARM64Equal && flagArg(boolval) != nil =>
+ (CSEL [arm64Negate(boolval.Op)] x y flagArg(boolval))
+(CSEL0 [cc] x (CMPWconst [0] boolval)) && cc == OpARM64NotEqual && flagArg(boolval) != nil =>
+ (CSEL0 [boolval.Op] x flagArg(boolval))
+(CSEL0 [cc] x (CMPWconst [0] boolval)) && cc == OpARM64Equal && flagArg(boolval) != nil =>
+ (CSEL0 [arm64Negate(boolval.Op)] x flagArg(boolval))
+
+// absorb shifts into ops
+(NEG x:(SLLconst [c] y)) && clobberIfDead(x) => (NEGshiftLL [c] y)
+(NEG x:(SRLconst [c] y)) && clobberIfDead(x) => (NEGshiftRL [c] y)
+(NEG x:(SRAconst [c] y)) && clobberIfDead(x) => (NEGshiftRA [c] y)
+(MVN x:(SLLconst [c] y)) && clobberIfDead(x) => (MVNshiftLL [c] y)
+(MVN x:(SRLconst [c] y)) && clobberIfDead(x) => (MVNshiftRL [c] y)
+(MVN x:(SRAconst [c] y)) && clobberIfDead(x) => (MVNshiftRA [c] y)
+(ADD x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (ADDshiftLL x0 y [c])
+(ADD x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (ADDshiftRL x0 y [c])
+(ADD x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (ADDshiftRA x0 y [c])
+(SUB x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (SUBshiftLL x0 y [c])
+(SUB x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (SUBshiftRL x0 y [c])
+(SUB x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (SUBshiftRA x0 y [c])
+(AND x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (ANDshiftLL x0 y [c])
+(AND x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (ANDshiftRL x0 y [c])
+(AND x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (ANDshiftRA x0 y [c])
+(OR x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (ORshiftLL x0 y [c]) // useful for combined load
+(OR x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (ORshiftRL x0 y [c])
+(OR x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (ORshiftRA x0 y [c])
+(XOR x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (XORshiftLL x0 y [c])
+(XOR x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (XORshiftRL x0 y [c])
+(XOR x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (XORshiftRA x0 y [c])
+(BIC x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (BICshiftLL x0 y [c])
+(BIC x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (BICshiftRL x0 y [c])
+(BIC x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (BICshiftRA x0 y [c])
+(ORN x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (ORNshiftLL x0 y [c])
+(ORN x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (ORNshiftRL x0 y [c])
+(ORN x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (ORNshiftRA x0 y [c])
+(EON x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (EONshiftLL x0 y [c])
+(EON x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (EONshiftRL x0 y [c])
+(EON x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (EONshiftRA x0 y [c])
+(CMP x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (CMPshiftLL x0 y [c])
+(CMP x0:(SLLconst [c] y) x1) && clobberIfDead(x0) => (InvertFlags (CMPshiftLL x1 y [c]))
+(CMP x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (CMPshiftRL x0 y [c])
+(CMP x0:(SRLconst [c] y) x1) && clobberIfDead(x0) => (InvertFlags (CMPshiftRL x1 y [c]))
+(CMP x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (CMPshiftRA x0 y [c])
+(CMP x0:(SRAconst [c] y) x1) && clobberIfDead(x0) => (InvertFlags (CMPshiftRA x1 y [c]))
+(CMN x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (CMNshiftLL x0 y [c])
+(CMN x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (CMNshiftRL x0 y [c])
+(CMN x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (CMNshiftRA x0 y [c])
+(TST x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (TSTshiftLL x0 y [c])
+(TST x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (TSTshiftRL x0 y [c])
+(TST x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (TSTshiftRA x0 y [c])
+
+// prefer *const ops to *shift ops
+(ADDshiftLL (MOVDconst [c]) x [d]) => (ADDconst [c] (SLLconst <x.Type> x [d]))
+(ADDshiftRL (MOVDconst [c]) x [d]) => (ADDconst [c] (SRLconst <x.Type> x [d]))
+(ADDshiftRA (MOVDconst [c]) x [d]) => (ADDconst [c] (SRAconst <x.Type> x [d]))
+(ANDshiftLL (MOVDconst [c]) x [d]) => (ANDconst [c] (SLLconst <x.Type> x [d]))
+(ANDshiftRL (MOVDconst [c]) x [d]) => (ANDconst [c] (SRLconst <x.Type> x [d]))
+(ANDshiftRA (MOVDconst [c]) x [d]) => (ANDconst [c] (SRAconst <x.Type> x [d]))
+(ORshiftLL (MOVDconst [c]) x [d]) => (ORconst [c] (SLLconst <x.Type> x [d]))
+(ORshiftRL (MOVDconst [c]) x [d]) => (ORconst [c] (SRLconst <x.Type> x [d]))
+(ORshiftRA (MOVDconst [c]) x [d]) => (ORconst [c] (SRAconst <x.Type> x [d]))
+(XORshiftLL (MOVDconst [c]) x [d]) => (XORconst [c] (SLLconst <x.Type> x [d]))
+(XORshiftRL (MOVDconst [c]) x [d]) => (XORconst [c] (SRLconst <x.Type> x [d]))
+(XORshiftRA (MOVDconst [c]) x [d]) => (XORconst [c] (SRAconst <x.Type> x [d]))
+(CMPshiftLL (MOVDconst [c]) x [d]) => (InvertFlags (CMPconst [c] (SLLconst <x.Type> x [d])))
+(CMPshiftRL (MOVDconst [c]) x [d]) => (InvertFlags (CMPconst [c] (SRLconst <x.Type> x [d])))
+(CMPshiftRA (MOVDconst [c]) x [d]) => (InvertFlags (CMPconst [c] (SRAconst <x.Type> x [d])))
+(CMNshiftLL (MOVDconst [c]) x [d]) => (CMNconst [c] (SLLconst <x.Type> x [d]))
+(CMNshiftRL (MOVDconst [c]) x [d]) => (CMNconst [c] (SRLconst <x.Type> x [d]))
+(CMNshiftRA (MOVDconst [c]) x [d]) => (CMNconst [c] (SRAconst <x.Type> x [d]))
+(TSTshiftLL (MOVDconst [c]) x [d]) => (TSTconst [c] (SLLconst <x.Type> x [d]))
+(TSTshiftRL (MOVDconst [c]) x [d]) => (TSTconst [c] (SRLconst <x.Type> x [d]))
+(TSTshiftRA (MOVDconst [c]) x [d]) => (TSTconst [c] (SRAconst <x.Type> x [d]))
+
+// constant folding in *shift ops
+(MVNshiftLL (MOVDconst [c]) [d]) => (MOVDconst [^int64(uint64(c)<<uint64(d))])
+(MVNshiftRL (MOVDconst [c]) [d]) => (MOVDconst [^int64(uint64(c)>>uint64(d))])
+(MVNshiftRA (MOVDconst [c]) [d]) => (MOVDconst [^(c>>uint64(d))])
+(NEGshiftLL (MOVDconst [c]) [d]) => (MOVDconst [-int64(uint64(c)<<uint64(d))])
+(NEGshiftRL (MOVDconst [c]) [d]) => (MOVDconst [-int64(uint64(c)>>uint64(d))])
+(NEGshiftRA (MOVDconst [c]) [d]) => (MOVDconst [-(c>>uint64(d))])
+(ADDshiftLL x (MOVDconst [c]) [d]) => (ADDconst x [int64(uint64(c)<<uint64(d))])
+(ADDshiftRL x (MOVDconst [c]) [d]) => (ADDconst x [int64(uint64(c)>>uint64(d))])
+(ADDshiftRA x (MOVDconst [c]) [d]) => (ADDconst x [c>>uint64(d)])
+(SUBshiftLL x (MOVDconst [c]) [d]) => (SUBconst x [int64(uint64(c)<<uint64(d))])
+(SUBshiftRL x (MOVDconst [c]) [d]) => (SUBconst x [int64(uint64(c)>>uint64(d))])
+(SUBshiftRA x (MOVDconst [c]) [d]) => (SUBconst x [c>>uint64(d)])
+(ANDshiftLL x (MOVDconst [c]) [d]) => (ANDconst x [int64(uint64(c)<<uint64(d))])
+(ANDshiftRL x (MOVDconst [c]) [d]) => (ANDconst x [int64(uint64(c)>>uint64(d))])
+(ANDshiftRA x (MOVDconst [c]) [d]) => (ANDconst x [c>>uint64(d)])
+(ORshiftLL x (MOVDconst [c]) [d]) => (ORconst x [int64(uint64(c)<<uint64(d))])
+(ORshiftRL x (MOVDconst [c]) [d]) => (ORconst x [int64(uint64(c)>>uint64(d))])
+(ORshiftRA x (MOVDconst [c]) [d]) => (ORconst x [c>>uint64(d)])
+(XORshiftLL x (MOVDconst [c]) [d]) => (XORconst x [int64(uint64(c)<<uint64(d))])
+(XORshiftRL x (MOVDconst [c]) [d]) => (XORconst x [int64(uint64(c)>>uint64(d))])
+(XORshiftRA x (MOVDconst [c]) [d]) => (XORconst x [c>>uint64(d)])
+(BICshiftLL x (MOVDconst [c]) [d]) => (ANDconst x [^int64(uint64(c)<<uint64(d))])
+(BICshiftRL x (MOVDconst [c]) [d]) => (ANDconst x [^int64(uint64(c)>>uint64(d))])
+(BICshiftRA x (MOVDconst [c]) [d]) => (ANDconst x [^(c>>uint64(d))])
+(ORNshiftLL x (MOVDconst [c]) [d]) => (ORconst x [^int64(uint64(c)<<uint64(d))])
+(ORNshiftRL x (MOVDconst [c]) [d]) => (ORconst x [^int64(uint64(c)>>uint64(d))])
+(ORNshiftRA x (MOVDconst [c]) [d]) => (ORconst x [^(c>>uint64(d))])
+(EONshiftLL x (MOVDconst [c]) [d]) => (XORconst x [^int64(uint64(c)<<uint64(d))])
+(EONshiftRL x (MOVDconst [c]) [d]) => (XORconst x [^int64(uint64(c)>>uint64(d))])
+(EONshiftRA x (MOVDconst [c]) [d]) => (XORconst x [^(c>>uint64(d))])
+(CMPshiftLL x (MOVDconst [c]) [d]) => (CMPconst x [int64(uint64(c)<<uint64(d))])
+(CMPshiftRL x (MOVDconst [c]) [d]) => (CMPconst x [int64(uint64(c)>>uint64(d))])
+(CMPshiftRA x (MOVDconst [c]) [d]) => (CMPconst x [c>>uint64(d)])
+(CMNshiftLL x (MOVDconst [c]) [d]) => (CMNconst x [int64(uint64(c)<<uint64(d))])
+(CMNshiftRL x (MOVDconst [c]) [d]) => (CMNconst x [int64(uint64(c)>>uint64(d))])
+(CMNshiftRA x (MOVDconst [c]) [d]) => (CMNconst x [c>>uint64(d)])
+(TSTshiftLL x (MOVDconst [c]) [d]) => (TSTconst x [int64(uint64(c)<<uint64(d))])
+(TSTshiftRL x (MOVDconst [c]) [d]) => (TSTconst x [int64(uint64(c)>>uint64(d))])
+(TSTshiftRA x (MOVDconst [c]) [d]) => (TSTconst x [c>>uint64(d)])
+
+// simplification with *shift ops
+(SUBshiftLL (SLLconst x [c]) x [c]) => (MOVDconst [0])
+(SUBshiftRL (SRLconst x [c]) x [c]) => (MOVDconst [0])
+(SUBshiftRA (SRAconst x [c]) x [c]) => (MOVDconst [0])
+(ANDshiftLL y:(SLLconst x [c]) x [c]) => y
+(ANDshiftRL y:(SRLconst x [c]) x [c]) => y
+(ANDshiftRA y:(SRAconst x [c]) x [c]) => y
+(ORshiftLL y:(SLLconst x [c]) x [c]) => y
+(ORshiftRL y:(SRLconst x [c]) x [c]) => y
+(ORshiftRA y:(SRAconst x [c]) x [c]) => y
+(XORshiftLL (SLLconst x [c]) x [c]) => (MOVDconst [0])
+(XORshiftRL (SRLconst x [c]) x [c]) => (MOVDconst [0])
+(XORshiftRA (SRAconst x [c]) x [c]) => (MOVDconst [0])
+(BICshiftLL (SLLconst x [c]) x [c]) => (MOVDconst [0])
+(BICshiftRL (SRLconst x [c]) x [c]) => (MOVDconst [0])
+(BICshiftRA (SRAconst x [c]) x [c]) => (MOVDconst [0])
+(EONshiftLL (SLLconst x [c]) x [c]) => (MOVDconst [-1])
+(EONshiftRL (SRLconst x [c]) x [c]) => (MOVDconst [-1])
+(EONshiftRA (SRAconst x [c]) x [c]) => (MOVDconst [-1])
+(ORNshiftLL (SLLconst x [c]) x [c]) => (MOVDconst [-1])
+(ORNshiftRL (SRLconst x [c]) x [c]) => (MOVDconst [-1])
+(ORNshiftRA (SRAconst x [c]) x [c]) => (MOVDconst [-1])
+
+// Generate rotates with const shift
+(ADDshiftLL [c] (SRLconst x [64-c]) x) => (RORconst [64-c] x)
+( ORshiftLL [c] (SRLconst x [64-c]) x) => (RORconst [64-c] x)
+(XORshiftLL [c] (SRLconst x [64-c]) x) => (RORconst [64-c] x)
+(ADDshiftRL [c] (SLLconst x [64-c]) x) => (RORconst [ c] x)
+( ORshiftRL [c] (SLLconst x [64-c]) x) => (RORconst [ c] x)
+(XORshiftRL [c] (SLLconst x [64-c]) x) => (RORconst [ c] x)
+
+(ADDshiftLL <t> [c] (UBFX [bfc] x) x) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ => (RORWconst [32-c] x)
+( ORshiftLL <t> [c] (UBFX [bfc] x) x) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ => (RORWconst [32-c] x)
+(XORshiftLL <t> [c] (UBFX [bfc] x) x) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ => (RORWconst [32-c] x)
+(ADDshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x)) && c < 32 && t.Size() == 4 => (RORWconst [c] x)
+( ORshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x)) && c < 32 && t.Size() == 4 => (RORWconst [c] x)
+(XORshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x)) && c < 32 && t.Size() == 4 => (RORWconst [c] x)
+
+(RORconst [c] (RORconst [d] x)) => (RORconst [(c+d)&63] x)
+(RORWconst [c] (RORWconst [d] x)) => (RORWconst [(c+d)&31] x)
+
+// Generate rotates with non-const shift.
+// These rules match the Go source code like
+// y &= 63
+// x << y | x >> (64-y)
+// "|" can also be "^" or "+".
+// As arm64 does not have a ROL instruction, so ROL(x, y) is replaced by ROR(x, -y).
+((ADD|OR|XOR) (SLL x (ANDconst <t> [63] y))
+ (CSEL0 <typ.UInt64> [cc] (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))
+ (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))))) && cc == OpARM64LessThanU
+ => (ROR x (NEG <t> y))
+((ADD|OR|XOR) (SRL <typ.UInt64> x (ANDconst <t> [63] y))
+ (CSEL0 <typ.UInt64> [cc] (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))
+ (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))))) && cc == OpARM64LessThanU
+ => (ROR x y)
+
+// These rules match the Go source code like
+// y &= 31
+// x << y | x >> (32-y)
+// "|" can also be "^" or "+".
+// As arm64 does not have a ROLW instruction, so ROLW(x, y) is replaced by RORW(x, -y).
+((ADD|OR|XOR) (SLL x (ANDconst <t> [31] y))
+ (CSEL0 <typ.UInt32> [cc] (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))
+ (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))))) && cc == OpARM64LessThanU
+ => (RORW x (NEG <t> y))
+((ADD|OR|XOR) (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y))
+ (CSEL0 <typ.UInt32> [cc] (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))
+ (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))))) && cc == OpARM64LessThanU
+ => (RORW x y)
+
+// ((x>>8) | (x<<8)) => (REV16W x), the type of x is uint16, "|" can also be "^" or "+".
+((ADDshiftLL|ORshiftLL|XORshiftLL) <typ.UInt16> [8] (UBFX <typ.UInt16> [armBFAuxInt(8, 8)] x) x) => (REV16W x)
+
+// Extract from reg pair
+(ADDshiftLL [c] (SRLconst x [64-c]) x2) => (EXTRconst [64-c] x2 x)
+( ORshiftLL [c] (SRLconst x [64-c]) x2) => (EXTRconst [64-c] x2 x)
+(XORshiftLL [c] (SRLconst x [64-c]) x2) => (EXTRconst [64-c] x2 x)
+
+(ADDshiftLL <t> [c] (UBFX [bfc] x) x2) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ => (EXTRWconst [32-c] x2 x)
+( ORshiftLL <t> [c] (UBFX [bfc] x) x2) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ => (EXTRWconst [32-c] x2 x)
+(XORshiftLL <t> [c] (UBFX [bfc] x) x2) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ => (EXTRWconst [32-c] x2 x)
+
+// Rewrite special pairs of shifts to AND.
+// On ARM64 the bitmask can fit into an instruction.
+(SRLconst [c] (SLLconst [c] x)) && 0 < c && c < 64 => (ANDconst [1<<uint(64-c)-1] x) // mask out high bits
+(SLLconst [c] (SRLconst [c] x)) && 0 < c && c < 64 => (ANDconst [^(1<<uint(c)-1)] x) // mask out low bits
+
+// Special case setting bit as 1. An example is math.Copysign(c,-1)
+(ORconst [c1] (ANDconst [c2] x)) && c2|c1 == ^0 => (ORconst [c1] x)
+
+// bitfield ops
+
+// sbfiz
+// (x << lc) >> rc
+(SRAconst [rc] (SLLconst [lc] x)) && lc > rc => (SBFIZ [armBFAuxInt(lc-rc, 64-lc)] x)
+(MOVWreg (SLLconst [lc] x)) && lc < 32 => (SBFIZ [armBFAuxInt(lc, 32-lc)] x)
+(MOVHreg (SLLconst [lc] x)) && lc < 16 => (SBFIZ [armBFAuxInt(lc, 16-lc)] x)
+(MOVBreg (SLLconst [lc] x)) && lc < 8 => (SBFIZ [armBFAuxInt(lc, 8-lc)] x)
+
+// sbfx
+// (x << lc) >> rc
+(SRAconst [rc] (SLLconst [lc] x)) && lc <= rc => (SBFX [armBFAuxInt(rc-lc, 64-rc)] x)
+(SRAconst [rc] (MOVWreg x)) && rc < 32 => (SBFX [armBFAuxInt(rc, 32-rc)] x)
+(SRAconst [rc] (MOVHreg x)) && rc < 16 => (SBFX [armBFAuxInt(rc, 16-rc)] x)
+(SRAconst [rc] (MOVBreg x)) && rc < 8 => (SBFX [armBFAuxInt(rc, 8-rc)] x)
+
+// sbfiz/sbfx combinations: merge shifts into bitfield ops
+(SRAconst [sc] (SBFIZ [bfc] x)) && sc < bfc.getARM64BFlsb()
+ => (SBFIZ [armBFAuxInt(bfc.getARM64BFlsb()-sc, bfc.getARM64BFwidth())] x)
+(SRAconst [sc] (SBFIZ [bfc] x)) && sc >= bfc.getARM64BFlsb()
+ && sc < bfc.getARM64BFlsb()+bfc.getARM64BFwidth()
+ => (SBFX [armBFAuxInt(sc-bfc.getARM64BFlsb(), bfc.getARM64BFlsb()+bfc.getARM64BFwidth()-sc)] x)
+
+// ubfiz
+// (x & ac) << sc
+(SLLconst [sc] (ANDconst [ac] x)) && isARM64BFMask(sc, ac, 0)
+ => (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x)
+(SLLconst [sc] (MOVWUreg x)) && isARM64BFMask(sc, 1<<32-1, 0) => (UBFIZ [armBFAuxInt(sc, 32)] x)
+(SLLconst [sc] (MOVHUreg x)) && isARM64BFMask(sc, 1<<16-1, 0) => (UBFIZ [armBFAuxInt(sc, 16)] x)
+(SLLconst [sc] (MOVBUreg x)) && isARM64BFMask(sc, 1<<8-1, 0) => (UBFIZ [armBFAuxInt(sc, 8)] x)
+// (x << sc) & ac
+(ANDconst [ac] (SLLconst [sc] x)) && isARM64BFMask(sc, ac, sc)
+ => (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x)
+(MOVWUreg (SLLconst [sc] x)) && isARM64BFMask(sc, 1<<32-1, sc)
+ => (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))] x)
+(MOVHUreg (SLLconst [sc] x)) && isARM64BFMask(sc, 1<<16-1, sc)
+ => (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))] x)
+(MOVBUreg (SLLconst [sc] x)) && isARM64BFMask(sc, 1<<8-1, sc)
+ => (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))] x)
+// (x << lc) >> rc
+(SRLconst [rc] (SLLconst [lc] x)) && lc > rc => (UBFIZ [armBFAuxInt(lc-rc, 64-lc)] x)
+
+// ubfx
+// (x >> sc) & ac
+(ANDconst [ac] (SRLconst [sc] x)) && isARM64BFMask(sc, ac, 0)
+ => (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x)
+(MOVWUreg (SRLconst [sc] x)) && isARM64BFMask(sc, 1<<32-1, 0) => (UBFX [armBFAuxInt(sc, 32)] x)
+(MOVHUreg (SRLconst [sc] x)) && isARM64BFMask(sc, 1<<16-1, 0) => (UBFX [armBFAuxInt(sc, 16)] x)
+(MOVBUreg (SRLconst [sc] x)) && isARM64BFMask(sc, 1<<8-1, 0) => (UBFX [armBFAuxInt(sc, 8)] x)
+// (x & ac) >> sc
+(SRLconst [sc] (ANDconst [ac] x)) && isARM64BFMask(sc, ac, sc)
+ => (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x)
+(SRLconst [sc] (MOVWUreg x)) && isARM64BFMask(sc, 1<<32-1, sc)
+ => (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))] x)
+(SRLconst [sc] (MOVHUreg x)) && isARM64BFMask(sc, 1<<16-1, sc)
+ => (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))] x)
+(SRLconst [sc] (MOVBUreg x)) && isARM64BFMask(sc, 1<<8-1, sc)
+ => (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))] x)
+// (x << lc) >> rc
+(SRLconst [rc] (SLLconst [lc] x)) && lc < rc => (UBFX [armBFAuxInt(rc-lc, 64-rc)] x)
+
+// ubfiz/ubfx combinations: merge shifts into bitfield ops
+(SRLconst [sc] (UBFX [bfc] x)) && sc < bfc.getARM64BFwidth()
+ => (UBFX [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()-sc)] x)
+(UBFX [bfc] (SRLconst [sc] x)) && sc+bfc.getARM64BFwidth()+bfc.getARM64BFlsb() < 64
+ => (UBFX [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth())] x)
+(SLLconst [sc] (UBFIZ [bfc] x)) && sc+bfc.getARM64BFwidth()+bfc.getARM64BFlsb() < 64
+ => (UBFIZ [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth())] x)
+(UBFIZ [bfc] (SLLconst [sc] x)) && sc < bfc.getARM64BFwidth()
+ => (UBFIZ [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()-sc)] x)
+// ((x << c1) >> c2) >> c3
+(SRLconst [sc] (UBFIZ [bfc] x)) && sc == bfc.getARM64BFlsb()
+ => (ANDconst [1<<uint(bfc.getARM64BFwidth())-1] x)
+(SRLconst [sc] (UBFIZ [bfc] x)) && sc < bfc.getARM64BFlsb()
+ => (UBFIZ [armBFAuxInt(bfc.getARM64BFlsb()-sc, bfc.getARM64BFwidth())] x)
+(SRLconst [sc] (UBFIZ [bfc] x)) && sc > bfc.getARM64BFlsb()
+ && sc < bfc.getARM64BFlsb()+bfc.getARM64BFwidth()
+ => (UBFX [armBFAuxInt(sc-bfc.getARM64BFlsb(), bfc.getARM64BFlsb()+bfc.getARM64BFwidth()-sc)] x)
+// ((x << c1) << c2) >> c3
+(UBFX [bfc] (SLLconst [sc] x)) && sc == bfc.getARM64BFlsb()
+ => (ANDconst [1<<uint(bfc.getARM64BFwidth())-1] x)
+(UBFX [bfc] (SLLconst [sc] x)) && sc < bfc.getARM64BFlsb()
+ => (UBFX [armBFAuxInt(bfc.getARM64BFlsb()-sc, bfc.getARM64BFwidth())] x)
+(UBFX [bfc] (SLLconst [sc] x)) && sc > bfc.getARM64BFlsb()
+ && sc < bfc.getARM64BFlsb()+bfc.getARM64BFwidth()
+ => (UBFIZ [armBFAuxInt(sc-bfc.getARM64BFlsb(), bfc.getARM64BFlsb()+bfc.getARM64BFwidth()-sc)] x)
+
+// bfi
+(OR (UBFIZ [bfc] x) (ANDconst [ac] y))
+ && ac == ^((1<<uint(bfc.getARM64BFwidth())-1) << uint(bfc.getARM64BFlsb()))
+ => (BFI [bfc] y x)
+(ORshiftRL [rc] (ANDconst [ac] x) (SLLconst [lc] y))
+ && lc > rc && ac == ^((1<<uint(64-lc)-1) << uint64(lc-rc))
+ => (BFI [armBFAuxInt(lc-rc, 64-lc)] x y)
+// bfxil
+(OR (UBFX [bfc] x) (ANDconst [ac] y)) && ac == ^(1<<uint(bfc.getARM64BFwidth())-1)
+ => (BFXIL [bfc] y x)
+(ORshiftLL [sc] (UBFX [bfc] x) (SRLconst [sc] y)) && sc == bfc.getARM64BFwidth()
+ => (BFXIL [bfc] y x)
+(ORshiftRL [rc] (ANDconst [ac] y) (SLLconst [lc] x)) && lc < rc && ac == ^((1<<uint(64-rc)-1))
+ => (BFXIL [armBFAuxInt(rc-lc, 64-rc)] y x)
+
+// do combined loads
+// little endian loads
+// b[0] | b[1]<<8 => load 16-bit
+(ORshiftLL <t> [8]
+ y0:(MOVDnop x0:(MOVBUload [i0] {s} p mem))
+ y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem)))
+ && i1 == i0+1
+ && x0.Uses == 1 && x1.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, y0, y1)
+ => @mergePoint(b,x0,x1) (MOVHUload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem)
+(ORshiftLL <t> [8]
+ y0:(MOVDnop x0:(MOVBUloadidx ptr0 idx0 mem))
+ y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x0, x1, y0, y1)
+ => @mergePoint(b,x0,x1) (MOVHUloadidx <t> ptr0 idx0 mem)
+(ORshiftLL <t> [8]
+ y0:(MOVDnop x0:(MOVBUloadidx ptr idx mem))
+ y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
+ && x0.Uses == 1 && x1.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, y0, y1)
+ => @mergePoint(b,x0,x1) (MOVHUloadidx <t> ptr idx mem)
+
+// b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24 => load 32-bit
+(ORshiftLL <t> [24] o0:(ORshiftLL [16]
+ x0:(MOVHUload [i0] {s} p mem)
+ y1:(MOVDnop x1:(MOVBUload [i2] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [i3] {s} p mem)))
+ && i2 == i0+2
+ && i3 == i0+3
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && y1.Uses == 1 && y2.Uses == 1
+ && o0.Uses == 1
+ && mergePoint(b,x0,x1,x2) != nil
+ && clobber(x0, x1, x2, y1, y2, o0)
+ => @mergePoint(b,x0,x1,x2) (MOVWUload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem)
+(ORshiftLL <t> [24] o0:(ORshiftLL [16]
+ x0:(MOVHUloadidx ptr0 idx0 mem)
+ y1:(MOVDnop x1:(MOVBUload [2] {s} p1:(ADD ptr1 idx1) mem)))
+ y2:(MOVDnop x2:(MOVBUload [3] {s} p mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && y1.Uses == 1 && y2.Uses == 1
+ && o0.Uses == 1
+ && mergePoint(b,x0,x1,x2) != nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, y1, y2, o0)
+ => @mergePoint(b,x0,x1,x2) (MOVWUloadidx <t> ptr0 idx0 mem)
+(ORshiftLL <t> [24] o0:(ORshiftLL [16]
+ x0:(MOVHUloadidx ptr idx mem)
+ y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
+ y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && y1.Uses == 1 && y2.Uses == 1
+ && o0.Uses == 1
+ && mergePoint(b,x0,x1,x2) != nil
+ && clobber(x0, x1, x2, y1, y2, o0)
+ => @mergePoint(b,x0,x1,x2) (MOVWUloadidx <t> ptr idx mem)
+(ORshiftLL <t> [24] o0:(ORshiftLL [16]
+ x0:(MOVHUloadidx2 ptr0 idx0 mem)
+ y1:(MOVDnop x1:(MOVBUload [2] {s} p1:(ADDshiftLL [1] ptr1 idx1) mem)))
+ y2:(MOVDnop x2:(MOVBUload [3] {s} p mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && y1.Uses == 1 && y2.Uses == 1
+ && o0.Uses == 1
+ && mergePoint(b,x0,x1,x2) != nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, y1, y2, o0)
+ => @mergePoint(b,x0,x1,x2) (MOVWUloadidx <t> ptr0 (SLLconst <idx0.Type> [1] idx0) mem)
+
+// b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24 | b[4]<<32 | b[5]<<40 | b[6]<<48 | b[7]<<56 => load 64-bit
+(ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
+ x0:(MOVWUload [i0] {s} p mem)
+ y1:(MOVDnop x1:(MOVBUload [i4] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [i5] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [i6] {s} p mem)))
+ y4:(MOVDnop x4:(MOVBUload [i7] {s} p mem)))
+ && i4 == i0+4
+ && i5 == i0+5
+ && i6 == i0+6
+ && i7 == i0+7
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
+ && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4) != nil
+ && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)
+ => @mergePoint(b,x0,x1,x2,x3,x4) (MOVDload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem)
+(ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
+ x0:(MOVWUloadidx ptr0 idx0 mem)
+ y1:(MOVDnop x1:(MOVBUload [4] {s} p1:(ADD ptr1 idx1) mem)))
+ y2:(MOVDnop x2:(MOVBUload [5] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [6] {s} p mem)))
+ y4:(MOVDnop x4:(MOVBUload [7] {s} p mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
+ && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4) != nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)
+ => @mergePoint(b,x0,x1,x2,x3,x4) (MOVDloadidx <t> ptr0 idx0 mem)
+(ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
+ x0:(MOVWUloadidx4 ptr0 idx0 mem)
+ y1:(MOVDnop x1:(MOVBUload [4] {s} p1:(ADDshiftLL [2] ptr1 idx1) mem)))
+ y2:(MOVDnop x2:(MOVBUload [5] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [6] {s} p mem)))
+ y4:(MOVDnop x4:(MOVBUload [7] {s} p mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
+ && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4) != nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)
+ => @mergePoint(b,x0,x1,x2,x3,x4) (MOVDloadidx <t> ptr0 (SLLconst <idx0.Type> [2] idx0) mem)
+(ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
+ x0:(MOVWUloadidx ptr idx mem)
+ y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [4] idx) mem)))
+ y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [5] idx) mem)))
+ y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [6] idx) mem)))
+ y4:(MOVDnop x4:(MOVBUloadidx ptr (ADDconst [7] idx) mem)))
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
+ && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4) != nil
+ && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)
+ => @mergePoint(b,x0,x1,x2,x3,x4) (MOVDloadidx <t> ptr idx mem)
+
+// b[3]<<24 | b[2]<<16 | b[1]<<8 | b[0] => load 32-bit
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
+ y0:(MOVDnop x0:(MOVBUload [i3] {s} p mem)))
+ y1:(MOVDnop x1:(MOVBUload [i2] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [i1] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [i0] {s} p mem)))
+ && i1 == i0+1
+ && i2 == i0+2
+ && i3 == i0+3
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3) != nil
+ && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ => @mergePoint(b,x0,x1,x2,x3) (MOVWUload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem)
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
+ y0:(MOVDnop x0:(MOVBUload [3] {s} p mem)))
+ y1:(MOVDnop x1:(MOVBUload [2] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
+ y3:(MOVDnop x3:(MOVBUloadidx ptr0 idx0 mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3) != nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ => @mergePoint(b,x0,x1,x2,x3) (MOVWUloadidx <t> ptr0 idx0 mem)
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
+ y0:(MOVDnop x0:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
+ y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
+ y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
+ y3:(MOVDnop x3:(MOVBUloadidx ptr idx mem)))
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3) != nil
+ && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ => @mergePoint(b,x0,x1,x2,x3) (MOVWUloadidx <t> ptr idx mem)
+
+// b[7]<<56 | b[6]<<48 | b[5]<<40 | b[4]<<32 | b[3]<<24 | b[2]<<16 | b[1]<<8 | b[0] => load 64-bit
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
+ y0:(MOVDnop x0:(MOVBUload [i7] {s} p mem)))
+ y1:(MOVDnop x1:(MOVBUload [i6] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [i5] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [i4] {s} p mem)))
+ y4:(MOVDnop x4:(MOVBUload [i3] {s} p mem)))
+ y5:(MOVDnop x5:(MOVBUload [i2] {s} p mem)))
+ y6:(MOVDnop x6:(MOVBUload [i1] {s} p mem)))
+ y7:(MOVDnop x7:(MOVBUload [i0] {s} p mem)))
+ && i1 == i0+1
+ && i2 == i0+2
+ && i3 == i0+3
+ && i4 == i0+4
+ && i5 == i0+5
+ && i6 == i0+6
+ && i7 == i0+7
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
+ && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
+ && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ => @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVDload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem)
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
+ y0:(MOVDnop x0:(MOVBUload [7] {s} p mem)))
+ y1:(MOVDnop x1:(MOVBUload [6] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [5] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [4] {s} p mem)))
+ y4:(MOVDnop x4:(MOVBUload [3] {s} p mem)))
+ y5:(MOVDnop x5:(MOVBUload [2] {s} p mem)))
+ y6:(MOVDnop x6:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
+ y7:(MOVDnop x7:(MOVBUloadidx ptr0 idx0 mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
+ && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ => @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVDloadidx <t> ptr0 idx0 mem)
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
+ y0:(MOVDnop x0:(MOVBUloadidx ptr (ADDconst [7] idx) mem)))
+ y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [6] idx) mem)))
+ y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [5] idx) mem)))
+ y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [4] idx) mem)))
+ y4:(MOVDnop x4:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
+ y5:(MOVDnop x5:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
+ y6:(MOVDnop x6:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
+ y7:(MOVDnop x7:(MOVBUloadidx ptr idx mem)))
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
+ && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
+ && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ => @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVDloadidx <t> ptr idx mem)
+
+// big endian loads
+// b[1] | b[0]<<8 => load 16-bit, reverse
+(ORshiftLL <t> [8]
+ y0:(MOVDnop x0:(MOVBUload [i1] {s} p mem))
+ y1:(MOVDnop x1:(MOVBUload [i0] {s} p mem)))
+ && i1 == i0+1
+ && x0.Uses == 1 && x1.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, y0, y1)
+ => @mergePoint(b,x0,x1) (REV16W <t> (MOVHUload <t> [i0] {s} p mem))
+(ORshiftLL <t> [8]
+ y0:(MOVDnop x0:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem))
+ y1:(MOVDnop x1:(MOVBUloadidx ptr0 idx0 mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x0, x1, y0, y1)
+ => @mergePoint(b,x0,x1) (REV16W <t> (MOVHUloadidx <t> ptr0 idx0 mem))
+(ORshiftLL <t> [8]
+ y0:(MOVDnop x0:(MOVBUloadidx ptr (ADDconst [1] idx) mem))
+ y1:(MOVDnop x1:(MOVBUloadidx ptr idx mem)))
+ && x0.Uses == 1 && x1.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, y0, y1)
+ => @mergePoint(b,x0,x1) (REV16W <t> (MOVHUloadidx <t> ptr idx mem))
+
+// b[3] | b[2]<<8 | b[1]<<16 | b[0]<<24 => load 32-bit, reverse
+(ORshiftLL <t> [24] o0:(ORshiftLL [16]
+ y0:(REV16W x0:(MOVHUload [i2] {s} p mem))
+ y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [i0] {s} p mem)))
+ && i1 == i0+1
+ && i2 == i0+2
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1
+ && o0.Uses == 1
+ && mergePoint(b,x0,x1,x2) != nil
+ && clobber(x0, x1, x2, y0, y1, y2, o0)
+ => @mergePoint(b,x0,x1,x2) (REVW <t> (MOVWUload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem))
+(ORshiftLL <t> [24] o0:(ORshiftLL [16]
+ y0:(REV16W x0:(MOVHUload [2] {s} p mem))
+ y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
+ y2:(MOVDnop x2:(MOVBUloadidx ptr0 idx0 mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1
+ && o0.Uses == 1
+ && mergePoint(b,x0,x1,x2) != nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, y0, y1, y2, o0)
+ => @mergePoint(b,x0,x1,x2) (REVW <t> (MOVWUloadidx <t> ptr0 idx0 mem))
+(ORshiftLL <t> [24] o0:(ORshiftLL [16]
+ y0:(REV16W x0:(MOVHUloadidx ptr (ADDconst [2] idx) mem))
+ y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
+ y2:(MOVDnop x2:(MOVBUloadidx ptr idx mem)))
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1
+ && o0.Uses == 1
+ && mergePoint(b,x0,x1,x2) != nil
+ && clobber(x0, x1, x2, y0, y1, y2, o0)
+ => @mergePoint(b,x0,x1,x2) (REVW <t> (MOVWUloadidx <t> ptr idx mem))
+
+// b[7] | b[6]<<8 | b[5]<<16 | b[4]<<24 | b[3]<<32 | b[2]<<40 | b[1]<<48 | b[0]<<56 => load 64-bit, reverse
+(ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
+ y0:(REVW x0:(MOVWUload [i4] {s} p mem))
+ y1:(MOVDnop x1:(MOVBUload [i3] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [i2] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [i1] {s} p mem)))
+ y4:(MOVDnop x4:(MOVBUload [i0] {s} p mem)))
+ && i1 == i0+1
+ && i2 == i0+2
+ && i3 == i0+3
+ && i4 == i0+4
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4) != nil
+ && clobber(x0, x1, x2, x3, x4, y0, y1, y2, y3, y4, o0, o1, o2)
+ => @mergePoint(b,x0,x1,x2,x3,x4) (REV <t> (MOVDload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem))
+(ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
+ y0:(REVW x0:(MOVWUload [4] {s} p mem))
+ y1:(MOVDnop x1:(MOVBUload [3] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [2] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
+ y4:(MOVDnop x4:(MOVBUloadidx ptr0 idx0 mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4) != nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, x3, x4, y0, y1, y2, y3, y4, o0, o1, o2)
+ => @mergePoint(b,x0,x1,x2,x3,x4) (REV <t> (MOVDloadidx <t> ptr0 idx0 mem))
+(ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
+ y0:(REVW x0:(MOVWUloadidx ptr (ADDconst [4] idx) mem))
+ y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
+ y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
+ y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
+ y4:(MOVDnop x4:(MOVBUloadidx ptr idx mem)))
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4) != nil
+ && clobber(x0, x1, x2, x3, x4, y0, y1, y2, y3, y4, o0, o1, o2)
+ => @mergePoint(b,x0,x1,x2,x3,x4) (REV <t> (MOVDloadidx <t> ptr idx mem))
+
+// b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3] => load 32-bit, reverse
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
+ y0:(MOVDnop x0:(MOVBUload [i0] {s} p mem)))
+ y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [i2] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [i3] {s} p mem)))
+ && i1 == i0+1
+ && i2 == i0+2
+ && i3 == i0+3
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3) != nil
+ && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ => @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem))
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
+ y0:(MOVDnop x0:(MOVBUloadidx ptr0 idx0 mem)))
+ y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
+ y2:(MOVDnop x2:(MOVBUload [2] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [3] {s} p mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3) != nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ => @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUloadidx <t> ptr0 idx0 mem))
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
+ y0:(MOVDnop x0:(MOVBUloadidx ptr idx mem)))
+ y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
+ y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
+ y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3) != nil
+ && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ => @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUloadidx <t> ptr idx mem))
+
+// b[0]<<56 | b[1]<<48 | b[2]<<40 | b[3]<<32 | b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7] => load 64-bit, reverse
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
+ y0:(MOVDnop x0:(MOVBUload [i0] {s} p mem)))
+ y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem)))
+ y2:(MOVDnop x2:(MOVBUload [i2] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [i3] {s} p mem)))
+ y4:(MOVDnop x4:(MOVBUload [i4] {s} p mem)))
+ y5:(MOVDnop x5:(MOVBUload [i5] {s} p mem)))
+ y6:(MOVDnop x6:(MOVBUload [i6] {s} p mem)))
+ y7:(MOVDnop x7:(MOVBUload [i7] {s} p mem)))
+ && i1 == i0+1
+ && i2 == i0+2
+ && i3 == i0+3
+ && i4 == i0+4
+ && i5 == i0+5
+ && i6 == i0+6
+ && i7 == i0+7
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
+ && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
+ && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ => @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem))
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
+ y0:(MOVDnop x0:(MOVBUloadidx ptr0 idx0 mem)))
+ y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
+ y2:(MOVDnop x2:(MOVBUload [2] {s} p mem)))
+ y3:(MOVDnop x3:(MOVBUload [3] {s} p mem)))
+ y4:(MOVDnop x4:(MOVBUload [4] {s} p mem)))
+ y5:(MOVDnop x5:(MOVBUload [5] {s} p mem)))
+ y6:(MOVDnop x6:(MOVBUload [6] {s} p mem)))
+ y7:(MOVDnop x7:(MOVBUload [7] {s} p mem)))
+ && s == nil
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
+ && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ => @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDloadidx <t> ptr0 idx0 mem))
+(OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
+ y0:(MOVDnop x0:(MOVBUloadidx ptr idx mem)))
+ y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
+ y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
+ y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
+ y4:(MOVDnop x4:(MOVBUloadidx ptr (ADDconst [4] idx) mem)))
+ y5:(MOVDnop x5:(MOVBUloadidx ptr (ADDconst [5] idx) mem)))
+ y6:(MOVDnop x6:(MOVBUloadidx ptr (ADDconst [6] idx) mem)))
+ y7:(MOVDnop x7:(MOVBUloadidx ptr (ADDconst [7] idx) mem)))
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
+ && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
+ && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
+ && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
+ && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
+ && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ => @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDloadidx <t> ptr idx mem))
+
+// Combine zero stores into larger (unaligned) stores.
+(MOVBstorezero [i] {s} ptr0 x:(MOVBstorezero [j] {s} ptr1 mem))
+ && x.Uses == 1
+ && areAdjacentOffsets(int64(i),int64(j),1)
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVHstorezero [int32(min(int64(i),int64(j)))] {s} ptr0 mem)
+(MOVBstorezero [1] {s} (ADD ptr0 idx0) x:(MOVBstorezeroidx ptr1 idx1 mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstorezeroidx ptr1 idx1 mem)
+(MOVBstorezeroidx ptr (ADDconst [1] idx) x:(MOVBstorezeroidx ptr idx mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstorezeroidx ptr idx mem)
+(MOVHstorezero [i] {s} ptr0 x:(MOVHstorezero [j] {s} ptr1 mem))
+ && x.Uses == 1
+ && areAdjacentOffsets(int64(i),int64(j),2)
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVWstorezero [int32(min(int64(i),int64(j)))] {s} ptr0 mem)
+(MOVHstorezero [2] {s} (ADD ptr0 idx0) x:(MOVHstorezeroidx ptr1 idx1 mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVWstorezeroidx ptr1 idx1 mem)
+(MOVHstorezeroidx ptr (ADDconst [2] idx) x:(MOVHstorezeroidx ptr idx mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstorezeroidx ptr idx mem)
+(MOVHstorezero [2] {s} (ADDshiftLL [1] ptr0 idx0) x:(MOVHstorezeroidx2 ptr1 idx1 mem))
+ && x.Uses == 1
+ && s == nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && clobber(x)
+ => (MOVWstorezeroidx ptr1 (SLLconst <idx1.Type> [1] idx1) mem)
+(MOVWstorezero [i] {s} ptr0 x:(MOVWstorezero [j] {s} ptr1 mem))
+ && x.Uses == 1
+ && areAdjacentOffsets(int64(i),int64(j),4)
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVDstorezero [int32(min(int64(i),int64(j)))] {s} ptr0 mem)
+(MOVWstorezero [4] {s} (ADD ptr0 idx0) x:(MOVWstorezeroidx ptr1 idx1 mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVDstorezeroidx ptr1 idx1 mem)
+(MOVWstorezeroidx ptr (ADDconst [4] idx) x:(MOVWstorezeroidx ptr idx mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVDstorezeroidx ptr idx mem)
+(MOVWstorezero [4] {s} (ADDshiftLL [2] ptr0 idx0) x:(MOVWstorezeroidx4 ptr1 idx1 mem))
+ && x.Uses == 1
+ && s == nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && clobber(x)
+ => (MOVDstorezeroidx ptr1 (SLLconst <idx1.Type> [2] idx1) mem)
+(MOVDstorezero [i] {s} ptr0 x:(MOVDstorezero [j] {s} ptr1 mem))
+ && x.Uses == 1
+ && areAdjacentOffsets(int64(i),int64(j),8)
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVQstorezero [int32(min(int64(i),int64(j)))] {s} ptr0 mem)
+(MOVDstorezero [8] {s} p0:(ADD ptr0 idx0) x:(MOVDstorezeroidx ptr1 idx1 mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVQstorezero [0] {s} p0 mem)
+(MOVDstorezero [8] {s} p0:(ADDshiftLL [3] ptr0 idx0) x:(MOVDstorezeroidx8 ptr1 idx1 mem))
+ && x.Uses == 1
+ && s == nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && clobber(x)
+ => (MOVQstorezero [0] {s} p0 mem)
+
+// Combine stores into larger (unaligned) stores.
+(MOVBstore [i] {s} ptr0 (SRLconst [8] w) x:(MOVBstore [i-1] {s} ptr1 w mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr0 w mem)
+(MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [8] w) x:(MOVBstoreidx ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstoreidx ptr1 idx1 w mem)
+(MOVBstoreidx ptr (ADDconst [1] idx) (SRLconst [8] w) x:(MOVBstoreidx ptr idx w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstoreidx ptr idx w mem)
+(MOVBstore [i] {s} ptr0 (UBFX [armBFAuxInt(8, 8)] w) x:(MOVBstore [i-1] {s} ptr1 w mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr0 w mem)
+(MOVBstore [1] {s} (ADD ptr0 idx0) (UBFX [armBFAuxInt(8, 8)] w) x:(MOVBstoreidx ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstoreidx ptr1 idx1 w mem)
+(MOVBstore [i] {s} ptr0 (UBFX [armBFAuxInt(8, 24)] w) x:(MOVBstore [i-1] {s} ptr1 w mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr0 w mem)
+(MOVBstore [1] {s} (ADD ptr0 idx0) (UBFX [armBFAuxInt(8, 24)] w) x:(MOVBstoreidx ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstoreidx ptr1 idx1 w mem)
+(MOVBstore [i] {s} ptr0 (SRLconst [8] (MOVDreg w)) x:(MOVBstore [i-1] {s} ptr1 w mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr0 w mem)
+(MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [8] (MOVDreg w)) x:(MOVBstoreidx ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstoreidx ptr1 idx1 w mem)
+(MOVBstore [i] {s} ptr0 (SRLconst [j] w) x:(MOVBstore [i-1] {s} ptr1 w0:(SRLconst [j-8] w) mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr0 w0 mem)
+(MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [j] w) x:(MOVBstoreidx ptr1 idx1 w0:(SRLconst [j-8] w) mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstoreidx ptr1 idx1 w0 mem)
+(MOVBstore [i] {s} ptr0 (UBFX [bfc] w) x:(MOVBstore [i-1] {s} ptr1 w0:(UBFX [bfc2] w) mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && bfc.getARM64BFwidth() == 32 - bfc.getARM64BFlsb()
+ && bfc2.getARM64BFwidth() == 32 - bfc2.getARM64BFlsb()
+ && bfc2.getARM64BFlsb() == bfc.getARM64BFlsb() - 8
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr0 w0 mem)
+(MOVBstore [1] {s} (ADD ptr0 idx0) (UBFX [bfc] w) x:(MOVBstoreidx ptr1 idx1 w0:(UBFX [bfc2] w) mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && bfc.getARM64BFwidth() == 32 - bfc.getARM64BFlsb()
+ && bfc2.getARM64BFwidth() == 32 - bfc2.getARM64BFlsb()
+ && bfc2.getARM64BFlsb() == bfc.getARM64BFlsb() - 8
+ && clobber(x)
+ => (MOVHstoreidx ptr1 idx1 w0 mem)
+(MOVBstore [i] {s} ptr0 (SRLconst [j] (MOVDreg w)) x:(MOVBstore [i-1] {s} ptr1 w0:(SRLconst [j-8] (MOVDreg w)) mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr0 w0 mem)
+(MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [j] (MOVDreg w)) x:(MOVBstoreidx ptr1 idx1 w0:(SRLconst [j-8] (MOVDreg w)) mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstoreidx ptr1 idx1 w0 mem)
+(MOVHstore [i] {s} ptr0 (SRLconst [16] w) x:(MOVHstore [i-2] {s} ptr1 w mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVWstore [i-2] {s} ptr0 w mem)
+(MOVHstore [2] {s} (ADD ptr0 idx0) (SRLconst [16] w) x:(MOVHstoreidx ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVWstoreidx ptr1 idx1 w mem)
+(MOVHstoreidx ptr (ADDconst [2] idx) (SRLconst [16] w) x:(MOVHstoreidx ptr idx w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstoreidx ptr idx w mem)
+(MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (SRLconst [16] w) x:(MOVHstoreidx2 ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && clobber(x)
+ => (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w mem)
+(MOVHstore [i] {s} ptr0 (UBFX [armBFAuxInt(16, 16)] w) x:(MOVHstore [i-2] {s} ptr1 w mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVWstore [i-2] {s} ptr0 w mem)
+(MOVHstore [2] {s} (ADD ptr0 idx0) (UBFX [armBFAuxInt(16, 16)] w) x:(MOVHstoreidx ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVWstoreidx ptr1 idx1 w mem)
+(MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (UBFX [armBFAuxInt(16, 16)] w) x:(MOVHstoreidx2 ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && clobber(x)
+ => (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w mem)
+(MOVHstore [i] {s} ptr0 (SRLconst [16] (MOVDreg w)) x:(MOVHstore [i-2] {s} ptr1 w mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVWstore [i-2] {s} ptr0 w mem)
+(MOVHstore [2] {s} (ADD ptr0 idx0) (SRLconst [16] (MOVDreg w)) x:(MOVHstoreidx ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVWstoreidx ptr1 idx1 w mem)
+(MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (SRLconst [16] (MOVDreg w)) x:(MOVHstoreidx2 ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && clobber(x)
+ => (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w mem)
+(MOVHstore [i] {s} ptr0 (SRLconst [j] w) x:(MOVHstore [i-2] {s} ptr1 w0:(SRLconst [j-16] w) mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVWstore [i-2] {s} ptr0 w0 mem)
+(MOVHstore [2] {s} (ADD ptr0 idx0) (SRLconst [j] w) x:(MOVHstoreidx ptr1 idx1 w0:(SRLconst [j-16] w) mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVWstoreidx ptr1 idx1 w0 mem)
+(MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (SRLconst [j] w) x:(MOVHstoreidx2 ptr1 idx1 w0:(SRLconst [j-16] w) mem))
+ && x.Uses == 1
+ && s == nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && clobber(x)
+ => (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w0 mem)
+(MOVWstore [i] {s} ptr0 (SRLconst [32] w) x:(MOVWstore [i-4] {s} ptr1 w mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVDstore [i-4] {s} ptr0 w mem)
+(MOVWstore [4] {s} (ADD ptr0 idx0) (SRLconst [32] w) x:(MOVWstoreidx ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVDstoreidx ptr1 idx1 w mem)
+(MOVWstoreidx ptr (ADDconst [4] idx) (SRLconst [32] w) x:(MOVWstoreidx ptr idx w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVDstoreidx ptr idx w mem)
+(MOVWstore [4] {s} (ADDshiftLL [2] ptr0 idx0) (SRLconst [32] w) x:(MOVWstoreidx4 ptr1 idx1 w mem))
+ && x.Uses == 1
+ && s == nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && clobber(x)
+ => (MOVDstoreidx ptr1 (SLLconst <idx1.Type> [2] idx1) w mem)
+(MOVWstore [i] {s} ptr0 (SRLconst [j] w) x:(MOVWstore [i-4] {s} ptr1 w0:(SRLconst [j-32] w) mem))
+ && x.Uses == 1
+ && isSamePtr(ptr0, ptr1)
+ && clobber(x)
+ => (MOVDstore [i-4] {s} ptr0 w0 mem)
+(MOVWstore [4] {s} (ADD ptr0 idx0) (SRLconst [j] w) x:(MOVWstoreidx ptr1 idx1 w0:(SRLconst [j-32] w) mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVDstoreidx ptr1 idx1 w0 mem)
+(MOVWstore [4] {s} (ADDshiftLL [2] ptr0 idx0) (SRLconst [j] w) x:(MOVWstoreidx4 ptr1 idx1 w0:(SRLconst [j-32] w) mem))
+ && x.Uses == 1
+ && s == nil
+ && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
+ && clobber(x)
+ => (MOVDstoreidx ptr1 (SLLconst <idx1.Type> [2] idx1) w0 mem)
+(MOVBstore [i] {s} ptr w
+ x0:(MOVBstore [i-1] {s} ptr (SRLconst [8] w)
+ x1:(MOVBstore [i-2] {s} ptr (SRLconst [16] w)
+ x2:(MOVBstore [i-3] {s} ptr (SRLconst [24] w)
+ x3:(MOVBstore [i-4] {s} ptr (SRLconst [32] w)
+ x4:(MOVBstore [i-5] {s} ptr (SRLconst [40] w)
+ x5:(MOVBstore [i-6] {s} ptr (SRLconst [48] w)
+ x6:(MOVBstore [i-7] {s} ptr (SRLconst [56] w) mem))))))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && x3.Uses == 1
+ && x4.Uses == 1
+ && x5.Uses == 1
+ && x6.Uses == 1
+ && clobber(x0, x1, x2, x3, x4, x5, x6)
+ => (MOVDstore [i-7] {s} ptr (REV <w.Type> w) mem)
+(MOVBstore [7] {s} p w
+ x0:(MOVBstore [6] {s} p (SRLconst [8] w)
+ x1:(MOVBstore [5] {s} p (SRLconst [16] w)
+ x2:(MOVBstore [4] {s} p (SRLconst [24] w)
+ x3:(MOVBstore [3] {s} p (SRLconst [32] w)
+ x4:(MOVBstore [2] {s} p (SRLconst [40] w)
+ x5:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (SRLconst [48] w)
+ x6:(MOVBstoreidx ptr0 idx0 (SRLconst [56] w) mem))))))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && x3.Uses == 1
+ && x4.Uses == 1
+ && x5.Uses == 1
+ && x6.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2, x3, x4, x5, x6)
+ => (MOVDstoreidx ptr0 idx0 (REV <w.Type> w) mem)
+(MOVBstore [i] {s} ptr w
+ x0:(MOVBstore [i-1] {s} ptr (UBFX [armBFAuxInt(8, 24)] w)
+ x1:(MOVBstore [i-2] {s} ptr (UBFX [armBFAuxInt(16, 16)] w)
+ x2:(MOVBstore [i-3] {s} ptr (UBFX [armBFAuxInt(24, 8)] w) mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && clobber(x0, x1, x2)
+ => (MOVWstore [i-3] {s} ptr (REVW <w.Type> w) mem)
+(MOVBstore [3] {s} p w
+ x0:(MOVBstore [2] {s} p (UBFX [armBFAuxInt(8, 24)] w)
+ x1:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (UBFX [armBFAuxInt(16, 16)] w)
+ x2:(MOVBstoreidx ptr0 idx0 (UBFX [armBFAuxInt(24, 8)] w) mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2)
+ => (MOVWstoreidx ptr0 idx0 (REVW <w.Type> w) mem)
+(MOVBstoreidx ptr (ADDconst [3] idx) w
+ x0:(MOVBstoreidx ptr (ADDconst [2] idx) (UBFX [armBFAuxInt(8, 24)] w)
+ x1:(MOVBstoreidx ptr (ADDconst [1] idx) (UBFX [armBFAuxInt(16, 16)] w)
+ x2:(MOVBstoreidx ptr idx (UBFX [armBFAuxInt(24, 8)] w) mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && clobber(x0, x1, x2)
+ => (MOVWstoreidx ptr idx (REVW <w.Type> w) mem)
+(MOVBstoreidx ptr idx w
+ x0:(MOVBstoreidx ptr (ADDconst [1] idx) (UBFX [armBFAuxInt(8, 24)] w)
+ x1:(MOVBstoreidx ptr (ADDconst [2] idx) (UBFX [armBFAuxInt(16, 16)] w)
+ x2:(MOVBstoreidx ptr (ADDconst [3] idx) (UBFX [armBFAuxInt(24, 8)] w) mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && clobber(x0, x1, x2)
+ => (MOVWstoreidx ptr idx w mem)
+(MOVBstore [i] {s} ptr w
+ x0:(MOVBstore [i-1] {s} ptr (SRLconst [8] (MOVDreg w))
+ x1:(MOVBstore [i-2] {s} ptr (SRLconst [16] (MOVDreg w))
+ x2:(MOVBstore [i-3] {s} ptr (SRLconst [24] (MOVDreg w)) mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && clobber(x0, x1, x2)
+ => (MOVWstore [i-3] {s} ptr (REVW <w.Type> w) mem)
+(MOVBstore [3] {s} p w
+ x0:(MOVBstore [2] {s} p (SRLconst [8] (MOVDreg w))
+ x1:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (SRLconst [16] (MOVDreg w))
+ x2:(MOVBstoreidx ptr0 idx0 (SRLconst [24] (MOVDreg w)) mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2)
+ => (MOVWstoreidx ptr0 idx0 (REVW <w.Type> w) mem)
+(MOVBstore [i] {s} ptr w
+ x0:(MOVBstore [i-1] {s} ptr (SRLconst [8] w)
+ x1:(MOVBstore [i-2] {s} ptr (SRLconst [16] w)
+ x2:(MOVBstore [i-3] {s} ptr (SRLconst [24] w) mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && clobber(x0, x1, x2)
+ => (MOVWstore [i-3] {s} ptr (REVW <w.Type> w) mem)
+(MOVBstore [3] {s} p w
+ x0:(MOVBstore [2] {s} p (SRLconst [8] w)
+ x1:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (SRLconst [16] w)
+ x2:(MOVBstoreidx ptr0 idx0 (SRLconst [24] w) mem))))
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && x2.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && isSamePtr(p1, p)
+ && clobber(x0, x1, x2)
+ => (MOVWstoreidx ptr0 idx0 (REVW <w.Type> w) mem)
+(MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (SRLconst [8] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
+(MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (SRLconst [8] w) mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
+(MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (UBFX [armBFAuxInt(8, 8)] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
+(MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (UBFX [armBFAuxInt(8, 8)] w) mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
+(MOVBstoreidx ptr (ADDconst [1] idx) w x:(MOVBstoreidx ptr idx (UBFX [armBFAuxInt(8, 8)] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstoreidx ptr idx (REV16W <w.Type> w) mem)
+(MOVBstoreidx ptr idx w x:(MOVBstoreidx ptr (ADDconst [1] idx) (UBFX [armBFAuxInt(8, 8)] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstoreidx ptr idx w mem)
+(MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (SRLconst [8] (MOVDreg w)) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
+(MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (SRLconst [8] (MOVDreg w)) mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
+(MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (UBFX [armBFAuxInt(8, 24)] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
+(MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (UBFX [armBFAuxInt(8, 24)] w) mem))
+ && x.Uses == 1
+ && s == nil
+ && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
+ && clobber(x)
+ => (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
+
+// FP simplification
+(FNEGS (FMULS x y)) => (FNMULS x y)
+(FNEGD (FMULD x y)) => (FNMULD x y)
+(FMULS (FNEGS x) y) => (FNMULS x y)
+(FMULD (FNEGD x) y) => (FNMULD x y)
+(FNEGS (FNMULS x y)) => (FMULS x y)
+(FNEGD (FNMULD x y)) => (FMULD x y)
+(FNMULS (FNEGS x) y) => (FMULS x y)
+(FNMULD (FNEGD x) y) => (FMULD x y)
+(FADDS a (FMULS x y)) => (FMADDS a x y)
+(FADDD a (FMULD x y)) => (FMADDD a x y)
+(FSUBS a (FMULS x y)) => (FMSUBS a x y)
+(FSUBD a (FMULD x y)) => (FMSUBD a x y)
+(FSUBS (FMULS x y) a) => (FNMSUBS a x y)
+(FSUBD (FMULD x y) a) => (FNMSUBD a x y)
+(FADDS a (FNMULS x y)) => (FMSUBS a x y)
+(FADDD a (FNMULD x y)) => (FMSUBD a x y)
+(FSUBS a (FNMULS x y)) => (FMADDS a x y)
+(FSUBD a (FNMULD x y)) => (FMADDD a x y)
+(FSUBS (FNMULS x y) a) => (FNMADDS a x y)
+(FSUBD (FNMULD x y) a) => (FNMADDD a x y)
+
+(MOVBUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVDconst [int64(read8(sym, int64(off)))])
+(MOVHUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVDconst [int64(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+(MOVWUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVDconst [int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+(MOVDload [off] {sym} (SB) _) && symIsRO(sym) => (MOVDconst [int64(read64(sym, int64(off), config.ctxt.Arch.ByteOrder))])
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
new file mode 100644
index 0000000..4d1d14e
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
@@ -0,0 +1,762 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import "strings"
+
+// Notes:
+// - Integer types live in the low portion of registers. Upper portions are junk.
+// - Boolean types use the low-order byte of a register. 0=false, 1=true.
+// Upper bytes are junk.
+// - *const instructions may use a constant larger than the instruction can encode.
+// In this case the assembler expands to multiple instructions and uses tmp
+// register (R27).
+
+// Suffixes encode the bit width of various instructions.
+// D (double word) = 64 bit
+// W (word) = 32 bit
+// H (half word) = 16 bit
+// HU = 16 bit unsigned
+// B (byte) = 8 bit
+// BU = 8 bit unsigned
+// S (single) = 32 bit float
+// D (double) = 64 bit float
+
+// Note: registers not used in regalloc are not included in this list,
+// so that regmask stays within int64
+// Be careful when hand coding regmasks.
+var regNamesARM64 = []string{
+ "R0",
+ "R1",
+ "R2",
+ "R3",
+ "R4",
+ "R5",
+ "R6",
+ "R7",
+ "R8",
+ "R9",
+ "R10",
+ "R11",
+ "R12",
+ "R13",
+ "R14",
+ "R15",
+ "R16",
+ "R17",
+ "R18", // platform register, not used
+ "R19",
+ "R20",
+ "R21",
+ "R22",
+ "R23",
+ "R24",
+ "R25",
+ "R26",
+ // R27 = REGTMP not used in regalloc
+ "g", // aka R28
+ "R29", // frame pointer, not used
+ "R30", // aka REGLINK
+ "SP", // aka R31
+
+ "F0",
+ "F1",
+ "F2",
+ "F3",
+ "F4",
+ "F5",
+ "F6",
+ "F7",
+ "F8",
+ "F9",
+ "F10",
+ "F11",
+ "F12",
+ "F13",
+ "F14",
+ "F15",
+ "F16",
+ "F17",
+ "F18",
+ "F19",
+ "F20",
+ "F21",
+ "F22",
+ "F23",
+ "F24",
+ "F25",
+ "F26",
+ "F27",
+ "F28",
+ "F29",
+ "F30",
+ "F31",
+
+ // If you add registers, update asyncPreempt in runtime.
+
+ // pseudo-registers
+ "SB",
+}
+
+func init() {
+ // Make map from reg names to reg integers.
+ if len(regNamesARM64) > 64 {
+ panic("too many registers")
+ }
+ num := map[string]int{}
+ for i, name := range regNamesARM64 {
+ num[name] = 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 (
+ gp = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30")
+ gpg = gp | buildReg("g")
+ gpsp = gp | buildReg("SP")
+ gpspg = gpg | buildReg("SP")
+ gpspsbg = gpspg | buildReg("SB")
+ fp = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31")
+ callerSave = gp | fp | buildReg("g") // runtime.setg (and anything calling it) may clobber g
+ r0 = buildReg("R0")
+ r1 = buildReg("R1")
+ r2 = buildReg("R2")
+ r3 = buildReg("R3")
+ )
+ // Common regInfo
+ var (
+ gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
+ gp0flags1 = regInfo{inputs: []regMask{0}, outputs: []regMask{gp}}
+ gp11 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
+ gp11sp = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
+ gp1flags = regInfo{inputs: []regMask{gpg}}
+ gp1flags1 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
+ gp11flags = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp, 0}}
+ gp21 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
+ gp21nog = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
+ gp21flags = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp, 0}}
+ gp2flags = regInfo{inputs: []regMask{gpg, gpg}}
+ gp2flags1 = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
+ gp2flags1flags = regInfo{inputs: []regMask{gp, gp, 0}, outputs: []regMask{gp, 0}}
+ gp2load = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
+ gp22 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp, gp}}
+ gp31 = regInfo{inputs: []regMask{gpg, gpg, gpg}, outputs: []regMask{gp}}
+ gpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
+ gpstore = regInfo{inputs: []regMask{gpspsbg, gpg}}
+ gpstore0 = regInfo{inputs: []regMask{gpspsbg}}
+ gpstore2 = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}}
+ gpxchg = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
+ gpcas = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{gp}}
+ fp01 = regInfo{inputs: nil, outputs: []regMask{fp}}
+ fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
+ fpgp = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}
+ gpfp = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}
+ fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
+ fp31 = regInfo{inputs: []regMask{fp, fp, fp}, outputs: []regMask{fp}}
+ fp2flags = regInfo{inputs: []regMask{fp, fp}}
+ fp1flags = regInfo{inputs: []regMask{fp}}
+ fpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{fp}}
+ fp2load = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{fp}}
+ fpstore = regInfo{inputs: []regMask{gpspsbg, fp}}
+ fpstore2 = regInfo{inputs: []regMask{gpspsbg, gpg, fp}}
+ readflags = regInfo{inputs: nil, outputs: []regMask{gp}}
+ )
+ ops := []opData{
+ // binary ops
+ {name: "ADCSflags", argLength: 3, reg: gp2flags1flags, typ: "(UInt64,Flags)", asm: "ADCS", commutative: true}, // arg0+arg1+carry, set flags.
+ {name: "ADCzerocarry", argLength: 1, reg: gp0flags1, typ: "UInt64", asm: "ADC"}, // ZR+ZR+carry
+ {name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1
+ {name: "ADDconst", argLength: 1, reg: gp11sp, asm: "ADD", aux: "Int64"}, // arg0 + auxInt
+ {name: "ADDSconstflags", argLength: 1, reg: gp11flags, typ: "(UInt64,Flags)", asm: "ADDS", aux: "Int64"}, // arg0+auxint, set flags.
+ {name: "ADDSflags", argLength: 2, reg: gp21flags, typ: "(UInt64,Flags)", asm: "ADDS", commutative: true}, // arg0+arg1, set flags.
+ {name: "SUB", argLength: 2, reg: gp21, asm: "SUB"}, // arg0 - arg1
+ {name: "SUBconst", argLength: 1, reg: gp11, asm: "SUB", aux: "Int64"}, // arg0 - auxInt
+ {name: "SBCSflags", argLength: 3, reg: gp2flags1flags, typ: "(UInt64,Flags)", asm: "SBCS"}, // arg0-(arg1+borrowing), set flags.
+ {name: "SUBSflags", argLength: 2, reg: gp21flags, typ: "(UInt64,Flags)", asm: "SUBS"}, // arg0 - arg1, set flags.
+ {name: "MUL", argLength: 2, reg: gp21, asm: "MUL", commutative: true}, // arg0 * arg1
+ {name: "MULW", argLength: 2, reg: gp21, asm: "MULW", commutative: true}, // arg0 * arg1, 32-bit
+ {name: "MNEG", argLength: 2, reg: gp21, asm: "MNEG", commutative: true}, // -arg0 * arg1
+ {name: "MNEGW", argLength: 2, reg: gp21, asm: "MNEGW", commutative: true}, // -arg0 * arg1, 32-bit
+ {name: "MULH", argLength: 2, reg: gp21, asm: "SMULH", commutative: true}, // (arg0 * arg1) >> 64, signed
+ {name: "UMULH", argLength: 2, reg: gp21, asm: "UMULH", commutative: true}, // (arg0 * arg1) >> 64, unsigned
+ {name: "MULL", argLength: 2, reg: gp21, asm: "SMULL", commutative: true}, // arg0 * arg1, signed, 32-bit mult results in 64-bit
+ {name: "UMULL", argLength: 2, reg: gp21, asm: "UMULL", commutative: true}, // arg0 * arg1, unsigned, 32-bit mult results in 64-bit
+ {name: "DIV", argLength: 2, reg: gp21, asm: "SDIV"}, // arg0 / arg1, signed
+ {name: "UDIV", argLength: 2, reg: gp21, asm: "UDIV"}, // arg0 / arg1, unsighed
+ {name: "DIVW", argLength: 2, reg: gp21, asm: "SDIVW"}, // arg0 / arg1, signed, 32 bit
+ {name: "UDIVW", argLength: 2, reg: gp21, asm: "UDIVW"}, // arg0 / arg1, unsighed, 32 bit
+ {name: "MOD", argLength: 2, reg: gp21, asm: "REM"}, // arg0 % arg1, signed
+ {name: "UMOD", argLength: 2, reg: gp21, asm: "UREM"}, // arg0 % arg1, unsigned
+ {name: "MODW", argLength: 2, reg: gp21, asm: "REMW"}, // arg0 % arg1, signed, 32 bit
+ {name: "UMODW", argLength: 2, reg: gp21, asm: "UREMW"}, // arg0 % arg1, unsigned, 32 bit
+
+ {name: "FADDS", argLength: 2, reg: fp21, asm: "FADDS", commutative: true}, // arg0 + arg1
+ {name: "FADDD", argLength: 2, reg: fp21, asm: "FADDD", commutative: true}, // arg0 + arg1
+ {name: "FSUBS", argLength: 2, reg: fp21, asm: "FSUBS"}, // arg0 - arg1
+ {name: "FSUBD", argLength: 2, reg: fp21, asm: "FSUBD"}, // arg0 - arg1
+ {name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true}, // arg0 * arg1
+ {name: "FMULD", argLength: 2, reg: fp21, asm: "FMULD", commutative: true}, // arg0 * arg1
+ {name: "FNMULS", argLength: 2, reg: fp21, asm: "FNMULS", commutative: true}, // -(arg0 * arg1)
+ {name: "FNMULD", argLength: 2, reg: fp21, asm: "FNMULD", commutative: true}, // -(arg0 * arg1)
+ {name: "FDIVS", argLength: 2, reg: fp21, asm: "FDIVS"}, // arg0 / arg1
+ {name: "FDIVD", argLength: 2, reg: fp21, asm: "FDIVD"}, // arg0 / arg1
+
+ {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0 & arg1
+ {name: "ANDconst", argLength: 1, reg: gp11, asm: "AND", aux: "Int64"}, // arg0 & auxInt
+ {name: "OR", argLength: 2, reg: gp21, asm: "ORR", commutative: true}, // arg0 | arg1
+ {name: "ORconst", argLength: 1, reg: gp11, asm: "ORR", aux: "Int64"}, // arg0 | auxInt
+ {name: "XOR", argLength: 2, reg: gp21, asm: "EOR", commutative: true}, // arg0 ^ arg1
+ {name: "XORconst", argLength: 1, reg: gp11, asm: "EOR", aux: "Int64"}, // arg0 ^ auxInt
+ {name: "BIC", argLength: 2, reg: gp21, asm: "BIC"}, // arg0 &^ arg1
+ {name: "EON", argLength: 2, reg: gp21, asm: "EON"}, // arg0 ^ ^arg1
+ {name: "ORN", argLength: 2, reg: gp21, asm: "ORN"}, // arg0 | ^arg1
+
+ {name: "LoweredMuluhilo", argLength: 2, reg: gp22, resultNotInArgs: true}, // arg0 * arg1, returns (hi, lo)
+
+ // unary ops
+ {name: "MVN", argLength: 1, reg: gp11, asm: "MVN"}, // ^arg0
+ {name: "NEG", argLength: 1, reg: gp11, asm: "NEG"}, // -arg0
+ {name: "NEGSflags", argLength: 1, reg: gp11flags, typ: "(UInt64,Flags)", asm: "NEGS"}, // -arg0, set flags.
+ {name: "NGCzerocarry", argLength: 1, reg: gp0flags1, typ: "UInt64", asm: "NGC"}, // -1 if borrowing, 0 otherwise.
+ {name: "FABSD", argLength: 1, reg: fp11, asm: "FABSD"}, // abs(arg0), float64
+ {name: "FNEGS", argLength: 1, reg: fp11, asm: "FNEGS"}, // -arg0, float32
+ {name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD"}, // -arg0, float64
+ {name: "FSQRTD", argLength: 1, reg: fp11, asm: "FSQRTD"}, // sqrt(arg0), float64
+ {name: "REV", argLength: 1, reg: gp11, asm: "REV"}, // byte reverse, 64-bit
+ {name: "REVW", argLength: 1, reg: gp11, asm: "REVW"}, // byte reverse, 32-bit
+ {name: "REV16W", argLength: 1, reg: gp11, asm: "REV16W"}, // byte reverse in each 16-bit halfword, 32-bit
+ {name: "RBIT", argLength: 1, reg: gp11, asm: "RBIT"}, // bit reverse, 64-bit
+ {name: "RBITW", argLength: 1, reg: gp11, asm: "RBITW"}, // bit reverse, 32-bit
+ {name: "CLZ", argLength: 1, reg: gp11, asm: "CLZ"}, // count leading zero, 64-bit
+ {name: "CLZW", argLength: 1, reg: gp11, asm: "CLZW"}, // count leading zero, 32-bit
+ {name: "VCNT", argLength: 1, reg: fp11, asm: "VCNT"}, // count set bits for each 8-bit unit and store the result in each 8-bit unit
+ {name: "VUADDLV", argLength: 1, reg: fp11, asm: "VUADDLV"}, // unsigned sum of eight bytes in a 64-bit value, zero extended to 64-bit.
+ {name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
+ {name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
+
+ // 3-operand, the addend comes first
+ {name: "FMADDS", argLength: 3, reg: fp31, asm: "FMADDS"}, // +arg0 + (arg1 * arg2)
+ {name: "FMADDD", argLength: 3, reg: fp31, asm: "FMADDD"}, // +arg0 + (arg1 * arg2)
+ {name: "FNMADDS", argLength: 3, reg: fp31, asm: "FNMADDS"}, // -arg0 - (arg1 * arg2)
+ {name: "FNMADDD", argLength: 3, reg: fp31, asm: "FNMADDD"}, // -arg0 - (arg1 * arg2)
+ {name: "FMSUBS", argLength: 3, reg: fp31, asm: "FMSUBS"}, // +arg0 - (arg1 * arg2)
+ {name: "FMSUBD", argLength: 3, reg: fp31, asm: "FMSUBD"}, // +arg0 - (arg1 * arg2)
+ {name: "FNMSUBS", argLength: 3, reg: fp31, asm: "FNMSUBS"}, // -arg0 + (arg1 * arg2)
+ {name: "FNMSUBD", argLength: 3, reg: fp31, asm: "FNMSUBD"}, // -arg0 + (arg1 * arg2)
+ {name: "MADD", argLength: 3, reg: gp31, asm: "MADD"}, // +arg0 + (arg1 * arg2)
+ {name: "MADDW", argLength: 3, reg: gp31, asm: "MADDW"}, // +arg0 + (arg1 * arg2), 32-bit
+ {name: "MSUB", argLength: 3, reg: gp31, asm: "MSUB"}, // +arg0 - (arg1 * arg2)
+ {name: "MSUBW", argLength: 3, reg: gp31, asm: "MSUBW"}, // +arg0 - (arg1 * arg2), 32-bit
+
+ // shifts
+ {name: "SLL", argLength: 2, reg: gp21, asm: "LSL"}, // arg0 << arg1, shift amount is mod 64
+ {name: "SLLconst", argLength: 1, reg: gp11, asm: "LSL", aux: "Int64"}, // arg0 << auxInt
+ {name: "SRL", argLength: 2, reg: gp21, asm: "LSR"}, // arg0 >> arg1, unsigned, shift amount is mod 64
+ {name: "SRLconst", argLength: 1, reg: gp11, asm: "LSR", aux: "Int64"}, // arg0 >> auxInt, unsigned
+ {name: "SRA", argLength: 2, reg: gp21, asm: "ASR"}, // arg0 >> arg1, signed, shift amount is mod 64
+ {name: "SRAconst", argLength: 1, reg: gp11, asm: "ASR", aux: "Int64"}, // arg0 >> auxInt, signed
+ {name: "ROR", argLength: 2, reg: gp21, asm: "ROR"}, // arg0 right rotate by (arg1 mod 64) bits
+ {name: "RORW", argLength: 2, reg: gp21, asm: "RORW"}, // arg0 right rotate by (arg1 mod 32) bits
+ {name: "RORconst", argLength: 1, reg: gp11, asm: "ROR", aux: "Int64"}, // arg0 right rotate by auxInt bits
+ {name: "RORWconst", argLength: 1, reg: gp11, asm: "RORW", aux: "Int64"}, // uint32(arg0) right rotate by auxInt bits
+ {name: "EXTRconst", argLength: 2, reg: gp21, asm: "EXTR", aux: "Int64"}, // extract 64 bits from arg0:arg1 starting at lsb auxInt
+ {name: "EXTRWconst", argLength: 2, reg: gp21, asm: "EXTRW", aux: "Int64"}, // extract 32 bits from arg0[31:0]:arg1[31:0] starting at lsb auxInt and zero top 32 bits
+
+ // comparisons
+ {name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to auxInt
+ {name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1, 32 bit
+ {name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt, 32 bit
+ {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1
+ {name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // arg0 compare to -auxInt
+ {name: "CMNW", argLength: 2, reg: gp2flags, asm: "CMNW", typ: "Flags", commutative: true}, // arg0 compare to -arg1, 32 bit
+ {name: "CMNWconst", argLength: 1, reg: gp1flags, asm: "CMNW", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt, 32 bit
+ {name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0
+ {name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int64", typ: "Flags"}, // arg0 & auxInt compare to 0
+ {name: "TSTW", argLength: 2, reg: gp2flags, asm: "TSTW", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0, 32 bit
+ {name: "TSTWconst", argLength: 1, reg: gp1flags, asm: "TSTW", aux: "Int32", typ: "Flags"}, // arg0 & auxInt compare to 0, 32 bit
+ {name: "FCMPS", argLength: 2, reg: fp2flags, asm: "FCMPS", typ: "Flags"}, // arg0 compare to arg1, float32
+ {name: "FCMPD", argLength: 2, reg: fp2flags, asm: "FCMPD", typ: "Flags"}, // arg0 compare to arg1, float64
+ {name: "FCMPS0", argLength: 1, reg: fp1flags, asm: "FCMPS", typ: "Flags"}, // arg0 compare to 0, float32
+ {name: "FCMPD0", argLength: 1, reg: fp1flags, asm: "FCMPD", typ: "Flags"}, // arg0 compare to 0, float64
+
+ // shifted ops
+ {name: "MVNshiftLL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0<<auxInt)
+ {name: "MVNshiftRL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0>>auxInt), unsigned shift
+ {name: "MVNshiftRA", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0>>auxInt), signed shift
+ {name: "NEGshiftLL", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"}, // -(arg0<<auxInt)
+ {name: "NEGshiftRL", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"}, // -(arg0>>auxInt), unsigned shift
+ {name: "NEGshiftRA", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"}, // -(arg0>>auxInt), signed shift
+ {name: "ADDshiftLL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"}, // arg0 + arg1<<auxInt
+ {name: "ADDshiftRL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"}, // arg0 + arg1>>auxInt, unsigned shift
+ {name: "ADDshiftRA", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"}, // arg0 + arg1>>auxInt, signed shift
+ {name: "SUBshiftLL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int64"}, // arg0 - arg1<<auxInt
+ {name: "SUBshiftRL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int64"}, // arg0 - arg1>>auxInt, unsigned shift
+ {name: "SUBshiftRA", argLength: 2, reg: gp21, asm: "SUB", aux: "Int64"}, // arg0 - arg1>>auxInt, signed shift
+ {name: "ANDshiftLL", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"}, // arg0 & (arg1<<auxInt)
+ {name: "ANDshiftRL", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"}, // arg0 & (arg1>>auxInt), unsigned shift
+ {name: "ANDshiftRA", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"}, // arg0 & (arg1>>auxInt), signed shift
+ {name: "ORshiftLL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"}, // arg0 | arg1<<auxInt
+ {name: "ORshiftRL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"}, // arg0 | arg1>>auxInt, unsigned shift
+ {name: "ORshiftRA", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"}, // arg0 | arg1>>auxInt, signed shift
+ {name: "XORshiftLL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"}, // arg0 ^ arg1<<auxInt
+ {name: "XORshiftRL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"}, // arg0 ^ arg1>>auxInt, unsigned shift
+ {name: "XORshiftRA", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"}, // arg0 ^ arg1>>auxInt, signed shift
+ {name: "BICshiftLL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"}, // arg0 &^ (arg1<<auxInt)
+ {name: "BICshiftRL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"}, // arg0 &^ (arg1>>auxInt), unsigned shift
+ {name: "BICshiftRA", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"}, // arg0 &^ (arg1>>auxInt), signed shift
+ {name: "EONshiftLL", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"}, // arg0 ^ ^(arg1<<auxInt)
+ {name: "EONshiftRL", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"}, // arg0 ^ ^(arg1>>auxInt), unsigned shift
+ {name: "EONshiftRA", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"}, // arg0 ^ ^(arg1>>auxInt), signed shift
+ {name: "ORNshiftLL", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"}, // arg0 | ^(arg1<<auxInt)
+ {name: "ORNshiftRL", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"}, // arg0 | ^(arg1>>auxInt), unsigned shift
+ {name: "ORNshiftRA", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"}, // arg0 | ^(arg1>>auxInt), signed shift
+ {name: "CMPshiftLL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to arg1<<auxInt
+ {name: "CMPshiftRL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to arg1>>auxInt, unsigned shift
+ {name: "CMPshiftRA", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to arg1>>auxInt, signed shift
+ {name: "CMNshiftLL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // (arg0 + arg1<<auxInt) compare to 0
+ {name: "CMNshiftRL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // (arg0 + arg1>>auxInt) compare to 0, unsigned shift
+ {name: "CMNshiftRA", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // (arg0 + arg1>>auxInt) compare to 0, signed shift
+ {name: "TSTshiftLL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1<<auxInt) compare to 0
+ {name: "TSTshiftRL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1>>auxInt) compare to 0, unsigned shift
+ {name: "TSTshiftRA", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1>>auxInt) compare to 0, signed shift
+
+ // bitfield ops
+ // for all bitfield ops lsb is auxInt>>8, width is auxInt&0xff
+ // insert low width bits of arg1 into the result starting at bit lsb, copy other bits from arg0
+ {name: "BFI", argLength: 2, reg: gp21nog, asm: "BFI", aux: "ARM64BitField", resultInArg0: true},
+ // extract width bits of arg1 starting at bit lsb and insert at low end of result, copy other bits from arg0
+ {name: "BFXIL", argLength: 2, reg: gp21nog, asm: "BFXIL", aux: "ARM64BitField", resultInArg0: true},
+ // insert low width bits of arg0 into the result starting at bit lsb, bits to the left of the inserted bit field are set to the high/sign bit of the inserted bit field, bits to the right are zeroed
+ {name: "SBFIZ", argLength: 1, reg: gp11, asm: "SBFIZ", aux: "ARM64BitField"},
+ // extract width bits of arg0 starting at bit lsb and insert at low end of result, remaining high bits are set to the high/sign bit of the extracted bitfield
+ {name: "SBFX", argLength: 1, reg: gp11, asm: "SBFX", aux: "ARM64BitField"},
+ // insert low width bits of arg0 into the result starting at bit lsb, bits to the left and right of the inserted bit field are zeroed
+ {name: "UBFIZ", argLength: 1, reg: gp11, asm: "UBFIZ", aux: "ARM64BitField"},
+ // extract width bits of arg0 starting at bit lsb and insert at low end of result, remaining high bits are zeroed
+ {name: "UBFX", argLength: 1, reg: gp11, asm: "UBFX", aux: "ARM64BitField"},
+
+ // moves
+ {name: "MOVDconst", argLength: 0, reg: gp01, aux: "Int64", asm: "MOVD", typ: "UInt64", rematerializeable: true}, // 64 bits from auxint
+ {name: "FMOVSconst", argLength: 0, reg: fp01, aux: "Float64", asm: "FMOVS", typ: "Float32", rematerializeable: true}, // auxint as 64-bit float, convert to 32-bit float
+ {name: "FMOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "FMOVD", typ: "Float64", rematerializeable: true}, // auxint as 64-bit float
+
+ {name: "MOVDaddr", argLength: 1, reg: regInfo{inputs: []regMask{buildReg("SP") | buildReg("SB")}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVD", rematerializeable: true, symEffect: "Addr"}, // arg0 + auxInt + aux.(*gc.Sym), arg0=SP/SB
+
+ {name: "MOVBload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVB", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVBUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVBU", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVH", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVHU", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVWload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVW", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVWUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVWU", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVDload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVD", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "FMOVSload", argLength: 2, reg: fpload, aux: "SymOff", asm: "FMOVS", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "FMOVDload", argLength: 2, reg: fpload, aux: "SymOff", asm: "FMOVD", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+
+ // register indexed load
+ {name: "MOVDloadidx", argLength: 3, reg: gp2load, asm: "MOVD", typ: "UInt64"}, // load 64-bit dword from arg0 + arg1, arg2 = mem.
+ {name: "MOVWloadidx", argLength: 3, reg: gp2load, asm: "MOVW", typ: "Int32"}, // load 32-bit word from arg0 + arg1, sign-extended to 64-bit, arg2=mem.
+ {name: "MOVWUloadidx", argLength: 3, reg: gp2load, asm: "MOVWU", typ: "UInt32"}, // load 32-bit word from arg0 + arg1, zero-extended to 64-bit, arg2=mem.
+ {name: "MOVHloadidx", argLength: 3, reg: gp2load, asm: "MOVH", typ: "Int16"}, // load 16-bit word from arg0 + arg1, sign-extended to 64-bit, arg2=mem.
+ {name: "MOVHUloadidx", argLength: 3, reg: gp2load, asm: "MOVHU", typ: "UInt16"}, // load 16-bit word from arg0 + arg1, zero-extended to 64-bit, arg2=mem.
+ {name: "MOVBloadidx", argLength: 3, reg: gp2load, asm: "MOVB", typ: "Int8"}, // load 8-bit word from arg0 + arg1, sign-extended to 64-bit, arg2=mem.
+ {name: "MOVBUloadidx", argLength: 3, reg: gp2load, asm: "MOVBU", typ: "UInt8"}, // load 8-bit word from arg0 + arg1, zero-extended to 64-bit, arg2=mem.
+ {name: "FMOVSloadidx", argLength: 3, reg: fp2load, asm: "FMOVS", typ: "Float32"}, // load 32-bit float from arg0 + arg1, arg2=mem.
+ {name: "FMOVDloadidx", argLength: 3, reg: fp2load, asm: "FMOVD", typ: "Float64"}, // load 64-bit float from arg0 + arg1, arg2=mem.
+
+ // shifted register indexed load
+ {name: "MOVHloadidx2", argLength: 3, reg: gp2load, asm: "MOVH", typ: "Int16"}, // load 16-bit half-word from arg0 + arg1*2, sign-extended to 64-bit, arg2=mem.
+ {name: "MOVHUloadidx2", argLength: 3, reg: gp2load, asm: "MOVHU", typ: "UInt16"}, // load 16-bit half-word from arg0 + arg1*2, zero-extended to 64-bit, arg2=mem.
+ {name: "MOVWloadidx4", argLength: 3, reg: gp2load, asm: "MOVW", typ: "Int32"}, // load 32-bit word from arg0 + arg1*4, sign-extended to 64-bit, arg2=mem.
+ {name: "MOVWUloadidx4", argLength: 3, reg: gp2load, asm: "MOVWU", typ: "UInt32"}, // load 32-bit word from arg0 + arg1*4, zero-extended to 64-bit, arg2=mem.
+ {name: "MOVDloadidx8", argLength: 3, reg: gp2load, asm: "MOVD", typ: "UInt64"}, // load 64-bit double-word from arg0 + arg1*8, arg2 = mem.
+
+ {name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 1 byte of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVDstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "STP", argLength: 4, reg: gpstore2, aux: "SymOff", asm: "STP", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 16 bytes of arg1 and arg2 to arg0 + auxInt + aux. arg3=mem.
+ {name: "FMOVSstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "FMOVS", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "FMOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "FMOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+
+ // register indexed store
+ {name: "MOVBstoreidx", argLength: 4, reg: gpstore2, asm: "MOVB", typ: "Mem"}, // store 1 byte of arg2 to arg0 + arg1, arg3 = mem.
+ {name: "MOVHstoreidx", argLength: 4, reg: gpstore2, asm: "MOVH", typ: "Mem"}, // store 2 bytes of arg2 to arg0 + arg1, arg3 = mem.
+ {name: "MOVWstoreidx", argLength: 4, reg: gpstore2, asm: "MOVW", typ: "Mem"}, // store 4 bytes of arg2 to arg0 + arg1, arg3 = mem.
+ {name: "MOVDstoreidx", argLength: 4, reg: gpstore2, asm: "MOVD", typ: "Mem"}, // store 8 bytes of arg2 to arg0 + arg1, arg3 = mem.
+ {name: "FMOVSstoreidx", argLength: 4, reg: fpstore2, asm: "FMOVS", typ: "Mem"}, // store 32-bit float of arg2 to arg0 + arg1, arg3=mem.
+ {name: "FMOVDstoreidx", argLength: 4, reg: fpstore2, asm: "FMOVD", typ: "Mem"}, // store 64-bit float of arg2 to arg0 + arg1, arg3=mem.
+
+ // shifted register indexed store
+ {name: "MOVHstoreidx2", argLength: 4, reg: gpstore2, asm: "MOVH", typ: "Mem"}, // store 2 bytes of arg2 to arg0 + arg1*2, arg3 = mem.
+ {name: "MOVWstoreidx4", argLength: 4, reg: gpstore2, asm: "MOVW", typ: "Mem"}, // store 4 bytes of arg2 to arg0 + arg1*4, arg3 = mem.
+ {name: "MOVDstoreidx8", argLength: 4, reg: gpstore2, asm: "MOVD", typ: "Mem"}, // store 8 bytes of arg2 to arg0 + arg1*8, arg3 = mem.
+
+ {name: "MOVBstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 1 byte of zero to arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes of zero to arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVWstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of zero to arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVDstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of zero to arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVQstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "STP", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 16 bytes of zero to arg0 + auxInt + aux. arg1=mem.
+
+ // register indexed store zero
+ {name: "MOVBstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVB", typ: "Mem"}, // store 1 byte of zero to arg0 + arg1, arg2 = mem.
+ {name: "MOVHstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVH", typ: "Mem"}, // store 2 bytes of zero to arg0 + arg1, arg2 = mem.
+ {name: "MOVWstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVW", typ: "Mem"}, // store 4 bytes of zero to arg0 + arg1, arg2 = mem.
+ {name: "MOVDstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVD", typ: "Mem"}, // store 8 bytes of zero to arg0 + arg1, arg2 = mem.
+
+ // shifted register indexed store zero
+ {name: "MOVHstorezeroidx2", argLength: 3, reg: gpstore, asm: "MOVH", typ: "Mem"}, // store 2 bytes of zero to arg0 + arg1*2, arg2 = mem.
+ {name: "MOVWstorezeroidx4", argLength: 3, reg: gpstore, asm: "MOVW", typ: "Mem"}, // store 4 bytes of zero to arg0 + arg1*4, arg2 = mem.
+ {name: "MOVDstorezeroidx8", argLength: 3, reg: gpstore, asm: "MOVD", typ: "Mem"}, // store 8 bytes of zero to arg0 + arg1*8, arg2 = mem.
+
+ {name: "FMOVDgpfp", argLength: 1, reg: gpfp, asm: "FMOVD"}, // move int64 to float64 (no conversion)
+ {name: "FMOVDfpgp", argLength: 1, reg: fpgp, asm: "FMOVD"}, // move float64 to int64 (no conversion)
+ {name: "FMOVSgpfp", argLength: 1, reg: gpfp, asm: "FMOVS"}, // move 32bits from int to float reg (no conversion)
+ {name: "FMOVSfpgp", argLength: 1, reg: fpgp, asm: "FMOVS"}, // move 32bits from float to int reg, zero extend (no conversion)
+
+ // conversions
+ {name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB"}, // move from arg0, sign-extended from byte
+ {name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // move from arg0, unsign-extended from byte
+ {name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVH"}, // move from arg0, sign-extended from half
+ {name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // move from arg0, unsign-extended from half
+ {name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"}, // move from arg0, sign-extended from word
+ {name: "MOVWUreg", argLength: 1, reg: gp11, asm: "MOVWU"}, // move from arg0, unsign-extended from word
+ {name: "MOVDreg", argLength: 1, reg: gp11, asm: "MOVD"}, // move from arg0
+
+ {name: "MOVDnop", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // nop, return arg0 in same register
+
+ {name: "SCVTFWS", argLength: 1, reg: gpfp, asm: "SCVTFWS"}, // int32 -> float32
+ {name: "SCVTFWD", argLength: 1, reg: gpfp, asm: "SCVTFWD"}, // int32 -> float64
+ {name: "UCVTFWS", argLength: 1, reg: gpfp, asm: "UCVTFWS"}, // uint32 -> float32
+ {name: "UCVTFWD", argLength: 1, reg: gpfp, asm: "UCVTFWD"}, // uint32 -> float64
+ {name: "SCVTFS", argLength: 1, reg: gpfp, asm: "SCVTFS"}, // int64 -> float32
+ {name: "SCVTFD", argLength: 1, reg: gpfp, asm: "SCVTFD"}, // int64 -> float64
+ {name: "UCVTFS", argLength: 1, reg: gpfp, asm: "UCVTFS"}, // uint64 -> float32
+ {name: "UCVTFD", argLength: 1, reg: gpfp, asm: "UCVTFD"}, // uint64 -> float64
+ {name: "FCVTZSSW", argLength: 1, reg: fpgp, asm: "FCVTZSSW"}, // float32 -> int32
+ {name: "FCVTZSDW", argLength: 1, reg: fpgp, asm: "FCVTZSDW"}, // float64 -> int32
+ {name: "FCVTZUSW", argLength: 1, reg: fpgp, asm: "FCVTZUSW"}, // float32 -> uint32
+ {name: "FCVTZUDW", argLength: 1, reg: fpgp, asm: "FCVTZUDW"}, // float64 -> uint32
+ {name: "FCVTZSS", argLength: 1, reg: fpgp, asm: "FCVTZSS"}, // float32 -> int64
+ {name: "FCVTZSD", argLength: 1, reg: fpgp, asm: "FCVTZSD"}, // float64 -> int64
+ {name: "FCVTZUS", argLength: 1, reg: fpgp, asm: "FCVTZUS"}, // float32 -> uint64
+ {name: "FCVTZUD", argLength: 1, reg: fpgp, asm: "FCVTZUD"}, // float64 -> uint64
+ {name: "FCVTSD", argLength: 1, reg: fp11, asm: "FCVTSD"}, // float32 -> float64
+ {name: "FCVTDS", argLength: 1, reg: fp11, asm: "FCVTDS"}, // float64 -> float32
+
+ // floating-point round to integral
+ {name: "FRINTAD", argLength: 1, reg: fp11, asm: "FRINTAD"},
+ {name: "FRINTMD", argLength: 1, reg: fp11, asm: "FRINTMD"},
+ {name: "FRINTND", argLength: 1, reg: fp11, asm: "FRINTND"},
+ {name: "FRINTPD", argLength: 1, reg: fp11, asm: "FRINTPD"},
+ {name: "FRINTZD", argLength: 1, reg: fp11, asm: "FRINTZD"},
+
+ // conditional instructions; auxint is
+ // one of the arm64 comparison pseudo-ops (LessThan, LessThanU, etc.)
+ {name: "CSEL", argLength: 3, reg: gp2flags1, asm: "CSEL", aux: "CCop"}, // auxint(flags) ? arg0 : arg1
+ {name: "CSEL0", argLength: 2, reg: gp1flags1, asm: "CSEL", aux: "CCop"}, // auxint(flags) ? arg0 : 0
+
+ // function calls
+ {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
+ {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
+ {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
+
+ // pseudo-ops
+ {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem.
+
+ {name: "Equal", argLength: 1, reg: readflags}, // bool, true flags encode x==y false otherwise.
+ {name: "NotEqual", argLength: 1, reg: readflags}, // bool, true flags encode x!=y false otherwise.
+ {name: "LessThan", argLength: 1, reg: readflags}, // bool, true flags encode signed x<y false otherwise.
+ {name: "LessEqual", argLength: 1, reg: readflags}, // bool, true flags encode signed x<=y false otherwise.
+ {name: "GreaterThan", argLength: 1, reg: readflags}, // bool, true flags encode signed x>y false otherwise.
+ {name: "GreaterEqual", argLength: 1, reg: readflags}, // bool, true flags encode signed x>=y false otherwise.
+ {name: "LessThanU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x<y false otherwise.
+ {name: "LessEqualU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x<=y false otherwise.
+ {name: "GreaterThanU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x>y false otherwise.
+ {name: "GreaterEqualU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x>=y false otherwise.
+ {name: "LessThanF", argLength: 1, reg: readflags}, // bool, true flags encode floating-point x<y false otherwise.
+ {name: "LessEqualF", argLength: 1, reg: readflags}, // bool, true flags encode floating-point x<=y false otherwise.
+ {name: "GreaterThanF", argLength: 1, reg: readflags}, // bool, true flags encode floating-point x>y false otherwise.
+ {name: "GreaterEqualF", argLength: 1, reg: readflags}, // bool, true flags encode floating-point x>=y false otherwise.
+ {name: "NotLessThanF", argLength: 1, reg: readflags}, // bool, true flags encode floating-point x>=y || x is unordered with y, false otherwise.
+ {name: "NotLessEqualF", argLength: 1, reg: readflags}, // bool, true flags encode floating-point x>y || x is unordered with y, false otherwise.
+ {name: "NotGreaterThanF", argLength: 1, reg: readflags}, // bool, true flags encode floating-point x<=y || x is unordered with y, false otherwise.
+ {name: "NotGreaterEqualF", argLength: 1, reg: readflags}, // bool, true flags encode floating-point x<y || x is unordered with y, false otherwise.
+ // duffzero
+ // arg0 = address of memory to zero
+ // arg1 = mem
+ // auxint = offset into duffzero code to start executing
+ // returns mem
+ // R20 changed as side effect
+ // R16 and R17 may be clobbered by linker trampoline.
+ {
+ name: "DUFFZERO",
+ aux: "Int64",
+ argLength: 2,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R20")},
+ clobbers: buildReg("R16 R17 R20 R30"),
+ },
+ faultOnNilArg0: true,
+ unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts
+ },
+
+ // large zeroing
+ // arg0 = address of memory to zero (in R16 aka arm64.REGRT1, changed as side effect)
+ // arg1 = address of the last 16-byte unit to zero
+ // arg2 = mem
+ // returns mem
+ // STP.P (ZR,ZR), 16(R16)
+ // CMP Rarg1, R16
+ // BLE -2(PC)
+ // Note: the-end-of-the-memory may be not a valid pointer. it's a problem if it is spilled.
+ // the-end-of-the-memory - 16 is with the area to zero, ok to spill.
+ {
+ name: "LoweredZero",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R16"), gp},
+ clobbers: buildReg("R16"),
+ },
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ },
+
+ // duffcopy
+ // arg0 = address of dst memory (in R21, changed as side effect)
+ // arg1 = address of src memory (in R20, changed as side effect)
+ // arg2 = mem
+ // auxint = offset into duffcopy code to start executing
+ // returns mem
+ // R20, R21 changed as side effect
+ // R16 and R17 may be clobbered by linker trampoline.
+ {
+ name: "DUFFCOPY",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R21"), buildReg("R20")},
+ clobbers: buildReg("R16 R17 R20 R21 R26 R30"),
+ },
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
+ },
+
+ // large move
+ // arg0 = address of dst memory (in R17 aka arm64.REGRT2, changed as side effect)
+ // arg1 = address of src memory (in R16 aka arm64.REGRT1, changed as side effect)
+ // arg2 = address of the last element of src
+ // arg3 = mem
+ // returns mem
+ // MOVD.P 8(R16), Rtmp
+ // MOVD.P Rtmp, 8(R17)
+ // CMP Rarg2, R16
+ // BLE -3(PC)
+ // Note: the-end-of-src may be not a valid pointer. it's a problem if it is spilled.
+ // the-end-of-src - 8 is within the area to copy, ok to spill.
+ {
+ name: "LoweredMove",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R17"), buildReg("R16"), gp},
+ clobbers: buildReg("R16 R17"),
+ },
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // Scheduler ensures LoweredGetClosurePtr occurs only in entry block,
+ // and sorts it to the very beginning of the block to prevent other
+ // use of R26 (arm64.REGCTXT, the closure pointer)
+ {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R26")}}, zeroWidth: true},
+
+ // LoweredGetCallerSP returns the SP of the caller of the current function.
+ {name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
+
+ // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+ // I.e., if f calls g "calls" getcallerpc,
+ // the result should be the PC within f that g will return to.
+ // See runtime/stubs.go for a more detailed discussion.
+ {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
+
+ // Constant flag value.
+ // Note: there's an "unordered" outcome for floating-point
+ // comparisons, but we don't use such a beast yet.
+ // This op is for temporary use by rewrite rules. It
+ // cannot appear in the generated assembly.
+ {name: "FlagConstant", aux: "FlagConstant"},
+
+ // (InvertFlags (CMP a b)) == (CMP b a)
+ // InvertFlags is a pseudo-op which can't appear in assembly output.
+ {name: "InvertFlags", argLength: 1}, // reverse direction of arg0
+
+ // atomic loads.
+ // load from arg0. arg1=mem. auxint must be zero.
+ // returns <value,memory> so they can be properly ordered with other loads.
+ {name: "LDAR", argLength: 2, reg: gpload, asm: "LDAR", faultOnNilArg0: true},
+ {name: "LDARB", argLength: 2, reg: gpload, asm: "LDARB", faultOnNilArg0: true},
+ {name: "LDARW", argLength: 2, reg: gpload, asm: "LDARW", faultOnNilArg0: true},
+
+ // atomic stores.
+ // store arg1 to arg0. arg2=mem. returns memory. auxint must be zero.
+ {name: "STLRB", argLength: 3, reg: gpstore, asm: "STLRB", faultOnNilArg0: true, hasSideEffects: true},
+ {name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true, hasSideEffects: true},
+ {name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic exchange.
+ // store arg1 to arg0. arg2=mem. returns <old content of *arg0, memory>. auxint must be zero.
+ // LDAXR (Rarg0), Rout
+ // STLXR Rarg1, (Rarg0), Rtmp
+ // CBNZ Rtmp, -2(PC)
+ {name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // atomic exchange variant.
+ // store arg1 to arg0. arg2=mem. returns <old content of *arg0, memory>. auxint must be zero.
+ // SWPALD Rarg1, (Rarg0), Rout
+ {name: "LoweredAtomicExchange64Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicExchange32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic add.
+ // *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>. auxint must be zero.
+ // LDAXR (Rarg0), Rout
+ // ADD Rarg1, Rout
+ // STLXR Rout, (Rarg0), Rtmp
+ // CBNZ Rtmp, -3(PC)
+ {name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // atomic add variant.
+ // *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>. auxint must be zero.
+ // LDADDAL (Rarg0), Rarg1, Rout
+ // ADD Rarg1, Rout
+ {name: "LoweredAtomicAdd64Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicAdd32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic compare and swap.
+ // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory. auxint must be zero.
+ // if *arg0 == arg1 {
+ // *arg0 = arg2
+ // return (true, memory)
+ // } else {
+ // return (false, memory)
+ // }
+ // LDAXR (Rarg0), Rtmp
+ // CMP Rarg1, Rtmp
+ // BNE 3(PC)
+ // STLXR Rarg2, (Rarg0), Rtmp
+ // CBNZ Rtmp, -4(PC)
+ // CSET EQ, Rout
+ {name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // atomic compare and swap variant.
+ // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory. auxint must be zero.
+ // if *arg0 == arg1 {
+ // *arg0 = arg2
+ // return (true, memory)
+ // } else {
+ // return (false, memory)
+ // }
+ // MOV Rarg1, Rtmp
+ // CASAL Rtmp, (Rarg0), Rarg2
+ // CMP Rarg1, Rtmp
+ // CSET EQ, Rout
+ {name: "LoweredAtomicCas64Variant", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicCas32Variant", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // atomic and/or.
+ // *arg0 &= (|=) arg1. arg2=mem. returns <new content of *arg0, memory>. auxint must be zero.
+ // LDAXR (Rarg0), Rout
+ // AND/OR Rarg1, Rout
+ // STLXR Rout, (Rarg0), Rtmp
+ // CBNZ Rtmp, -3(PC)
+ {name: "LoweredAtomicAnd8", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AND", typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicAnd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AND", typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicOr8", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "ORR", typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicOr32", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "ORR", typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // atomic and/or variant.
+ // *arg0 &= (|=) arg1. arg2=mem. returns <new content of *arg0, memory>. auxint must be zero.
+ // AND:
+ // MNV Rarg1, Rtemp
+ // LDANDALB Rtemp, (Rarg0), Rout
+ // AND Rarg1, Rout
+ // OR:
+ // LDORALB Rarg1, (Rarg0), Rout
+ // ORR Rarg1, Rout
+ {name: "LoweredAtomicAnd8Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicAnd32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicOr8Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicOr32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true},
+
+ // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+ // It saves all GP registers if necessary,
+ // but clobbers R30 (LR) because it's a call.
+ // R16 and R17 may be clobbered by linker trampoline.
+ {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R16 R17 R30")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
+
+ // There are three of these functions so that they can have three different register inputs.
+ // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
+ // default registers to match so we don't need to copy registers around unnecessarily.
+ {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
+ {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
+ {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r0, r1}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
+ }
+
+ blocks := []blockData{
+ {name: "EQ", controls: 1},
+ {name: "NE", controls: 1},
+ {name: "LT", controls: 1},
+ {name: "LE", controls: 1},
+ {name: "GT", controls: 1},
+ {name: "GE", controls: 1},
+ {name: "ULT", controls: 1},
+ {name: "ULE", controls: 1},
+ {name: "UGT", controls: 1},
+ {name: "UGE", controls: 1},
+ {name: "Z", controls: 1}, // Control == 0 (take a register instead of flags)
+ {name: "NZ", controls: 1}, // Control != 0
+ {name: "ZW", controls: 1}, // Control == 0, 32-bit
+ {name: "NZW", controls: 1}, // Control != 0, 32-bit
+ {name: "TBZ", controls: 1, aux: "Int64"}, // Control & (1 << AuxInt) == 0
+ {name: "TBNZ", controls: 1, aux: "Int64"}, // Control & (1 << AuxInt) != 0
+ {name: "FLT", controls: 1},
+ {name: "FLE", controls: 1},
+ {name: "FGT", controls: 1},
+ {name: "FGE", controls: 1},
+ {name: "LTnoov", controls: 1}, // 'LT' but without honoring overflow
+ {name: "LEnoov", controls: 1}, // 'LE' but without honoring overflow
+ {name: "GTnoov", controls: 1}, // 'GT' but without honoring overflow
+ {name: "GEnoov", controls: 1}, // 'GE' but without honoring overflow
+ }
+
+ archs = append(archs, arch{
+ name: "ARM64",
+ pkg: "cmd/internal/obj/arm64",
+ genfile: "../../arm64/ssa.go",
+ ops: ops,
+ blocks: blocks,
+ regnames: regNamesARM64,
+ gpregmask: gp,
+ fpregmask: fp,
+ framepointerreg: -1, // not used
+ linkreg: int8(num["R30"]),
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go
new file mode 100644
index 0000000..1a7eefa
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/ARMOps.go
@@ -0,0 +1,600 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import "strings"
+
+// Notes:
+// - Integer types live in the low portion of registers. Upper portions are junk.
+// - Boolean types use the low-order byte of a register. 0=false, 1=true.
+// Upper bytes are junk.
+// - *const instructions may use a constant larger than the instruction can encode.
+// In this case the assembler expands to multiple instructions and uses tmp
+// register (R11).
+
+// Suffixes encode the bit width of various instructions.
+// W (word) = 32 bit
+// H (half word) = 16 bit
+// HU = 16 bit unsigned
+// B (byte) = 8 bit
+// BU = 8 bit unsigned
+// F (float) = 32 bit float
+// D (double) = 64 bit float
+
+var regNamesARM = []string{
+ "R0",
+ "R1",
+ "R2",
+ "R3",
+ "R4",
+ "R5",
+ "R6",
+ "R7",
+ "R8",
+ "R9",
+ "g", // aka R10
+ "R11", // tmp
+ "R12",
+ "SP", // aka R13
+ "R14", // link
+ "R15", // pc
+
+ "F0",
+ "F1",
+ "F2",
+ "F3",
+ "F4",
+ "F5",
+ "F6",
+ "F7",
+ "F8",
+ "F9",
+ "F10",
+ "F11",
+ "F12",
+ "F13",
+ "F14",
+ "F15", // tmp
+
+ // If you add registers, update asyncPreempt in runtime.
+
+ // pseudo-registers
+ "SB",
+}
+
+func init() {
+ // Make map from reg names to reg integers.
+ if len(regNamesARM) > 64 {
+ panic("too many registers")
+ }
+ num := map[string]int{}
+ for i, name := range regNamesARM {
+ num[name] = 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 (
+ gp = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14")
+ gpg = gp | buildReg("g")
+ gpsp = gp | buildReg("SP")
+ gpspg = gpg | buildReg("SP")
+ gpspsbg = gpspg | buildReg("SB")
+ fp = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15")
+ callerSave = gp | fp | buildReg("g") // runtime.setg (and anything calling it) may clobber g
+ r0 = buildReg("R0")
+ r1 = buildReg("R1")
+ r2 = buildReg("R2")
+ r3 = buildReg("R3")
+ r4 = buildReg("R4")
+ )
+ // Common regInfo
+ var (
+ gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
+ gp11 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
+ gp11carry = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp, 0}}
+ gp11sp = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
+ gp1flags = regInfo{inputs: []regMask{gpg}}
+ gp1flags1 = regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}
+ gp21 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
+ gp21carry = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp, 0}}
+ gp2flags = regInfo{inputs: []regMask{gpg, gpg}}
+ gp2flags1 = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
+ gp22 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp, gp}}
+ gp31 = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}}
+ gp31carry = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp, 0}}
+ gp3flags = regInfo{inputs: []regMask{gp, gp, gp}}
+ gp3flags1 = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}}
+ gpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
+ gpstore = regInfo{inputs: []regMask{gpspsbg, gpg}}
+ gp2load = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
+ gp2store = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}}
+ fp01 = regInfo{inputs: nil, outputs: []regMask{fp}}
+ fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
+ fp1flags = regInfo{inputs: []regMask{fp}}
+ fpgp = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}, clobbers: buildReg("F15")} // int-float conversion uses F15 as tmp
+ gpfp = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}, clobbers: buildReg("F15")}
+ fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
+ fp31 = regInfo{inputs: []regMask{fp, fp, fp}, outputs: []regMask{fp}}
+ fp2flags = regInfo{inputs: []regMask{fp, fp}}
+ fpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{fp}}
+ fpstore = regInfo{inputs: []regMask{gpspsbg, fp}}
+ readflags = regInfo{inputs: nil, outputs: []regMask{gp}}
+ )
+ ops := []opData{
+ // binary ops
+ {name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1
+ {name: "ADDconst", argLength: 1, reg: gp11sp, asm: "ADD", aux: "Int32"}, // arg0 + auxInt
+ {name: "SUB", argLength: 2, reg: gp21, asm: "SUB"}, // arg0 - arg1
+ {name: "SUBconst", argLength: 1, reg: gp11, asm: "SUB", aux: "Int32"}, // arg0 - auxInt
+ {name: "RSB", argLength: 2, reg: gp21, asm: "RSB"}, // arg1 - arg0
+ {name: "RSBconst", argLength: 1, reg: gp11, asm: "RSB", aux: "Int32"}, // auxInt - arg0
+ {name: "MUL", argLength: 2, reg: gp21, asm: "MUL", commutative: true}, // arg0 * arg1
+ {name: "HMUL", argLength: 2, reg: gp21, asm: "MULL", commutative: true}, // (arg0 * arg1) >> 32, signed
+ {name: "HMULU", argLength: 2, reg: gp21, asm: "MULLU", commutative: true}, // (arg0 * arg1) >> 32, unsigned
+
+ // udiv runtime call for soft division
+ // output0 = arg0/arg1, output1 = arg0%arg1
+ // see ../../../../../runtime/vlop_arm.s
+ {
+ name: "CALLudiv",
+ argLength: 2,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R1"), buildReg("R0")},
+ outputs: []regMask{buildReg("R0"), buildReg("R1")},
+ clobbers: buildReg("R2 R3 R14"),
+ },
+ clobberFlags: true,
+ typ: "(UInt32,UInt32)",
+ call: false, // TODO(mdempsky): Should this be true?
+ },
+
+ {name: "ADDS", argLength: 2, reg: gp21carry, asm: "ADD", commutative: true}, // arg0 + arg1, set carry flag
+ {name: "ADDSconst", argLength: 1, reg: gp11carry, asm: "ADD", aux: "Int32"}, // arg0 + auxInt, set carry flag
+ {name: "ADC", argLength: 3, reg: gp2flags1, asm: "ADC", commutative: true}, // arg0 + arg1 + carry, arg2=flags
+ {name: "ADCconst", argLength: 2, reg: gp1flags1, asm: "ADC", aux: "Int32"}, // arg0 + auxInt + carry, arg1=flags
+ {name: "SUBS", argLength: 2, reg: gp21carry, asm: "SUB"}, // arg0 - arg1, set carry flag
+ {name: "SUBSconst", argLength: 1, reg: gp11carry, asm: "SUB", aux: "Int32"}, // arg0 - auxInt, set carry flag
+ {name: "RSBSconst", argLength: 1, reg: gp11carry, asm: "RSB", aux: "Int32"}, // auxInt - arg0, set carry flag
+ {name: "SBC", argLength: 3, reg: gp2flags1, asm: "SBC"}, // arg0 - arg1 - carry, arg2=flags
+ {name: "SBCconst", argLength: 2, reg: gp1flags1, asm: "SBC", aux: "Int32"}, // arg0 - auxInt - carry, arg1=flags
+ {name: "RSCconst", argLength: 2, reg: gp1flags1, asm: "RSC", aux: "Int32"}, // auxInt - arg0 - carry, arg1=flags
+
+ {name: "MULLU", argLength: 2, reg: gp22, asm: "MULLU", commutative: true}, // arg0 * arg1, high 32 bits in out0, low 32 bits in out1
+ {name: "MULA", argLength: 3, reg: gp31, asm: "MULA"}, // arg0 * arg1 + arg2
+ {name: "MULS", argLength: 3, reg: gp31, asm: "MULS"}, // arg2 - arg0 * arg1
+
+ {name: "ADDF", argLength: 2, reg: fp21, asm: "ADDF", commutative: true}, // arg0 + arg1
+ {name: "ADDD", argLength: 2, reg: fp21, asm: "ADDD", commutative: true}, // arg0 + arg1
+ {name: "SUBF", argLength: 2, reg: fp21, asm: "SUBF"}, // arg0 - arg1
+ {name: "SUBD", argLength: 2, reg: fp21, asm: "SUBD"}, // arg0 - arg1
+ {name: "MULF", argLength: 2, reg: fp21, asm: "MULF", commutative: true}, // arg0 * arg1
+ {name: "MULD", argLength: 2, reg: fp21, asm: "MULD", commutative: true}, // arg0 * arg1
+ {name: "NMULF", argLength: 2, reg: fp21, asm: "NMULF", commutative: true}, // -(arg0 * arg1)
+ {name: "NMULD", argLength: 2, reg: fp21, asm: "NMULD", commutative: true}, // -(arg0 * arg1)
+ {name: "DIVF", argLength: 2, reg: fp21, asm: "DIVF"}, // arg0 / arg1
+ {name: "DIVD", argLength: 2, reg: fp21, asm: "DIVD"}, // arg0 / arg1
+
+ {name: "MULAF", argLength: 3, reg: fp31, asm: "MULAF", resultInArg0: true}, // arg0 + (arg1 * arg2)
+ {name: "MULAD", argLength: 3, reg: fp31, asm: "MULAD", resultInArg0: true}, // arg0 + (arg1 * arg2)
+ {name: "MULSF", argLength: 3, reg: fp31, asm: "MULSF", resultInArg0: true}, // arg0 - (arg1 * arg2)
+ {name: "MULSD", argLength: 3, reg: fp31, asm: "MULSD", resultInArg0: true}, // arg0 - (arg1 * arg2)
+
+ // FMULAD only exists on platforms with the VFPv4 instruction set.
+ // Any use must be preceded by a successful check of runtime.arm_support_vfpv4.
+ {name: "FMULAD", argLength: 3, reg: fp31, asm: "FMULAD", resultInArg0: true}, // arg0 + (arg1 * arg2)
+
+ {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0 & arg1
+ {name: "ANDconst", argLength: 1, reg: gp11, asm: "AND", aux: "Int32"}, // arg0 & auxInt
+ {name: "OR", argLength: 2, reg: gp21, asm: "ORR", commutative: true}, // arg0 | arg1
+ {name: "ORconst", argLength: 1, reg: gp11, asm: "ORR", aux: "Int32"}, // arg0 | auxInt
+ {name: "XOR", argLength: 2, reg: gp21, asm: "EOR", commutative: true}, // arg0 ^ arg1
+ {name: "XORconst", argLength: 1, reg: gp11, asm: "EOR", aux: "Int32"}, // arg0 ^ auxInt
+ {name: "BIC", argLength: 2, reg: gp21, asm: "BIC"}, // arg0 &^ arg1
+ {name: "BICconst", argLength: 1, reg: gp11, asm: "BIC", aux: "Int32"}, // arg0 &^ auxInt
+
+ // bit extraction, AuxInt = Width<<8 | LSB
+ {name: "BFX", argLength: 1, reg: gp11, asm: "BFX", aux: "Int32"}, // extract W bits from bit L in arg0, then signed extend
+ {name: "BFXU", argLength: 1, reg: gp11, asm: "BFXU", aux: "Int32"}, // extract W bits from bit L in arg0, then unsigned extend
+
+ // unary ops
+ {name: "MVN", argLength: 1, reg: gp11, asm: "MVN"}, // ^arg0
+
+ {name: "NEGF", argLength: 1, reg: fp11, asm: "NEGF"}, // -arg0, float32
+ {name: "NEGD", argLength: 1, reg: fp11, asm: "NEGD"}, // -arg0, float64
+ {name: "SQRTD", argLength: 1, reg: fp11, asm: "SQRTD"}, // sqrt(arg0), float64
+ {name: "ABSD", argLength: 1, reg: fp11, asm: "ABSD"}, // abs(arg0), float64
+
+ {name: "CLZ", argLength: 1, reg: gp11, asm: "CLZ"}, // count leading zero
+ {name: "REV", argLength: 1, reg: gp11, asm: "REV"}, // reverse byte order
+ {name: "REV16", argLength: 1, reg: gp11, asm: "REV16"}, // reverse byte order in 16-bit halfwords
+ {name: "RBIT", argLength: 1, reg: gp11, asm: "RBIT"}, // reverse bit order
+
+ // shifts
+ {name: "SLL", argLength: 2, reg: gp21, asm: "SLL"}, // arg0 << arg1, shift amount is mod 256
+ {name: "SLLconst", argLength: 1, reg: gp11, asm: "SLL", aux: "Int32"}, // arg0 << auxInt, 0 <= auxInt < 32
+ {name: "SRL", argLength: 2, reg: gp21, asm: "SRL"}, // arg0 >> arg1, unsigned, shift amount is mod 256
+ {name: "SRLconst", argLength: 1, reg: gp11, asm: "SRL", aux: "Int32"}, // arg0 >> auxInt, unsigned, 0 <= auxInt < 32
+ {name: "SRA", argLength: 2, reg: gp21, asm: "SRA"}, // arg0 >> arg1, signed, shift amount is mod 256
+ {name: "SRAconst", argLength: 1, reg: gp11, asm: "SRA", aux: "Int32"}, // arg0 >> auxInt, signed, 0 <= auxInt < 32
+ {name: "SRR", argLength: 2, reg: gp21}, // arg0 right rotate by arg1 bits
+ {name: "SRRconst", argLength: 1, reg: gp11, aux: "Int32"}, // arg0 right rotate by auxInt bits, 0 <= auxInt < 32
+
+ // auxInt for all of these satisfy 0 <= auxInt < 32
+ {name: "ADDshiftLL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1<<auxInt
+ {name: "ADDshiftRL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, unsigned shift
+ {name: "ADDshiftRA", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, signed shift
+ {name: "SUBshiftLL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int32"}, // arg0 - arg1<<auxInt
+ {name: "SUBshiftRL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, unsigned shift
+ {name: "SUBshiftRA", argLength: 2, reg: gp21, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, signed shift
+ {name: "RSBshiftLL", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1<<auxInt - arg0
+ {name: "RSBshiftRL", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, unsigned shift
+ {name: "RSBshiftRA", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, signed shift
+ {name: "ANDshiftLL", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0 & (arg1<<auxInt)
+ {name: "ANDshiftRL", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0 & (arg1>>auxInt), unsigned shift
+ {name: "ANDshiftRA", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0 & (arg1>>auxInt), signed shift
+ {name: "ORshiftLL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"}, // arg0 | arg1<<auxInt
+ {name: "ORshiftRL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"}, // arg0 | arg1>>auxInt, unsigned shift
+ {name: "ORshiftRA", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"}, // arg0 | arg1>>auxInt, signed shift
+ {name: "XORshiftLL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0 ^ arg1<<auxInt
+ {name: "XORshiftRL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0 ^ arg1>>auxInt, unsigned shift
+ {name: "XORshiftRA", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0 ^ arg1>>auxInt, signed shift
+ {name: "XORshiftRR", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0 ^ (arg1 right rotate by auxInt)
+ {name: "BICshiftLL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0 &^ (arg1<<auxInt)
+ {name: "BICshiftRL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0 &^ (arg1>>auxInt), unsigned shift
+ {name: "BICshiftRA", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0 &^ (arg1>>auxInt), signed shift
+ {name: "MVNshiftLL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int32"}, // ^(arg0<<auxInt)
+ {name: "MVNshiftRL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int32"}, // ^(arg0>>auxInt), unsigned shift
+ {name: "MVNshiftRA", argLength: 1, reg: gp11, asm: "MVN", aux: "Int32"}, // ^(arg0>>auxInt), signed shift
+
+ {name: "ADCshiftLL", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0 + arg1<<auxInt + carry, arg2=flags
+ {name: "ADCshiftRL", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0 + arg1>>auxInt + carry, unsigned shift, arg2=flags
+ {name: "ADCshiftRA", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0 + arg1>>auxInt + carry, signed shift, arg2=flags
+ {name: "SBCshiftLL", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0 - arg1<<auxInt - carry, arg2=flags
+ {name: "SBCshiftRL", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0 - arg1>>auxInt - carry, unsigned shift, arg2=flags
+ {name: "SBCshiftRA", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0 - arg1>>auxInt - carry, signed shift, arg2=flags
+ {name: "RSCshiftLL", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1<<auxInt - arg0 - carry, arg2=flags
+ {name: "RSCshiftRL", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1>>auxInt - arg0 - carry, unsigned shift, arg2=flags
+ {name: "RSCshiftRA", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1>>auxInt - arg0 - carry, signed shift, arg2=flags
+
+ {name: "ADDSshiftLL", argLength: 2, reg: gp21carry, asm: "ADD", aux: "Int32"}, // arg0 + arg1<<auxInt, set carry flag
+ {name: "ADDSshiftRL", argLength: 2, reg: gp21carry, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, unsigned shift, set carry flag
+ {name: "ADDSshiftRA", argLength: 2, reg: gp21carry, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, signed shift, set carry flag
+ {name: "SUBSshiftLL", argLength: 2, reg: gp21carry, asm: "SUB", aux: "Int32"}, // arg0 - arg1<<auxInt, set carry flag
+ {name: "SUBSshiftRL", argLength: 2, reg: gp21carry, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, unsigned shift, set carry flag
+ {name: "SUBSshiftRA", argLength: 2, reg: gp21carry, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, signed shift, set carry flag
+ {name: "RSBSshiftLL", argLength: 2, reg: gp21carry, asm: "RSB", aux: "Int32"}, // arg1<<auxInt - arg0, set carry flag
+ {name: "RSBSshiftRL", argLength: 2, reg: gp21carry, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, unsigned shift, set carry flag
+ {name: "RSBSshiftRA", argLength: 2, reg: gp21carry, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, signed shift, set carry flag
+
+ {name: "ADDshiftLLreg", argLength: 3, reg: gp31, asm: "ADD"}, // arg0 + arg1<<arg2
+ {name: "ADDshiftRLreg", argLength: 3, reg: gp31, asm: "ADD"}, // arg0 + arg1>>arg2, unsigned shift
+ {name: "ADDshiftRAreg", argLength: 3, reg: gp31, asm: "ADD"}, // arg0 + arg1>>arg2, signed shift
+ {name: "SUBshiftLLreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0 - arg1<<arg2
+ {name: "SUBshiftRLreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0 - arg1>>arg2, unsigned shift
+ {name: "SUBshiftRAreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0 - arg1>>arg2, signed shift
+ {name: "RSBshiftLLreg", argLength: 3, reg: gp31, asm: "RSB"}, // arg1<<arg2 - arg0
+ {name: "RSBshiftRLreg", argLength: 3, reg: gp31, asm: "RSB"}, // arg1>>arg2 - arg0, unsigned shift
+ {name: "RSBshiftRAreg", argLength: 3, reg: gp31, asm: "RSB"}, // arg1>>arg2 - arg0, signed shift
+ {name: "ANDshiftLLreg", argLength: 3, reg: gp31, asm: "AND"}, // arg0 & (arg1<<arg2)
+ {name: "ANDshiftRLreg", argLength: 3, reg: gp31, asm: "AND"}, // arg0 & (arg1>>arg2), unsigned shift
+ {name: "ANDshiftRAreg", argLength: 3, reg: gp31, asm: "AND"}, // arg0 & (arg1>>arg2), signed shift
+ {name: "ORshiftLLreg", argLength: 3, reg: gp31, asm: "ORR"}, // arg0 | arg1<<arg2
+ {name: "ORshiftRLreg", argLength: 3, reg: gp31, asm: "ORR"}, // arg0 | arg1>>arg2, unsigned shift
+ {name: "ORshiftRAreg", argLength: 3, reg: gp31, asm: "ORR"}, // arg0 | arg1>>arg2, signed shift
+ {name: "XORshiftLLreg", argLength: 3, reg: gp31, asm: "EOR"}, // arg0 ^ arg1<<arg2
+ {name: "XORshiftRLreg", argLength: 3, reg: gp31, asm: "EOR"}, // arg0 ^ arg1>>arg2, unsigned shift
+ {name: "XORshiftRAreg", argLength: 3, reg: gp31, asm: "EOR"}, // arg0 ^ arg1>>arg2, signed shift
+ {name: "BICshiftLLreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0 &^ (arg1<<arg2)
+ {name: "BICshiftRLreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0 &^ (arg1>>arg2), unsigned shift
+ {name: "BICshiftRAreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0 &^ (arg1>>arg2), signed shift
+ {name: "MVNshiftLLreg", argLength: 2, reg: gp21, asm: "MVN"}, // ^(arg0<<arg1)
+ {name: "MVNshiftRLreg", argLength: 2, reg: gp21, asm: "MVN"}, // ^(arg0>>arg1), unsigned shift
+ {name: "MVNshiftRAreg", argLength: 2, reg: gp21, asm: "MVN"}, // ^(arg0>>arg1), signed shift
+
+ {name: "ADCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0 + arg1<<arg2 + carry, arg3=flags
+ {name: "ADCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0 + arg1>>arg2 + carry, unsigned shift, arg3=flags
+ {name: "ADCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0 + arg1>>arg2 + carry, signed shift, arg3=flags
+ {name: "SBCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0 - arg1<<arg2 - carry, arg3=flags
+ {name: "SBCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0 - arg1>>arg2 - carry, unsigned shift, arg3=flags
+ {name: "SBCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0 - arg1>>arg2 - carry, signed shift, arg3=flags
+ {name: "RSCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1<<arg2 - arg0 - carry, arg3=flags
+ {name: "RSCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1>>arg2 - arg0 - carry, unsigned shift, arg3=flags
+ {name: "RSCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1>>arg2 - arg0 - carry, signed shift, arg3=flags
+
+ {name: "ADDSshiftLLreg", argLength: 3, reg: gp31carry, asm: "ADD"}, // arg0 + arg1<<arg2, set carry flag
+ {name: "ADDSshiftRLreg", argLength: 3, reg: gp31carry, asm: "ADD"}, // arg0 + arg1>>arg2, unsigned shift, set carry flag
+ {name: "ADDSshiftRAreg", argLength: 3, reg: gp31carry, asm: "ADD"}, // arg0 + arg1>>arg2, signed shift, set carry flag
+ {name: "SUBSshiftLLreg", argLength: 3, reg: gp31carry, asm: "SUB"}, // arg0 - arg1<<arg2, set carry flag
+ {name: "SUBSshiftRLreg", argLength: 3, reg: gp31carry, asm: "SUB"}, // arg0 - arg1>>arg2, unsigned shift, set carry flag
+ {name: "SUBSshiftRAreg", argLength: 3, reg: gp31carry, asm: "SUB"}, // arg0 - arg1>>arg2, signed shift, set carry flag
+ {name: "RSBSshiftLLreg", argLength: 3, reg: gp31carry, asm: "RSB"}, // arg1<<arg2 - arg0, set carry flag
+ {name: "RSBSshiftRLreg", argLength: 3, reg: gp31carry, asm: "RSB"}, // arg1>>arg2 - arg0, unsigned shift, set carry flag
+ {name: "RSBSshiftRAreg", argLength: 3, reg: gp31carry, asm: "RSB"}, // arg1>>arg2 - arg0, signed shift, set carry flag
+
+ // comparisons
+ {name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt
+ {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1
+ {name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt
+ {name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0
+ {name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & auxInt compare to 0
+ {name: "TEQ", argLength: 2, reg: gp2flags, asm: "TEQ", typ: "Flags", commutative: true}, // arg0 ^ arg1 compare to 0
+ {name: "TEQconst", argLength: 1, reg: gp1flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0 ^ auxInt compare to 0
+ {name: "CMPF", argLength: 2, reg: fp2flags, asm: "CMPF", typ: "Flags"}, // arg0 compare to arg1, float32
+ {name: "CMPD", argLength: 2, reg: fp2flags, asm: "CMPD", typ: "Flags"}, // arg0 compare to arg1, float64
+
+ {name: "CMPshiftLL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to arg1<<auxInt
+ {name: "CMPshiftRL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to arg1>>auxInt, unsigned shift
+ {name: "CMPshiftRA", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to arg1>>auxInt, signed shift
+ {name: "CMNshiftLL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0 compare to -(arg1<<auxInt)
+ {name: "CMNshiftRL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0 compare to -(arg1>>auxInt), unsigned shift
+ {name: "CMNshiftRA", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0 compare to -(arg1>>auxInt), signed shift
+ {name: "TSTshiftLL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & (arg1<<auxInt) compare to 0
+ {name: "TSTshiftRL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & (arg1>>auxInt) compare to 0, unsigned shift
+ {name: "TSTshiftRA", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & (arg1>>auxInt) compare to 0, signed shift
+ {name: "TEQshiftLL", argLength: 2, reg: gp2flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0 ^ (arg1<<auxInt) compare to 0
+ {name: "TEQshiftRL", argLength: 2, reg: gp2flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0 ^ (arg1>>auxInt) compare to 0, unsigned shift
+ {name: "TEQshiftRA", argLength: 2, reg: gp2flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0 ^ (arg1>>auxInt) compare to 0, signed shift
+
+ {name: "CMPshiftLLreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1<<arg2
+ {name: "CMPshiftRLreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1>>arg2, unsigned shift
+ {name: "CMPshiftRAreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1>>arg2, signed shift
+ {name: "CMNshiftLLreg", argLength: 3, reg: gp3flags, asm: "CMN", typ: "Flags"}, // arg0 + (arg1<<arg2) compare to 0
+ {name: "CMNshiftRLreg", argLength: 3, reg: gp3flags, asm: "CMN", typ: "Flags"}, // arg0 + (arg1>>arg2) compare to 0, unsigned shift
+ {name: "CMNshiftRAreg", argLength: 3, reg: gp3flags, asm: "CMN", typ: "Flags"}, // arg0 + (arg1>>arg2) compare to 0, signed shift
+ {name: "TSTshiftLLreg", argLength: 3, reg: gp3flags, asm: "TST", typ: "Flags"}, // arg0 & (arg1<<arg2) compare to 0
+ {name: "TSTshiftRLreg", argLength: 3, reg: gp3flags, asm: "TST", typ: "Flags"}, // arg0 & (arg1>>arg2) compare to 0, unsigned shift
+ {name: "TSTshiftRAreg", argLength: 3, reg: gp3flags, asm: "TST", typ: "Flags"}, // arg0 & (arg1>>arg2) compare to 0, signed shift
+ {name: "TEQshiftLLreg", argLength: 3, reg: gp3flags, asm: "TEQ", typ: "Flags"}, // arg0 ^ (arg1<<arg2) compare to 0
+ {name: "TEQshiftRLreg", argLength: 3, reg: gp3flags, asm: "TEQ", typ: "Flags"}, // arg0 ^ (arg1>>arg2) compare to 0, unsigned shift
+ {name: "TEQshiftRAreg", argLength: 3, reg: gp3flags, asm: "TEQ", typ: "Flags"}, // arg0 ^ (arg1>>arg2) compare to 0, signed shift
+
+ {name: "CMPF0", argLength: 1, reg: fp1flags, asm: "CMPF", typ: "Flags"}, // arg0 compare to 0, float32
+ {name: "CMPD0", argLength: 1, reg: fp1flags, asm: "CMPD", typ: "Flags"}, // arg0 compare to 0, float64
+
+ // moves
+ {name: "MOVWconst", argLength: 0, reg: gp01, aux: "Int32", asm: "MOVW", typ: "UInt32", rematerializeable: true}, // 32 low bits of auxint
+ {name: "MOVFconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVF", typ: "Float32", rematerializeable: true}, // auxint as 64-bit float, convert to 32-bit float
+ {name: "MOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVD", typ: "Float64", rematerializeable: true}, // auxint as 64-bit float
+
+ {name: "MOVWaddr", argLength: 1, reg: regInfo{inputs: []regMask{buildReg("SP") | buildReg("SB")}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVW", rematerializeable: true, symEffect: "Addr"}, // arg0 + auxInt + aux.(*gc.Sym), arg0=SP/SB
+
+ {name: "MOVBload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVB", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVBUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVBU", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVH", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVHU", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVWload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVW", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVFload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVF", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVDload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVD", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+
+ {name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 1 byte of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVFstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVF", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+
+ {name: "MOVWloadidx", argLength: 3, reg: gp2load, asm: "MOVW", typ: "UInt32"}, // load from arg0 + arg1. arg2=mem
+ {name: "MOVWloadshiftLL", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32", typ: "UInt32"}, // load from arg0 + arg1<<auxInt. arg2=mem
+ {name: "MOVWloadshiftRL", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32", typ: "UInt32"}, // load from arg0 + arg1>>auxInt, unsigned shift. arg2=mem
+ {name: "MOVWloadshiftRA", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32", typ: "UInt32"}, // load from arg0 + arg1>>auxInt, signed shift. arg2=mem
+ {name: "MOVBUloadidx", argLength: 3, reg: gp2load, asm: "MOVBU", typ: "UInt8"}, // load from arg0 + arg1. arg2=mem
+ {name: "MOVBloadidx", argLength: 3, reg: gp2load, asm: "MOVB", typ: "Int8"}, // load from arg0 + arg1. arg2=mem
+ {name: "MOVHUloadidx", argLength: 3, reg: gp2load, asm: "MOVHU", typ: "UInt16"}, // load from arg0 + arg1. arg2=mem
+ {name: "MOVHloadidx", argLength: 3, reg: gp2load, asm: "MOVH", typ: "Int16"}, // load from arg0 + arg1. arg2=mem
+
+ {name: "MOVWstoreidx", argLength: 4, reg: gp2store, asm: "MOVW", typ: "Mem"}, // store arg2 to arg0 + arg1. arg3=mem
+ {name: "MOVWstoreshiftLL", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32", typ: "Mem"}, // store arg2 to arg0 + arg1<<auxInt. arg3=mem
+ {name: "MOVWstoreshiftRL", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32", typ: "Mem"}, // store arg2 to arg0 + arg1>>auxInt, unsigned shift. arg3=mem
+ {name: "MOVWstoreshiftRA", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32", typ: "Mem"}, // store arg2 to arg0 + arg1>>auxInt, signed shift. arg3=mem
+ {name: "MOVBstoreidx", argLength: 4, reg: gp2store, asm: "MOVB", typ: "Mem"}, // store arg2 to arg0 + arg1. arg3=mem
+ {name: "MOVHstoreidx", argLength: 4, reg: gp2store, asm: "MOVH", typ: "Mem"}, // store arg2 to arg0 + arg1. arg3=mem
+
+ {name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVBS"}, // move from arg0, sign-extended from byte
+ {name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // move from arg0, unsign-extended from byte
+ {name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVHS"}, // move from arg0, sign-extended from half
+ {name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // move from arg0, unsign-extended from half
+ {name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"}, // move from arg0
+
+ {name: "MOVWnop", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // nop, return arg0 in same register
+
+ {name: "MOVWF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // int32 -> float32
+ {name: "MOVWD", argLength: 1, reg: gpfp, asm: "MOVWD"}, // int32 -> float64
+ {name: "MOVWUF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // uint32 -> float32, set U bit in the instruction
+ {name: "MOVWUD", argLength: 1, reg: gpfp, asm: "MOVWD"}, // uint32 -> float64, set U bit in the instruction
+ {name: "MOVFW", argLength: 1, reg: fpgp, asm: "MOVFW"}, // float32 -> int32
+ {name: "MOVDW", argLength: 1, reg: fpgp, asm: "MOVDW"}, // float64 -> int32
+ {name: "MOVFWU", argLength: 1, reg: fpgp, asm: "MOVFW"}, // float32 -> uint32, set U bit in the instruction
+ {name: "MOVDWU", argLength: 1, reg: fpgp, asm: "MOVDW"}, // float64 -> uint32, set U bit in the instruction
+ {name: "MOVFD", argLength: 1, reg: fp11, asm: "MOVFD"}, // float32 -> float64
+ {name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
+
+ // conditional instructions, for lowering shifts
+ {name: "CMOVWHSconst", argLength: 2, reg: gp1flags1, asm: "MOVW", aux: "Int32", resultInArg0: true}, // replace arg0 w/ const if flags indicates HS, arg1=flags
+ {name: "CMOVWLSconst", argLength: 2, reg: gp1flags1, asm: "MOVW", aux: "Int32", resultInArg0: true}, // replace arg0 w/ const if flags indicates LS, arg1=flags
+ {name: "SRAcond", argLength: 3, reg: gp2flags1, asm: "SRA"}, // arg0 >> 31 if flags indicates HS, arg0 >> arg1 otherwise, signed shift, arg2=flags
+
+ // function calls
+ {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
+ {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
+ {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
+
+ // pseudo-ops
+ {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem.
+
+ {name: "Equal", argLength: 1, reg: readflags}, // bool, true flags encode x==y false otherwise.
+ {name: "NotEqual", argLength: 1, reg: readflags}, // bool, true flags encode x!=y false otherwise.
+ {name: "LessThan", argLength: 1, reg: readflags}, // bool, true flags encode signed x<y false otherwise.
+ {name: "LessEqual", argLength: 1, reg: readflags}, // bool, true flags encode signed x<=y false otherwise.
+ {name: "GreaterThan", argLength: 1, reg: readflags}, // bool, true flags encode signed x>y false otherwise.
+ {name: "GreaterEqual", argLength: 1, reg: readflags}, // bool, true flags encode signed x>=y false otherwise.
+ {name: "LessThanU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x<y false otherwise.
+ {name: "LessEqualU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x<=y false otherwise.
+ {name: "GreaterThanU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x>y false otherwise.
+ {name: "GreaterEqualU", argLength: 1, reg: readflags}, // bool, true flags encode unsigned x>=y false otherwise.
+
+ // duffzero (must be 4-byte aligned)
+ // arg0 = address of memory to zero (in R1, changed as side effect)
+ // arg1 = value to store (always zero)
+ // arg2 = mem
+ // auxint = offset into duffzero code to start executing
+ // returns mem
+ {
+ name: "DUFFZERO",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R1"), buildReg("R0")},
+ clobbers: buildReg("R1 R14"),
+ },
+ faultOnNilArg0: true,
+ },
+
+ // duffcopy (must be 4-byte aligned)
+ // arg0 = address of dst memory (in R2, changed as side effect)
+ // arg1 = address of src memory (in R1, changed as side effect)
+ // arg2 = mem
+ // auxint = offset into duffcopy code to start executing
+ // returns mem
+ {
+ name: "DUFFCOPY",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R2"), buildReg("R1")},
+ clobbers: buildReg("R0 R1 R2 R14"),
+ },
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // large or unaligned zeroing
+ // arg0 = address of memory to zero (in R1, changed as side effect)
+ // arg1 = address of the last element to zero
+ // arg2 = value to store (always zero)
+ // arg3 = mem
+ // returns mem
+ // MOVW.P Rarg2, 4(R1)
+ // CMP R1, Rarg1
+ // BLE -2(PC)
+ {
+ name: "LoweredZero",
+ aux: "Int64",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R1"), gp, gp},
+ clobbers: buildReg("R1"),
+ },
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ },
+
+ // large or unaligned move
+ // arg0 = address of dst memory (in R2, changed as side effect)
+ // arg1 = address of src memory (in R1, changed as side effect)
+ // arg2 = address of the last element of src
+ // arg3 = mem
+ // returns mem
+ // MOVW.P 4(R1), Rtmp
+ // MOVW.P Rtmp, 4(R2)
+ // CMP R1, Rarg2
+ // BLE -3(PC)
+ {
+ name: "LoweredMove",
+ aux: "Int64",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R2"), buildReg("R1"), gp},
+ clobbers: buildReg("R1 R2"),
+ },
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // Scheduler ensures LoweredGetClosurePtr occurs only in entry block,
+ // and sorts it to the very beginning of the block to prevent other
+ // use of R7 (arm.REGCTXT, the closure pointer)
+ {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R7")}}, zeroWidth: true},
+
+ // LoweredGetCallerSP returns the SP of the caller of the current function.
+ {name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
+
+ // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+ // I.e., if f calls g "calls" getcallerpc,
+ // the result should be the PC within f that g will return to.
+ // See runtime/stubs.go for a more detailed discussion.
+ {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
+
+ // There are three of these functions so that they can have three different register inputs.
+ // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
+ // default registers to match so we don't need to copy registers around unnecessarily.
+ {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r0, r1}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ // Extend ops are the same as Bounds ops except the indexes are 64-bit.
+ {name: "LoweredPanicExtendA", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r4, r2, r3}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
+ {name: "LoweredPanicExtendB", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r4, r1, r2}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
+ {name: "LoweredPanicExtendC", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r4, r0, r1}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
+
+ // Constant flag value.
+ // Note: there's an "unordered" outcome for floating-point
+ // comparisons, but we don't use such a beast yet.
+ // This op is for temporary use by rewrite rules. It
+ // cannot appear in the generated assembly.
+ {name: "FlagConstant", aux: "FlagConstant"},
+
+ // (InvertFlags (CMP a b)) == (CMP b a)
+ // InvertFlags is a pseudo-op which can't appear in assembly output.
+ {name: "InvertFlags", argLength: 1}, // reverse direction of arg0
+
+ // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+ // It saves all GP registers if necessary,
+ // but clobbers R14 (LR) because it's a call.
+ {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R14")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
+ }
+
+ blocks := []blockData{
+ {name: "EQ", controls: 1},
+ {name: "NE", controls: 1},
+ {name: "LT", controls: 1},
+ {name: "LE", controls: 1},
+ {name: "GT", controls: 1},
+ {name: "GE", controls: 1},
+ {name: "ULT", controls: 1},
+ {name: "ULE", controls: 1},
+ {name: "UGT", controls: 1},
+ {name: "UGE", controls: 1},
+ {name: "LTnoov", controls: 1}, // 'LT' but without honoring overflow
+ {name: "LEnoov", controls: 1}, // 'LE' but without honoring overflow
+ {name: "GTnoov", controls: 1}, // 'GT' but without honoring overflow
+ {name: "GEnoov", controls: 1}, // 'GE' but without honoring overflow
+ }
+
+ archs = append(archs, arch{
+ name: "ARM",
+ pkg: "cmd/internal/obj/arm",
+ genfile: "../../arm/ssa.go",
+ ops: ops,
+ blocks: blocks,
+ regnames: regNamesARM,
+ gpregmask: gp,
+ fpregmask: fp,
+ framepointerreg: -1, // not used
+ linkreg: int8(num["R14"]),
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/MIPS.rules b/src/cmd/compile/internal/ssa/gen/MIPS.rules
new file mode 100644
index 0000000..8ad2c90
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/MIPS.rules
@@ -0,0 +1,697 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+(Add(Ptr|32|16|8) ...) => (ADD ...)
+(Add(32|64)F ...) => (ADD(F|D) ...)
+
+(Select0 (Add32carry <t> x y)) => (ADD <t.FieldType(0)> x y)
+(Select1 (Add32carry <t> x y)) => (SGTU <typ.Bool> x (ADD <t.FieldType(0)> x y))
+(Add32withcarry <t> x y c) => (ADD c (ADD <t> x y))
+
+(Sub(Ptr|32|16|8) ...) => (SUB ...)
+(Sub(32|64)F ...) => (SUB(F|D) ...)
+
+(Select0 (Sub32carry <t> x y)) => (SUB <t.FieldType(0)> x y)
+(Select1 (Sub32carry <t> x y)) => (SGTU <typ.Bool> (SUB <t.FieldType(0)> x y) x)
+(Sub32withcarry <t> x y c) => (SUB (SUB <t> x y) c)
+
+(Mul(32|16|8) ...) => (MUL ...)
+(Mul(32|64)F ...) => (MUL(F|D) ...)
+
+(Hmul(32|32u) x y) => (Select0 (MUL(T|TU) x y))
+(Mul32uhilo ...) => (MULTU ...)
+
+(Div32 x y) => (Select1 (DIV x y))
+(Div32u x y) => (Select1 (DIVU x y))
+(Div16 x y) => (Select1 (DIV (SignExt16to32 x) (SignExt16to32 y)))
+(Div16u x y) => (Select1 (DIVU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Div8 x y) => (Select1 (DIV (SignExt8to32 x) (SignExt8to32 y)))
+(Div8u x y) => (Select1 (DIVU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Div(32|64)F ...) => (DIV(F|D) ...)
+
+(Mod32 x y) => (Select0 (DIV x y))
+(Mod32u x y) => (Select0 (DIVU x y))
+(Mod16 x y) => (Select0 (DIV (SignExt16to32 x) (SignExt16to32 y)))
+(Mod16u x y) => (Select0 (DIVU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Mod8 x y) => (Select0 (DIV (SignExt8to32 x) (SignExt8to32 y)))
+(Mod8u x y) => (Select0 (DIVU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+
+// (x + y) / 2 with x>=y becomes (x - y) / 2 + y
+(Avg32u <t> x y) => (ADD (SRLconst <t> (SUB <t> x y) [1]) y)
+
+(And(32|16|8) ...) => (AND ...)
+(Or(32|16|8) ...) => (OR ...)
+(Xor(32|16|8) ...) => (XOR ...)
+
+// constant shifts
+// generic opt rewrites all constant shifts to shift by Const64
+(Lsh32x64 x (Const64 [c])) && uint32(c) < 32 => (SLLconst x [int32(c)])
+(Rsh32x64 x (Const64 [c])) && uint32(c) < 32 => (SRAconst x [int32(c)])
+(Rsh32Ux64 x (Const64 [c])) && uint32(c) < 32 => (SRLconst x [int32(c)])
+(Lsh16x64 x (Const64 [c])) && uint32(c) < 16 => (SLLconst x [int32(c)])
+(Rsh16x64 x (Const64 [c])) && uint32(c) < 16 => (SRAconst (SLLconst <typ.UInt32> x [16]) [int32(c+16)])
+(Rsh16Ux64 x (Const64 [c])) && uint32(c) < 16 => (SRLconst (SLLconst <typ.UInt32> x [16]) [int32(c+16)])
+(Lsh8x64 x (Const64 [c])) && uint32(c) < 8 => (SLLconst x [int32(c)])
+(Rsh8x64 x (Const64 [c])) && uint32(c) < 8 => (SRAconst (SLLconst <typ.UInt32> x [24]) [int32(c+24)])
+(Rsh8Ux64 x (Const64 [c])) && uint32(c) < 8 => (SRLconst (SLLconst <typ.UInt32> x [24]) [int32(c+24)])
+
+// large constant shifts
+(Lsh32x64 _ (Const64 [c])) && uint32(c) >= 32 => (MOVWconst [0])
+(Rsh32Ux64 _ (Const64 [c])) && uint32(c) >= 32 => (MOVWconst [0])
+(Lsh16x64 _ (Const64 [c])) && uint32(c) >= 16 => (MOVWconst [0])
+(Rsh16Ux64 _ (Const64 [c])) && uint32(c) >= 16 => (MOVWconst [0])
+(Lsh8x64 _ (Const64 [c])) && uint32(c) >= 8 => (MOVWconst [0])
+(Rsh8Ux64 _ (Const64 [c])) && uint32(c) >= 8 => (MOVWconst [0])
+
+// large constant signed right shift, we leave the sign bit
+(Rsh32x64 x (Const64 [c])) && uint32(c) >= 32 => (SRAconst x [31])
+(Rsh16x64 x (Const64 [c])) && uint32(c) >= 16 => (SRAconst (SLLconst <typ.UInt32> x [16]) [31])
+(Rsh8x64 x (Const64 [c])) && uint32(c) >= 8 => (SRAconst (SLLconst <typ.UInt32> x [24]) [31])
+
+// shifts
+// hardware instruction uses only the low 5 bits of the shift
+// we compare to 32 to ensure Go semantics for large shifts
+(Lsh32x32 <t> x y) => (CMOVZ (SLL <t> x y) (MOVWconst [0]) (SGTUconst [32] y))
+(Lsh32x16 <t> x y) => (CMOVZ (SLL <t> x (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+(Lsh32x8 <t> x y) => (CMOVZ (SLL <t> x (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+
+(Lsh16x32 <t> x y) => (CMOVZ (SLL <t> x y) (MOVWconst [0]) (SGTUconst [32] y))
+(Lsh16x16 <t> x y) => (CMOVZ (SLL <t> x (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+(Lsh16x8 <t> x y) => (CMOVZ (SLL <t> x (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+
+(Lsh8x32 <t> x y) => (CMOVZ (SLL <t> x y) (MOVWconst [0]) (SGTUconst [32] y))
+(Lsh8x16 <t> x y) => (CMOVZ (SLL <t> x (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+(Lsh8x8 <t> x y) => (CMOVZ (SLL <t> x (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+
+(Rsh32Ux32 <t> x y) => (CMOVZ (SRL <t> x y) (MOVWconst [0]) (SGTUconst [32] y))
+(Rsh32Ux16 <t> x y) => (CMOVZ (SRL <t> x (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+(Rsh32Ux8 <t> x y) => (CMOVZ (SRL <t> x (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+
+(Rsh16Ux32 <t> x y) => (CMOVZ (SRL <t> (ZeroExt16to32 x) y) (MOVWconst [0]) (SGTUconst [32] y))
+(Rsh16Ux16 <t> x y) => (CMOVZ (SRL <t> (ZeroExt16to32 x) (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+(Rsh16Ux8 <t> x y) => (CMOVZ (SRL <t> (ZeroExt16to32 x) (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+
+(Rsh8Ux32 <t> x y) => (CMOVZ (SRL <t> (ZeroExt8to32 x) y) (MOVWconst [0]) (SGTUconst [32] y))
+(Rsh8Ux16 <t> x y) => (CMOVZ (SRL <t> (ZeroExt8to32 x) (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+(Rsh8Ux8 <t> x y) => (CMOVZ (SRL <t> (ZeroExt8to32 x) (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+
+(Rsh32x32 x y) => (SRA x ( CMOVZ <typ.UInt32> y (MOVWconst [31]) (SGTUconst [32] y)))
+(Rsh32x16 x y) => (SRA x ( CMOVZ <typ.UInt32> (ZeroExt16to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt16to32 y))))
+(Rsh32x8 x y) => (SRA x ( CMOVZ <typ.UInt32> (ZeroExt8to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt8to32 y))))
+
+(Rsh16x32 x y) => (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> y (MOVWconst [31]) (SGTUconst [32] y)))
+(Rsh16x16 x y) => (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> (ZeroExt16to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt16to32 y))))
+(Rsh16x8 x y) => (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> (ZeroExt8to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt8to32 y))))
+
+(Rsh8x32 x y) => (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> y (MOVWconst [31]) (SGTUconst [32] y)))
+(Rsh8x16 x y) => (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> (ZeroExt16to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt16to32 y))))
+(Rsh8x8 x y) => (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> (ZeroExt8to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt8to32 y))))
+
+// rotates
+(RotateLeft8 <t> x (MOVWconst [c])) => (Or8 (Lsh8x32 <t> x (MOVWconst [c&7])) (Rsh8Ux32 <t> x (MOVWconst [-c&7])))
+(RotateLeft16 <t> x (MOVWconst [c])) => (Or16 (Lsh16x32 <t> x (MOVWconst [c&15])) (Rsh16Ux32 <t> x (MOVWconst [-c&15])))
+(RotateLeft32 <t> x (MOVWconst [c])) => (Or32 (Lsh32x32 <t> x (MOVWconst [c&31])) (Rsh32Ux32 <t> x (MOVWconst [-c&31])))
+(RotateLeft64 <t> x (MOVWconst [c])) => (Or64 (Lsh64x32 <t> x (MOVWconst [c&63])) (Rsh64Ux32 <t> x (MOVWconst [-c&63])))
+
+// unary ops
+(Neg(32|16|8) ...) => (NEG ...)
+(Neg(32|64)F ...) => (NEG(F|D) ...)
+
+(Com(32|16|8) x) => (NORconst [0] x)
+
+(Sqrt ...) => (SQRTD ...)
+
+// TODO: optimize this case?
+(Ctz32NonZero ...) => (Ctz32 ...)
+
+// count trailing zero
+// 32 - CLZ(x&-x - 1)
+(Ctz32 <t> x) => (SUB (MOVWconst [32]) (CLZ <t> (SUBconst <t> [1] (AND <t> x (NEG <t> x)))))
+
+// bit length
+(BitLen32 <t> x) => (SUB (MOVWconst [32]) (CLZ <t> x))
+
+// boolean ops -- booleans are represented with 0=false, 1=true
+(AndB ...) => (AND ...)
+(OrB ...) => (OR ...)
+(EqB x y) => (XORconst [1] (XOR <typ.Bool> x y))
+(NeqB ...) => (XOR ...)
+(Not x) => (XORconst [1] x)
+
+// constants
+(Const(32|16|8) [val]) => (MOVWconst [int32(val)])
+(Const(32|64)F ...) => (MOV(F|D)const ...)
+(ConstNil) => (MOVWconst [0])
+(ConstBool [b]) => (MOVWconst [b2i32(b)])
+
+// truncations
+// Because we ignore high parts of registers, truncates are just copies.
+(Trunc16to8 ...) => (Copy ...)
+(Trunc32to8 ...) => (Copy ...)
+(Trunc32to16 ...) => (Copy ...)
+
+// Zero-/Sign-extensions
+(ZeroExt8to16 ...) => (MOVBUreg ...)
+(ZeroExt8to32 ...) => (MOVBUreg ...)
+(ZeroExt16to32 ...) => (MOVHUreg ...)
+
+(SignExt8to16 ...) => (MOVBreg ...)
+(SignExt8to32 ...) => (MOVBreg ...)
+(SignExt16to32 ...) => (MOVHreg ...)
+
+(Signmask x) => (SRAconst x [31])
+(Zeromask x) => (NEG (SGTU x (MOVWconst [0])))
+(Slicemask <t> x) => (SRAconst (NEG <t> x) [31])
+
+// float-int conversion
+(Cvt32to(32|64)F ...) => (MOVW(F|D) ...)
+(Cvt(32|64)Fto32 ...) => (TRUNC(F|D)W ...)
+(Cvt32Fto64F ...) => (MOVFD ...)
+(Cvt64Fto32F ...) => (MOVDF ...)
+
+(CvtBoolToUint8 ...) => (Copy ...)
+
+(Round(32|64)F ...) => (Copy ...)
+
+// comparisons
+(Eq8 x y) => (SGTUconst [1] (XOR (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Eq16 x y) => (SGTUconst [1] (XOR (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Eq32 x y) => (SGTUconst [1] (XOR x y))
+(EqPtr x y) => (SGTUconst [1] (XOR x y))
+(Eq(32|64)F x y) => (FPFlagTrue (CMPEQ(F|D) x y))
+
+(Neq8 x y) => (SGTU (XOR (ZeroExt8to32 x) (ZeroExt8to32 y)) (MOVWconst [0]))
+(Neq16 x y) => (SGTU (XOR (ZeroExt16to32 x) (ZeroExt16to32 y)) (MOVWconst [0]))
+(Neq32 x y) => (SGTU (XOR x y) (MOVWconst [0]))
+(NeqPtr x y) => (SGTU (XOR x y) (MOVWconst [0]))
+(Neq(32|64)F x y) => (FPFlagFalse (CMPEQ(F|D) x y))
+
+(Less8 x y) => (SGT (SignExt8to32 y) (SignExt8to32 x))
+(Less16 x y) => (SGT (SignExt16to32 y) (SignExt16to32 x))
+(Less32 x y) => (SGT y x)
+(Less(32|64)F x y) => (FPFlagTrue (CMPGT(F|D) y x)) // reverse operands to work around NaN
+
+(Less8U x y) => (SGTU (ZeroExt8to32 y) (ZeroExt8to32 x))
+(Less16U x y) => (SGTU (ZeroExt16to32 y) (ZeroExt16to32 x))
+(Less32U x y) => (SGTU y x)
+
+(Leq8 x y) => (XORconst [1] (SGT (SignExt8to32 x) (SignExt8to32 y)))
+(Leq16 x y) => (XORconst [1] (SGT (SignExt16to32 x) (SignExt16to32 y)))
+(Leq32 x y) => (XORconst [1] (SGT x y))
+(Leq(32|64)F x y) => (FPFlagTrue (CMPGE(F|D) y x)) // reverse operands to work around NaN
+
+(Leq8U x y) => (XORconst [1] (SGTU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Leq16U x y) => (XORconst [1] (SGTU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Leq32U x y) => (XORconst [1] (SGTU x y))
+
+(OffPtr [off] ptr:(SP)) => (MOVWaddr [int32(off)] ptr)
+(OffPtr [off] ptr) => (ADDconst [int32(off)] ptr)
+
+(Addr {sym} base) => (MOVWaddr {sym} base)
+(LocalAddr {sym} base _) => (MOVWaddr {sym} base)
+
+// loads
+(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
+(Load <t> ptr mem) && (is8BitInt(t) && isSigned(t)) => (MOVBload ptr mem)
+(Load <t> ptr mem) && (is8BitInt(t) && !isSigned(t)) => (MOVBUload ptr mem)
+(Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) => (MOVHload ptr mem)
+(Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) => (MOVHUload ptr mem)
+(Load <t> ptr mem) && (is32BitInt(t) || isPtr(t)) => (MOVWload ptr mem)
+(Load <t> ptr mem) && is32BitFloat(t) => (MOVFload ptr mem)
+(Load <t> ptr mem) && is64BitFloat(t) => (MOVDload ptr mem)
+
+// stores
+(Store {t} ptr val mem) && t.Size() == 1 => (MOVBstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 2 => (MOVHstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && !is32BitFloat(val.Type) => (MOVWstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && is32BitFloat(val.Type) => (MOVFstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 && is64BitFloat(val.Type) => (MOVDstore ptr val mem)
+
+// zero instructions
+(Zero [0] _ mem) => mem
+(Zero [1] ptr mem) => (MOVBstore ptr (MOVWconst [0]) mem)
+(Zero [2] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore ptr (MOVWconst [0]) mem)
+(Zero [2] ptr mem) =>
+ (MOVBstore [1] ptr (MOVWconst [0])
+ (MOVBstore [0] ptr (MOVWconst [0]) mem))
+(Zero [4] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore ptr (MOVWconst [0]) mem)
+(Zero [4] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [2] ptr (MOVWconst [0])
+ (MOVHstore [0] ptr (MOVWconst [0]) mem))
+(Zero [4] ptr mem) =>
+ (MOVBstore [3] ptr (MOVWconst [0])
+ (MOVBstore [2] ptr (MOVWconst [0])
+ (MOVBstore [1] ptr (MOVWconst [0])
+ (MOVBstore [0] ptr (MOVWconst [0]) mem))))
+(Zero [3] ptr mem) =>
+ (MOVBstore [2] ptr (MOVWconst [0])
+ (MOVBstore [1] ptr (MOVWconst [0])
+ (MOVBstore [0] ptr (MOVWconst [0]) mem)))
+(Zero [6] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [4] ptr (MOVWconst [0])
+ (MOVHstore [2] ptr (MOVWconst [0])
+ (MOVHstore [0] ptr (MOVWconst [0]) mem)))
+(Zero [8] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [4] ptr (MOVWconst [0])
+ (MOVWstore [0] ptr (MOVWconst [0]) mem))
+(Zero [12] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [8] ptr (MOVWconst [0])
+ (MOVWstore [4] ptr (MOVWconst [0])
+ (MOVWstore [0] ptr (MOVWconst [0]) mem)))
+(Zero [16] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [12] ptr (MOVWconst [0])
+ (MOVWstore [8] ptr (MOVWconst [0])
+ (MOVWstore [4] ptr (MOVWconst [0])
+ (MOVWstore [0] ptr (MOVWconst [0]) mem))))
+
+// large or unaligned zeroing uses a loop
+(Zero [s] {t} ptr mem)
+ && (s > 16 || t.Alignment()%4 != 0) =>
+ (LoweredZero [int32(t.Alignment())]
+ ptr
+ (ADDconst <ptr.Type> ptr [int32(s-moveSize(t.Alignment(), config))])
+ mem)
+
+// moves
+(Move [0] _ _ mem) => mem
+(Move [1] dst src mem) => (MOVBstore dst (MOVBUload src mem) mem)
+(Move [2] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore dst (MOVHUload src mem) mem)
+(Move [2] dst src mem) =>
+ (MOVBstore [1] dst (MOVBUload [1] src mem)
+ (MOVBstore dst (MOVBUload src mem) mem))
+(Move [4] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore dst (MOVWload src mem) mem)
+(Move [4] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [2] dst (MOVHUload [2] src mem)
+ (MOVHstore dst (MOVHUload src mem) mem))
+(Move [4] dst src mem) =>
+ (MOVBstore [3] dst (MOVBUload [3] src mem)
+ (MOVBstore [2] dst (MOVBUload [2] src mem)
+ (MOVBstore [1] dst (MOVBUload [1] src mem)
+ (MOVBstore dst (MOVBUload src mem) mem))))
+(Move [3] dst src mem) =>
+ (MOVBstore [2] dst (MOVBUload [2] src mem)
+ (MOVBstore [1] dst (MOVBUload [1] src mem)
+ (MOVBstore dst (MOVBUload src mem) mem)))
+(Move [8] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [4] dst (MOVWload [4] src mem)
+ (MOVWstore dst (MOVWload src mem) mem))
+(Move [8] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [6] dst (MOVHload [6] src mem)
+ (MOVHstore [4] dst (MOVHload [4] src mem)
+ (MOVHstore [2] dst (MOVHload [2] src mem)
+ (MOVHstore dst (MOVHload src mem) mem))))
+(Move [6] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [4] dst (MOVHload [4] src mem)
+ (MOVHstore [2] dst (MOVHload [2] src mem)
+ (MOVHstore dst (MOVHload src mem) mem)))
+(Move [12] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [8] dst (MOVWload [8] src mem)
+ (MOVWstore [4] dst (MOVWload [4] src mem)
+ (MOVWstore dst (MOVWload src mem) mem)))
+(Move [16] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [12] dst (MOVWload [12] src mem)
+ (MOVWstore [8] dst (MOVWload [8] src mem)
+ (MOVWstore [4] dst (MOVWload [4] src mem)
+ (MOVWstore dst (MOVWload src mem) mem))))
+
+
+// large or unaligned move uses a loop
+(Move [s] {t} dst src mem)
+ && (s > 16 && logLargeCopy(v, s) || t.Alignment()%4 != 0) =>
+ (LoweredMove [int32(t.Alignment())]
+ dst
+ src
+ (ADDconst <src.Type> src [int32(s-moveSize(t.Alignment(), config))])
+ mem)
+
+// calls
+(StaticCall ...) => (CALLstatic ...)
+(ClosureCall ...) => (CALLclosure ...)
+(InterCall ...) => (CALLinter ...)
+
+// atomic intrinsics
+(AtomicLoad(8|32) ...) => (LoweredAtomicLoad(8|32) ...)
+(AtomicLoadPtr ...) => (LoweredAtomicLoad32 ...)
+
+(AtomicStore(8|32) ...) => (LoweredAtomicStore(8|32) ...)
+(AtomicStorePtrNoWB ...) => (LoweredAtomicStore32 ...)
+
+(AtomicExchange32 ...) => (LoweredAtomicExchange ...)
+(AtomicAdd32 ...) => (LoweredAtomicAdd ...)
+
+(AtomicCompareAndSwap32 ...) => (LoweredAtomicCas ...)
+
+// AtomicOr8(ptr,val) => LoweredAtomicOr(ptr&^3,uint32(val) << ((ptr & 3) * 8))
+(AtomicOr8 ptr val mem) && !config.BigEndian =>
+ (LoweredAtomicOr (AND <typ.UInt32Ptr> (MOVWconst [^3]) ptr)
+ (SLL <typ.UInt32> (ZeroExt8to32 val)
+ (SLLconst <typ.UInt32> [3]
+ (ANDconst <typ.UInt32> [3] ptr))) mem)
+
+// AtomicAnd8(ptr,val) => LoweredAtomicAnd(ptr&^3,(uint32(val) << ((ptr & 3) * 8)) | ^(uint32(0xFF) << ((ptr & 3) * 8))))
+(AtomicAnd8 ptr val mem) && !config.BigEndian =>
+ (LoweredAtomicAnd (AND <typ.UInt32Ptr> (MOVWconst [^3]) ptr)
+ (OR <typ.UInt32> (SLL <typ.UInt32> (ZeroExt8to32 val)
+ (SLLconst <typ.UInt32> [3]
+ (ANDconst <typ.UInt32> [3] ptr)))
+ (NORconst [0] <typ.UInt32> (SLL <typ.UInt32>
+ (MOVWconst [0xff]) (SLLconst <typ.UInt32> [3]
+ (ANDconst <typ.UInt32> [3] ptr))))) mem)
+
+// AtomicOr8(ptr,val) => LoweredAtomicOr(ptr&^3,uint32(val) << (((ptr^3) & 3) * 8))
+(AtomicOr8 ptr val mem) && config.BigEndian =>
+ (LoweredAtomicOr (AND <typ.UInt32Ptr> (MOVWconst [^3]) ptr)
+ (SLL <typ.UInt32> (ZeroExt8to32 val)
+ (SLLconst <typ.UInt32> [3]
+ (ANDconst <typ.UInt32> [3]
+ (XORconst <typ.UInt32> [3] ptr)))) mem)
+
+// AtomicAnd8(ptr,val) => LoweredAtomicAnd(ptr&^3,(uint32(val) << (((ptr^3) & 3) * 8)) | ^(uint32(0xFF) << (((ptr^3) & 3) * 8))))
+(AtomicAnd8 ptr val mem) && config.BigEndian =>
+ (LoweredAtomicAnd (AND <typ.UInt32Ptr> (MOVWconst [^3]) ptr)
+ (OR <typ.UInt32> (SLL <typ.UInt32> (ZeroExt8to32 val)
+ (SLLconst <typ.UInt32> [3]
+ (ANDconst <typ.UInt32> [3]
+ (XORconst <typ.UInt32> [3] ptr))))
+ (NORconst [0] <typ.UInt32> (SLL <typ.UInt32>
+ (MOVWconst [0xff]) (SLLconst <typ.UInt32> [3]
+ (ANDconst <typ.UInt32> [3]
+ (XORconst <typ.UInt32> [3] ptr)))))) mem)
+
+(AtomicAnd32 ...) => (LoweredAtomicAnd ...)
+(AtomicOr32 ...) => (LoweredAtomicOr ...)
+
+
+// checks
+(NilCheck ...) => (LoweredNilCheck ...)
+(IsNonNil ptr) => (SGTU ptr (MOVWconst [0]))
+(IsInBounds idx len) => (SGTU len idx)
+(IsSliceInBounds idx len) => (XORconst [1] (SGTU idx len))
+
+// pseudo-ops
+(GetClosurePtr ...) => (LoweredGetClosurePtr ...)
+(GetCallerSP ...) => (LoweredGetCallerSP ...)
+(GetCallerPC ...) => (LoweredGetCallerPC ...)
+
+(If cond yes no) => (NE cond yes no)
+
+// Write barrier.
+(WB ...) => (LoweredWB ...)
+
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
+
+(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 0 => (LoweredPanicExtendA [kind] hi lo y mem)
+(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 1 => (LoweredPanicExtendB [kind] hi lo y mem)
+(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 2 => (LoweredPanicExtendC [kind] hi lo y mem)
+
+// Optimizations
+
+// Absorb boolean tests into block
+(NE (FPFlagTrue cmp) yes no) => (FPT cmp yes no)
+(NE (FPFlagFalse cmp) yes no) => (FPF cmp yes no)
+(EQ (FPFlagTrue cmp) yes no) => (FPF cmp yes no)
+(EQ (FPFlagFalse cmp) yes no) => (FPT cmp yes no)
+(NE (XORconst [1] cmp:(SGT _ _)) yes no) => (EQ cmp yes no)
+(NE (XORconst [1] cmp:(SGTU _ _)) yes no) => (EQ cmp yes no)
+(NE (XORconst [1] cmp:(SGTconst _)) yes no) => (EQ cmp yes no)
+(NE (XORconst [1] cmp:(SGTUconst _)) yes no) => (EQ cmp yes no)
+(NE (XORconst [1] cmp:(SGTzero _)) yes no) => (EQ cmp yes no)
+(NE (XORconst [1] cmp:(SGTUzero _)) yes no) => (EQ cmp yes no)
+(EQ (XORconst [1] cmp:(SGT _ _)) yes no) => (NE cmp yes no)
+(EQ (XORconst [1] cmp:(SGTU _ _)) yes no) => (NE cmp yes no)
+(EQ (XORconst [1] cmp:(SGTconst _)) yes no) => (NE cmp yes no)
+(EQ (XORconst [1] cmp:(SGTUconst _)) yes no) => (NE cmp yes no)
+(EQ (XORconst [1] cmp:(SGTzero _)) yes no) => (NE cmp yes no)
+(EQ (XORconst [1] cmp:(SGTUzero _)) yes no) => (NE cmp yes no)
+(NE (SGTUconst [1] x) yes no) => (EQ x yes no)
+(EQ (SGTUconst [1] x) yes no) => (NE x yes no)
+(NE (SGTUzero x) yes no) => (NE x yes no)
+(EQ (SGTUzero x) yes no) => (EQ x yes no)
+(NE (SGTconst [0] x) yes no) => (LTZ x yes no)
+(EQ (SGTconst [0] x) yes no) => (GEZ x yes no)
+(NE (SGTzero x) yes no) => (GTZ x yes no)
+(EQ (SGTzero x) yes no) => (LEZ x yes no)
+
+// fold offset into address
+(ADDconst [off1] (MOVWaddr [off2] {sym} ptr)) => (MOVWaddr [off1+off2] {sym} ptr)
+
+// fold address into load/store
+(MOVBload [off1] {sym} x:(ADDconst [off2] ptr) mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVBload [off1+off2] {sym} ptr mem)
+(MOVBUload [off1] {sym} x:(ADDconst [off2] ptr) mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVBUload [off1+off2] {sym} ptr mem)
+(MOVHload [off1] {sym} x:(ADDconst [off2] ptr) mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVHload [off1+off2] {sym} ptr mem)
+(MOVHUload [off1] {sym} x:(ADDconst [off2] ptr) mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVHUload [off1+off2] {sym} ptr mem)
+(MOVWload [off1] {sym} x:(ADDconst [off2] ptr) mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVWload [off1+off2] {sym} ptr mem)
+(MOVFload [off1] {sym} x:(ADDconst [off2] ptr) mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVFload [off1+off2] {sym} ptr mem)
+(MOVDload [off1] {sym} x:(ADDconst [off2] ptr) mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVDload [off1+off2] {sym} ptr mem)
+
+(MOVBstore [off1] {sym} x:(ADDconst [off2] ptr) val mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVBstore [off1+off2] {sym} ptr val mem)
+(MOVHstore [off1] {sym} x:(ADDconst [off2] ptr) val mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVHstore [off1+off2] {sym} ptr val mem)
+(MOVWstore [off1] {sym} x:(ADDconst [off2] ptr) val mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVWstore [off1+off2] {sym} ptr val mem)
+(MOVFstore [off1] {sym} x:(ADDconst [off2] ptr) val mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVFstore [off1+off2] {sym} ptr val mem)
+(MOVDstore [off1] {sym} x:(ADDconst [off2] ptr) val mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVDstore [off1+off2] {sym} ptr val mem)
+
+(MOVBstorezero [off1] {sym} x:(ADDconst [off2] ptr) mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVBstorezero [off1+off2] {sym} ptr mem)
+(MOVHstorezero [off1] {sym} x:(ADDconst [off2] ptr) mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVHstorezero [off1+off2] {sym} ptr mem)
+(MOVWstorezero [off1] {sym} x:(ADDconst [off2] ptr) mem) && (is16Bit(int64(off1+off2)) || x.Uses == 1) => (MOVWstorezero [off1+off2] {sym} ptr mem)
+
+(MOVBload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVBUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVFload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVFload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVDload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+
+(MOVBstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) =>
+ (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVHstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) =>
+ (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVWstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) =>
+ (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVFstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) =>
+ (MOVFstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVDstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) =>
+ (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVBstorezero [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHstorezero [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWstorezero [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) =>
+ (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+
+// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
+(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVBreg x)
+(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVBUreg x)
+(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVHreg x)
+(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => (MOVHUreg x)
+(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => x
+(MOVFload [off] {sym} ptr (MOVFstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => x
+(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) => x
+
+// store zero
+(MOVBstore [off] {sym} ptr (MOVWconst [0]) mem) => (MOVBstorezero [off] {sym} ptr mem)
+(MOVHstore [off] {sym} ptr (MOVWconst [0]) mem) => (MOVHstorezero [off] {sym} ptr mem)
+(MOVWstore [off] {sym} ptr (MOVWconst [0]) mem) => (MOVWstorezero [off] {sym} ptr mem)
+
+// don't extend after proper load
+(MOVBreg x:(MOVBload _ _)) => (MOVWreg x)
+(MOVBUreg x:(MOVBUload _ _)) => (MOVWreg x)
+(MOVHreg x:(MOVBload _ _)) => (MOVWreg x)
+(MOVHreg x:(MOVBUload _ _)) => (MOVWreg x)
+(MOVHreg x:(MOVHload _ _)) => (MOVWreg x)
+(MOVHUreg x:(MOVBUload _ _)) => (MOVWreg x)
+(MOVHUreg x:(MOVHUload _ _)) => (MOVWreg x)
+
+// fold double extensions
+(MOVBreg x:(MOVBreg _)) => (MOVWreg x)
+(MOVBUreg x:(MOVBUreg _)) => (MOVWreg x)
+(MOVHreg x:(MOVBreg _)) => (MOVWreg x)
+(MOVHreg x:(MOVBUreg _)) => (MOVWreg x)
+(MOVHreg x:(MOVHreg _)) => (MOVWreg x)
+(MOVHUreg x:(MOVBUreg _)) => (MOVWreg x)
+(MOVHUreg x:(MOVHUreg _)) => (MOVWreg 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.
+// Make sure we don't combine these ops if the load has another use.
+// This prevents a single load from being split into multiple loads
+// which then might return different values. See test/atomicload.go.
+(MOVBreg <t> x:(MOVBUload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBload <t> [off] {sym} ptr mem)
+(MOVBUreg <t> x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBUload <t> [off] {sym} ptr mem)
+(MOVHreg <t> x:(MOVHUload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVHload <t> [off] {sym} ptr mem)
+(MOVHUreg <t> x:(MOVHload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVHUload <t> [off] {sym} ptr mem)
+
+// fold extensions and ANDs together
+(MOVBUreg (ANDconst [c] x)) => (ANDconst [c&0xff] x)
+(MOVHUreg (ANDconst [c] x)) => (ANDconst [c&0xffff] x)
+(MOVBreg (ANDconst [c] x)) && c & 0x80 == 0 => (ANDconst [c&0x7f] x)
+(MOVHreg (ANDconst [c] x)) && c & 0x8000 == 0 => (ANDconst [c&0x7fff] x)
+
+// don't extend before store
+(MOVBstore [off] {sym} ptr (MOVBreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVBUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVHreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVHUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVWreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVWreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOVWreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
+
+// if a register move has only 1 use, just use the same register without emitting instruction
+// MOVWnop doesn't emit instruction, only for ensuring the type.
+(MOVWreg x) && x.Uses == 1 => (MOVWnop x)
+
+// fold constant into arithmatic ops
+(ADD x (MOVWconst [c])) => (ADDconst [c] x)
+(SUB x (MOVWconst [c])) => (SUBconst [c] x)
+(AND x (MOVWconst [c])) => (ANDconst [c] x)
+(OR x (MOVWconst [c])) => (ORconst [c] x)
+(XOR x (MOVWconst [c])) => (XORconst [c] x)
+(NOR x (MOVWconst [c])) => (NORconst [c] x)
+
+(SLL x (MOVWconst [c])) => (SLLconst x [c&31])
+(SRL x (MOVWconst [c])) => (SRLconst x [c&31])
+(SRA x (MOVWconst [c])) => (SRAconst x [c&31])
+
+(SGT (MOVWconst [c]) x) => (SGTconst [c] x)
+(SGTU (MOVWconst [c]) x) => (SGTUconst [c] x)
+(SGT x (MOVWconst [0])) => (SGTzero x)
+(SGTU x (MOVWconst [0])) => (SGTUzero x)
+
+// mul with constant
+(Select1 (MULTU (MOVWconst [0]) _ )) => (MOVWconst [0])
+(Select0 (MULTU (MOVWconst [0]) _ )) => (MOVWconst [0])
+(Select1 (MULTU (MOVWconst [1]) x )) => x
+(Select0 (MULTU (MOVWconst [1]) _ )) => (MOVWconst [0])
+(Select1 (MULTU (MOVWconst [-1]) x )) => (NEG <x.Type> x)
+(Select0 (MULTU (MOVWconst [-1]) x )) => (CMOVZ (ADDconst <x.Type> [-1] x) (MOVWconst [0]) x)
+(Select1 (MULTU (MOVWconst [c]) x )) && isPowerOfTwo64(int64(uint32(c))) => (SLLconst [int32(log2uint32(int64(c)))] x)
+(Select0 (MULTU (MOVWconst [c]) x )) && isPowerOfTwo64(int64(uint32(c))) => (SRLconst [int32(32-log2uint32(int64(c)))] x)
+
+(MUL (MOVWconst [0]) _ ) => (MOVWconst [0])
+(MUL (MOVWconst [1]) x ) => x
+(MUL (MOVWconst [-1]) x ) => (NEG x)
+(MUL (MOVWconst [c]) x ) && isPowerOfTwo64(int64(uint32(c))) => (SLLconst [int32(log2uint32(int64(c)))] x)
+
+// generic simplifications
+(ADD x (NEG y)) => (SUB x y)
+(SUB x x) => (MOVWconst [0])
+(SUB (MOVWconst [0]) x) => (NEG x)
+(AND x x) => x
+(OR x x) => x
+(XOR x x) => (MOVWconst [0])
+
+// miscellaneous patterns generated by dec64
+(AND (SGTUconst [1] x) (SGTUconst [1] y)) => (SGTUconst [1] (OR <x.Type> x y))
+(OR (SGTUzero x) (SGTUzero y)) => (SGTUzero (OR <x.Type> x y))
+
+// remove redundant *const ops
+(ADDconst [0] x) => x
+(SUBconst [0] x) => x
+(ANDconst [0] _) => (MOVWconst [0])
+(ANDconst [-1] x) => x
+(ORconst [0] x) => x
+(ORconst [-1] _) => (MOVWconst [-1])
+(XORconst [0] x) => x
+(XORconst [-1] x) => (NORconst [0] x)
+
+// generic constant folding
+(ADDconst [c] (MOVWconst [d])) => (MOVWconst [int32(c+d)])
+(ADDconst [c] (ADDconst [d] x)) => (ADDconst [c+d] x)
+(ADDconst [c] (SUBconst [d] x)) => (ADDconst [c-d] x)
+(SUBconst [c] (MOVWconst [d])) => (MOVWconst [d-c])
+(SUBconst [c] (SUBconst [d] x)) => (ADDconst [-c-d] x)
+(SUBconst [c] (ADDconst [d] x)) => (ADDconst [-c+d] x)
+(SLLconst [c] (MOVWconst [d])) => (MOVWconst [d<<uint32(c)])
+(SRLconst [c] (MOVWconst [d])) => (MOVWconst [int32(uint32(d)>>uint32(c))])
+(SRAconst [c] (MOVWconst [d])) => (MOVWconst [d>>uint32(c)])
+(MUL (MOVWconst [c]) (MOVWconst [d])) => (MOVWconst [c*d])
+(Select1 (MULTU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)*uint32(d))])
+(Select0 (MULTU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32((int64(uint32(c))*int64(uint32(d)))>>32)])
+(Select1 (DIV (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [c/d])
+(Select1 (DIVU (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)/uint32(d))])
+(Select0 (DIV (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [c%d])
+(Select0 (DIVU (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)%uint32(d))])
+(ANDconst [c] (MOVWconst [d])) => (MOVWconst [c&d])
+(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
+(ORconst [c] (MOVWconst [d])) => (MOVWconst [c|d])
+(ORconst [c] (ORconst [d] x)) => (ORconst [c|d] x)
+(XORconst [c] (MOVWconst [d])) => (MOVWconst [c^d])
+(XORconst [c] (XORconst [d] x)) => (XORconst [c^d] x)
+(NORconst [c] (MOVWconst [d])) => (MOVWconst [^(c|d)])
+(NEG (MOVWconst [c])) => (MOVWconst [-c])
+(MOVBreg (MOVWconst [c])) => (MOVWconst [int32(int8(c))])
+(MOVBUreg (MOVWconst [c])) => (MOVWconst [int32(uint8(c))])
+(MOVHreg (MOVWconst [c])) => (MOVWconst [int32(int16(c))])
+(MOVHUreg (MOVWconst [c])) => (MOVWconst [int32(uint16(c))])
+(MOVWreg (MOVWconst [c])) => (MOVWconst [c])
+
+// constant comparisons
+(SGTconst [c] (MOVWconst [d])) && c > d => (MOVWconst [1])
+(SGTconst [c] (MOVWconst [d])) && c <= d => (MOVWconst [0])
+(SGTUconst [c] (MOVWconst [d])) && uint32(c) > uint32(d) => (MOVWconst [1])
+(SGTUconst [c] (MOVWconst [d])) && uint32(c) <= uint32(d) => (MOVWconst [0])
+(SGTzero (MOVWconst [d])) && d > 0 => (MOVWconst [1])
+(SGTzero (MOVWconst [d])) && d <= 0 => (MOVWconst [0])
+(SGTUzero (MOVWconst [d])) && d != 0 => (MOVWconst [1])
+(SGTUzero (MOVWconst [d])) && d == 0 => (MOVWconst [0])
+
+// other known comparisons
+(SGTconst [c] (MOVBreg _)) && 0x7f < c => (MOVWconst [1])
+(SGTconst [c] (MOVBreg _)) && c <= -0x80 => (MOVWconst [0])
+(SGTconst [c] (MOVBUreg _)) && 0xff < c => (MOVWconst [1])
+(SGTconst [c] (MOVBUreg _)) && c < 0 => (MOVWconst [0])
+(SGTUconst [c] (MOVBUreg _)) && 0xff < uint32(c) => (MOVWconst [1])
+(SGTconst [c] (MOVHreg _)) && 0x7fff < c => (MOVWconst [1])
+(SGTconst [c] (MOVHreg _)) && c <= -0x8000 => (MOVWconst [0])
+(SGTconst [c] (MOVHUreg _)) && 0xffff < c => (MOVWconst [1])
+(SGTconst [c] (MOVHUreg _)) && c < 0 => (MOVWconst [0])
+(SGTUconst [c] (MOVHUreg _)) && 0xffff < uint32(c) => (MOVWconst [1])
+(SGTconst [c] (ANDconst [m] _)) && 0 <= m && m < c => (MOVWconst [1])
+(SGTUconst [c] (ANDconst [m] _)) && uint32(m) < uint32(c) => (MOVWconst [1])
+(SGTconst [c] (SRLconst _ [d])) && 0 <= c && uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c) => (MOVWconst [1])
+(SGTUconst [c] (SRLconst _ [d])) && uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c) => (MOVWconst [1])
+
+// absorb constants into branches
+(EQ (MOVWconst [0]) yes no) => (First yes no)
+(EQ (MOVWconst [c]) yes no) && c != 0 => (First no yes)
+(NE (MOVWconst [0]) yes no) => (First no yes)
+(NE (MOVWconst [c]) yes no) && c != 0 => (First yes no)
+(LTZ (MOVWconst [c]) yes no) && c < 0 => (First yes no)
+(LTZ (MOVWconst [c]) yes no) && c >= 0 => (First no yes)
+(LEZ (MOVWconst [c]) yes no) && c <= 0 => (First yes no)
+(LEZ (MOVWconst [c]) yes no) && c > 0 => (First no yes)
+(GTZ (MOVWconst [c]) yes no) && c > 0 => (First yes no)
+(GTZ (MOVWconst [c]) yes no) && c <= 0 => (First no yes)
+(GEZ (MOVWconst [c]) yes no) && c >= 0 => (First yes no)
+(GEZ (MOVWconst [c]) yes no) && c < 0 => (First no yes)
+
+// conditional move
+(CMOVZ _ f (MOVWconst [0])) => f
+(CMOVZ a _ (MOVWconst [c])) && c!=0 => a
+(CMOVZzero _ (MOVWconst [0])) => (MOVWconst [0])
+(CMOVZzero a (MOVWconst [c])) && c!=0 => a
+(CMOVZ a (MOVWconst [0]) c) => (CMOVZzero a c)
+
+// atomic
+(LoweredAtomicStore32 ptr (MOVWconst [0]) mem) => (LoweredAtomicStorezero ptr mem)
+(LoweredAtomicAdd ptr (MOVWconst [c]) mem) && is16Bit(int64(c)) => (LoweredAtomicAddconst [c] ptr mem)
+
diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64.rules b/src/cmd/compile/internal/ssa/gen/MIPS64.rules
new file mode 100644
index 0000000..088c9b1
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/MIPS64.rules
@@ -0,0 +1,678 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+(Add(Ptr|64|32|16|8) ...) => (ADDV ...)
+(Add(32|64)F ...) => (ADD(F|D) ...)
+
+(Sub(Ptr|64|32|16|8) ...) => (SUBV ...)
+(Sub(32|64)F ...) => (SUB(F|D) ...)
+
+(Mul(64|32|16|8) x y) => (Select1 (MULVU x y))
+(Mul(32|64)F ...) => (MUL(F|D) ...)
+(Mul64uhilo ...) => (MULVU ...)
+(Select0 (Mul64uover x y)) => (Select1 <typ.UInt64> (MULVU x y))
+(Select1 (Mul64uover x y)) => (SGTU <typ.Bool> (Select0 <typ.UInt64> (MULVU x y)) (MOVVconst <typ.UInt64> [0]))
+
+(Hmul64 x y) => (Select0 (MULV x y))
+(Hmul64u x y) => (Select0 (MULVU x y))
+(Hmul32 x y) => (SRAVconst (Select1 <typ.Int64> (MULV (SignExt32to64 x) (SignExt32to64 y))) [32])
+(Hmul32u x y) => (SRLVconst (Select1 <typ.UInt64> (MULVU (ZeroExt32to64 x) (ZeroExt32to64 y))) [32])
+
+(Div64 x y) => (Select1 (DIVV x y))
+(Div64u x y) => (Select1 (DIVVU x y))
+(Div32 x y) => (Select1 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
+(Div32u x y) => (Select1 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
+(Div16 x y) => (Select1 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
+(Div16u x y) => (Select1 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
+(Div8 x y) => (Select1 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
+(Div8u x y) => (Select1 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
+(Div(32|64)F ...) => (DIV(F|D) ...)
+
+(Mod64 x y) => (Select0 (DIVV x y))
+(Mod64u x y) => (Select0 (DIVVU x y))
+(Mod32 x y) => (Select0 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
+(Mod32u x y) => (Select0 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
+(Mod16 x y) => (Select0 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
+(Mod16u x y) => (Select0 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
+(Mod8 x y) => (Select0 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
+(Mod8u x y) => (Select0 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
+
+// (x + y) / 2 with x>=y => (x - y) / 2 + y
+(Avg64u <t> x y) => (ADDV (SRLVconst <t> (SUBV <t> x y) [1]) y)
+
+(And(64|32|16|8) ...) => (AND ...)
+(Or(64|32|16|8) ...) => (OR ...)
+(Xor(64|32|16|8) ...) => (XOR ...)
+
+// shifts
+// hardware instruction uses only the low 6 bits of the shift
+// we compare to 64 to ensure Go semantics for large shifts
+(Lsh64x64 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
+(Lsh64x32 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
+(Lsh64x16 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
+(Lsh64x8 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
+
+(Lsh32x64 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
+(Lsh32x32 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
+(Lsh32x16 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
+(Lsh32x8 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
+
+(Lsh16x64 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
+(Lsh16x32 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
+(Lsh16x16 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
+(Lsh16x8 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
+
+(Lsh8x64 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
+(Lsh8x32 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
+(Lsh8x16 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
+(Lsh8x8 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
+
+(Rsh64Ux64 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> x y))
+(Rsh64Ux32 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> x (ZeroExt32to64 y)))
+(Rsh64Ux16 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> x (ZeroExt16to64 y)))
+(Rsh64Ux8 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> x (ZeroExt8to64 y)))
+
+(Rsh32Ux64 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt32to64 x) y))
+(Rsh32Ux32 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt32to64 y)))
+(Rsh32Ux16 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt16to64 y)))
+(Rsh32Ux8 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt8to64 y)))
+
+(Rsh16Ux64 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt16to64 x) y))
+(Rsh16Ux32 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt32to64 y)))
+(Rsh16Ux16 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt16to64 y)))
+(Rsh16Ux8 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt8to64 y)))
+
+(Rsh8Ux64 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt8to64 x) y))
+(Rsh8Ux32 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt32to64 y)))
+(Rsh8Ux16 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt16to64 y)))
+(Rsh8Ux8 <t> x y) => (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt8to64 y)))
+
+(Rsh64x64 <t> x y) => (SRAV x (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
+(Rsh64x32 <t> x y) => (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
+(Rsh64x16 <t> x y) => (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
+(Rsh64x8 <t> x y) => (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
+
+(Rsh32x64 <t> x y) => (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
+(Rsh32x32 <t> x y) => (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
+(Rsh32x16 <t> x y) => (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
+(Rsh32x8 <t> x y) => (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
+
+(Rsh16x64 <t> x y) => (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
+(Rsh16x32 <t> x y) => (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
+(Rsh16x16 <t> x y) => (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
+(Rsh16x8 <t> x y) => (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
+
+(Rsh8x64 <t> x y) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
+(Rsh8x32 <t> x y) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
+(Rsh8x16 <t> x y) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
+(Rsh8x8 <t> x y) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
+
+// rotates
+(RotateLeft8 <t> x (MOVVconst [c])) => (Or8 (Lsh8x64 <t> x (MOVVconst [c&7])) (Rsh8Ux64 <t> x (MOVVconst [-c&7])))
+(RotateLeft16 <t> x (MOVVconst [c])) => (Or16 (Lsh16x64 <t> x (MOVVconst [c&15])) (Rsh16Ux64 <t> x (MOVVconst [-c&15])))
+(RotateLeft32 <t> x (MOVVconst [c])) => (Or32 (Lsh32x64 <t> x (MOVVconst [c&31])) (Rsh32Ux64 <t> x (MOVVconst [-c&31])))
+(RotateLeft64 <t> x (MOVVconst [c])) => (Or64 (Lsh64x64 <t> x (MOVVconst [c&63])) (Rsh64Ux64 <t> x (MOVVconst [-c&63])))
+
+// unary ops
+(Neg(64|32|16|8) ...) => (NEGV ...)
+(Neg(32|64)F ...) => (NEG(F|D) ...)
+
+(Com(64|32|16|8) x) => (NOR (MOVVconst [0]) x)
+
+(Sqrt ...) => (SQRTD ...)
+
+// boolean ops -- booleans are represented with 0=false, 1=true
+(AndB ...) => (AND ...)
+(OrB ...) => (OR ...)
+(EqB x y) => (XOR (MOVVconst [1]) (XOR <typ.Bool> x y))
+(NeqB ...) => (XOR ...)
+(Not x) => (XORconst [1] x)
+
+// constants
+(Const(64|32|16|8) [val]) => (MOVVconst [int64(val)])
+(Const(32|64)F [val]) => (MOV(F|D)const [float64(val)])
+(ConstNil) => (MOVVconst [0])
+(ConstBool [b]) => (MOVVconst [int64(b2i(b))])
+
+(Slicemask <t> x) => (SRAVconst (NEGV <t> x) [63])
+
+// truncations
+// Because we ignore high parts of registers, truncates are just copies.
+(Trunc16to8 ...) => (Copy ...)
+(Trunc32to8 ...) => (Copy ...)
+(Trunc32to16 ...) => (Copy ...)
+(Trunc64to8 ...) => (Copy ...)
+(Trunc64to16 ...) => (Copy ...)
+(Trunc64to32 ...) => (Copy ...)
+
+// Zero-/Sign-extensions
+(ZeroExt8to16 ...) => (MOVBUreg ...)
+(ZeroExt8to32 ...) => (MOVBUreg ...)
+(ZeroExt16to32 ...) => (MOVHUreg ...)
+(ZeroExt8to64 ...) => (MOVBUreg ...)
+(ZeroExt16to64 ...) => (MOVHUreg ...)
+(ZeroExt32to64 ...) => (MOVWUreg ...)
+
+(SignExt8to16 ...) => (MOVBreg ...)
+(SignExt8to32 ...) => (MOVBreg ...)
+(SignExt16to32 ...) => (MOVHreg ...)
+(SignExt8to64 ...) => (MOVBreg ...)
+(SignExt16to64 ...) => (MOVHreg ...)
+(SignExt32to64 ...) => (MOVWreg ...)
+
+// float <=> int conversion
+(Cvt32to32F ...) => (MOVWF ...)
+(Cvt32to64F ...) => (MOVWD ...)
+(Cvt64to32F ...) => (MOVVF ...)
+(Cvt64to64F ...) => (MOVVD ...)
+(Cvt32Fto32 ...) => (TRUNCFW ...)
+(Cvt64Fto32 ...) => (TRUNCDW ...)
+(Cvt32Fto64 ...) => (TRUNCFV ...)
+(Cvt64Fto64 ...) => (TRUNCDV ...)
+(Cvt32Fto64F ...) => (MOVFD ...)
+(Cvt64Fto32F ...) => (MOVDF ...)
+
+(CvtBoolToUint8 ...) => (Copy ...)
+
+(Round(32|64)F ...) => (Copy ...)
+
+// comparisons
+(Eq8 x y) => (SGTU (MOVVconst [1]) (XOR (ZeroExt8to64 x) (ZeroExt8to64 y)))
+(Eq16 x y) => (SGTU (MOVVconst [1]) (XOR (ZeroExt16to64 x) (ZeroExt16to64 y)))
+(Eq32 x y) => (SGTU (MOVVconst [1]) (XOR (ZeroExt32to64 x) (ZeroExt32to64 y)))
+(Eq64 x y) => (SGTU (MOVVconst [1]) (XOR x y))
+(EqPtr x y) => (SGTU (MOVVconst [1]) (XOR x y))
+(Eq(32|64)F x y) => (FPFlagTrue (CMPEQ(F|D) x y))
+
+(Neq8 x y) => (SGTU (XOR (ZeroExt8to64 x) (ZeroExt8to64 y)) (MOVVconst [0]))
+(Neq16 x y) => (SGTU (XOR (ZeroExt16to32 x) (ZeroExt16to64 y)) (MOVVconst [0]))
+(Neq32 x y) => (SGTU (XOR (ZeroExt32to64 x) (ZeroExt32to64 y)) (MOVVconst [0]))
+(Neq64 x y) => (SGTU (XOR x y) (MOVVconst [0]))
+(NeqPtr x y) => (SGTU (XOR x y) (MOVVconst [0]))
+(Neq(32|64)F x y) => (FPFlagFalse (CMPEQ(F|D) x y))
+
+(Less8 x y) => (SGT (SignExt8to64 y) (SignExt8to64 x))
+(Less16 x y) => (SGT (SignExt16to64 y) (SignExt16to64 x))
+(Less32 x y) => (SGT (SignExt32to64 y) (SignExt32to64 x))
+(Less64 x y) => (SGT y x)
+(Less(32|64)F x y) => (FPFlagTrue (CMPGT(F|D) y x)) // reverse operands to work around NaN
+
+(Less8U x y) => (SGTU (ZeroExt8to64 y) (ZeroExt8to64 x))
+(Less16U x y) => (SGTU (ZeroExt16to64 y) (ZeroExt16to64 x))
+(Less32U x y) => (SGTU (ZeroExt32to64 y) (ZeroExt32to64 x))
+(Less64U x y) => (SGTU y x)
+
+(Leq8 x y) => (XOR (MOVVconst [1]) (SGT (SignExt8to64 x) (SignExt8to64 y)))
+(Leq16 x y) => (XOR (MOVVconst [1]) (SGT (SignExt16to64 x) (SignExt16to64 y)))
+(Leq32 x y) => (XOR (MOVVconst [1]) (SGT (SignExt32to64 x) (SignExt32to64 y)))
+(Leq64 x y) => (XOR (MOVVconst [1]) (SGT x y))
+(Leq(32|64)F x y) => (FPFlagTrue (CMPGE(F|D) y x)) // reverse operands to work around NaN
+
+(Leq8U x y) => (XOR (MOVVconst [1]) (SGTU (ZeroExt8to64 x) (ZeroExt8to64 y)))
+(Leq16U x y) => (XOR (MOVVconst [1]) (SGTU (ZeroExt16to64 x) (ZeroExt16to64 y)))
+(Leq32U x y) => (XOR (MOVVconst [1]) (SGTU (ZeroExt32to64 x) (ZeroExt32to64 y)))
+(Leq64U x y) => (XOR (MOVVconst [1]) (SGTU x y))
+
+(OffPtr [off] ptr:(SP)) && is32Bit(off) => (MOVVaddr [int32(off)] ptr)
+(OffPtr [off] ptr) => (ADDVconst [off] ptr)
+
+(Addr {sym} base) => (MOVVaddr {sym} base)
+(LocalAddr {sym} base _) => (MOVVaddr {sym} base)
+
+// loads
+(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
+(Load <t> ptr mem) && (is8BitInt(t) && isSigned(t)) => (MOVBload ptr mem)
+(Load <t> ptr mem) && (is8BitInt(t) && !isSigned(t)) => (MOVBUload ptr mem)
+(Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) => (MOVHload ptr mem)
+(Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) => (MOVHUload ptr mem)
+(Load <t> ptr mem) && (is32BitInt(t) && isSigned(t)) => (MOVWload ptr mem)
+(Load <t> ptr mem) && (is32BitInt(t) && !isSigned(t)) => (MOVWUload ptr mem)
+(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) => (MOVVload ptr mem)
+(Load <t> ptr mem) && is32BitFloat(t) => (MOVFload ptr mem)
+(Load <t> ptr mem) && is64BitFloat(t) => (MOVDload ptr mem)
+
+// stores
+(Store {t} ptr val mem) && t.Size() == 1 => (MOVBstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 2 => (MOVHstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && !is32BitFloat(val.Type) => (MOVWstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 && !is64BitFloat(val.Type) => (MOVVstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && is32BitFloat(val.Type) => (MOVFstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 && is64BitFloat(val.Type) => (MOVDstore ptr val mem)
+
+// zeroing
+(Zero [0] _ mem) => mem
+(Zero [1] ptr mem) => (MOVBstore ptr (MOVVconst [0]) mem)
+(Zero [2] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore ptr (MOVVconst [0]) mem)
+(Zero [2] ptr mem) =>
+ (MOVBstore [1] ptr (MOVVconst [0])
+ (MOVBstore [0] ptr (MOVVconst [0]) mem))
+(Zero [4] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore ptr (MOVVconst [0]) mem)
+(Zero [4] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [2] ptr (MOVVconst [0])
+ (MOVHstore [0] ptr (MOVVconst [0]) mem))
+(Zero [4] ptr mem) =>
+ (MOVBstore [3] ptr (MOVVconst [0])
+ (MOVBstore [2] ptr (MOVVconst [0])
+ (MOVBstore [1] ptr (MOVVconst [0])
+ (MOVBstore [0] ptr (MOVVconst [0]) mem))))
+(Zero [8] {t} ptr mem) && t.Alignment()%8 == 0 =>
+ (MOVVstore ptr (MOVVconst [0]) mem)
+(Zero [8] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [4] ptr (MOVVconst [0])
+ (MOVWstore [0] ptr (MOVVconst [0]) mem))
+(Zero [8] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [6] ptr (MOVVconst [0])
+ (MOVHstore [4] ptr (MOVVconst [0])
+ (MOVHstore [2] ptr (MOVVconst [0])
+ (MOVHstore [0] ptr (MOVVconst [0]) mem))))
+
+(Zero [3] ptr mem) =>
+ (MOVBstore [2] ptr (MOVVconst [0])
+ (MOVBstore [1] ptr (MOVVconst [0])
+ (MOVBstore [0] ptr (MOVVconst [0]) mem)))
+(Zero [6] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [4] ptr (MOVVconst [0])
+ (MOVHstore [2] ptr (MOVVconst [0])
+ (MOVHstore [0] ptr (MOVVconst [0]) mem)))
+(Zero [12] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [8] ptr (MOVVconst [0])
+ (MOVWstore [4] ptr (MOVVconst [0])
+ (MOVWstore [0] ptr (MOVVconst [0]) mem)))
+(Zero [16] {t} ptr mem) && t.Alignment()%8 == 0 =>
+ (MOVVstore [8] ptr (MOVVconst [0])
+ (MOVVstore [0] ptr (MOVVconst [0]) mem))
+(Zero [24] {t} ptr mem) && t.Alignment()%8 == 0 =>
+ (MOVVstore [16] ptr (MOVVconst [0])
+ (MOVVstore [8] ptr (MOVVconst [0])
+ (MOVVstore [0] ptr (MOVVconst [0]) mem)))
+
+// medium zeroing uses a duff device
+// 8, and 128 are magic constants, see runtime/mkduff.go
+(Zero [s] {t} ptr mem)
+ && s%8 == 0 && s > 24 && s <= 8*128
+ && t.Alignment()%8 == 0 && !config.noDuffDevice =>
+ (DUFFZERO [8 * (128 - s/8)] ptr mem)
+
+// large or unaligned zeroing uses a loop
+(Zero [s] {t} ptr mem)
+ && (s > 8*128 || config.noDuffDevice) || t.Alignment()%8 != 0 =>
+ (LoweredZero [t.Alignment()]
+ ptr
+ (ADDVconst <ptr.Type> ptr [s-moveSize(t.Alignment(), config)])
+ mem)
+
+// moves
+(Move [0] _ _ mem) => mem
+(Move [1] dst src mem) => (MOVBstore dst (MOVBload src mem) mem)
+(Move [2] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore dst (MOVHload src mem) mem)
+(Move [2] dst src mem) =>
+ (MOVBstore [1] dst (MOVBload [1] src mem)
+ (MOVBstore dst (MOVBload src mem) mem))
+(Move [4] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore dst (MOVWload src mem) mem)
+(Move [4] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [2] dst (MOVHload [2] src mem)
+ (MOVHstore dst (MOVHload src mem) mem))
+(Move [4] dst src mem) =>
+ (MOVBstore [3] dst (MOVBload [3] src mem)
+ (MOVBstore [2] dst (MOVBload [2] src mem)
+ (MOVBstore [1] dst (MOVBload [1] src mem)
+ (MOVBstore dst (MOVBload src mem) mem))))
+(Move [8] {t} dst src mem) && t.Alignment()%8 == 0 =>
+ (MOVVstore dst (MOVVload src mem) mem)
+(Move [8] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [4] dst (MOVWload [4] src mem)
+ (MOVWstore dst (MOVWload src mem) mem))
+(Move [8] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [6] dst (MOVHload [6] src mem)
+ (MOVHstore [4] dst (MOVHload [4] src mem)
+ (MOVHstore [2] dst (MOVHload [2] src mem)
+ (MOVHstore dst (MOVHload src mem) mem))))
+
+(Move [3] dst src mem) =>
+ (MOVBstore [2] dst (MOVBload [2] src mem)
+ (MOVBstore [1] dst (MOVBload [1] src mem)
+ (MOVBstore dst (MOVBload src mem) mem)))
+(Move [6] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [4] dst (MOVHload [4] src mem)
+ (MOVHstore [2] dst (MOVHload [2] src mem)
+ (MOVHstore dst (MOVHload src mem) mem)))
+(Move [12] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [8] dst (MOVWload [8] src mem)
+ (MOVWstore [4] dst (MOVWload [4] src mem)
+ (MOVWstore dst (MOVWload src mem) mem)))
+(Move [16] {t} dst src mem) && t.Alignment()%8 == 0 =>
+ (MOVVstore [8] dst (MOVVload [8] src mem)
+ (MOVVstore dst (MOVVload src mem) mem))
+(Move [24] {t} dst src mem) && t.Alignment()%8 == 0 =>
+ (MOVVstore [16] dst (MOVVload [16] src mem)
+ (MOVVstore [8] dst (MOVVload [8] src mem)
+ (MOVVstore dst (MOVVload src mem) mem)))
+
+// medium move uses a duff device
+(Move [s] {t} dst src mem)
+ && s%8 == 0 && s >= 24 && s <= 8*128 && t.Alignment()%8 == 0
+ && !config.noDuffDevice && logLargeCopy(v, s) =>
+ (DUFFCOPY [16 * (128 - s/8)] dst src mem)
+// 16 and 128 are magic constants. 16 is the number of bytes to encode:
+// MOVV (R1), R23
+// ADDV $8, R1
+// MOVV R23, (R2)
+// ADDV $8, R2
+// and 128 is the number of such blocks. See runtime/duff_mips64.s:duffcopy.
+
+// large or unaligned move uses a loop
+(Move [s] {t} dst src mem)
+ && s > 24 && logLargeCopy(v, s) || t.Alignment()%8 != 0 =>
+ (LoweredMove [t.Alignment()]
+ dst
+ src
+ (ADDVconst <src.Type> src [s-moveSize(t.Alignment(), config)])
+ mem)
+
+// calls
+(StaticCall ...) => (CALLstatic ...)
+(ClosureCall ...) => (CALLclosure ...)
+(InterCall ...) => (CALLinter ...)
+
+// atomic intrinsics
+(AtomicLoad(8|32|64) ...) => (LoweredAtomicLoad(8|32|64) ...)
+(AtomicLoadPtr ...) => (LoweredAtomicLoad64 ...)
+
+(AtomicStore(8|32|64) ...) => (LoweredAtomicStore(8|32|64) ...)
+(AtomicStorePtrNoWB ...) => (LoweredAtomicStore64 ...)
+
+(AtomicExchange(32|64) ...) => (LoweredAtomicExchange(32|64) ...)
+
+(AtomicAdd(32|64) ...) => (LoweredAtomicAdd(32|64) ...)
+
+(AtomicCompareAndSwap(32|64) ...) => (LoweredAtomicCas(32|64) ...)
+
+// checks
+(NilCheck ...) => (LoweredNilCheck ...)
+(IsNonNil ptr) => (SGTU ptr (MOVVconst [0]))
+(IsInBounds idx len) => (SGTU len idx)
+(IsSliceInBounds idx len) => (XOR (MOVVconst [1]) (SGTU idx len))
+
+// pseudo-ops
+(GetClosurePtr ...) => (LoweredGetClosurePtr ...)
+(GetCallerSP ...) => (LoweredGetCallerSP ...)
+(GetCallerPC ...) => (LoweredGetCallerPC ...)
+
+(If cond yes no) => (NE cond yes no)
+
+// Write barrier.
+(WB ...) => (LoweredWB ...)
+
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
+
+// Optimizations
+
+// Absorb boolean tests into block
+(NE (FPFlagTrue cmp) yes no) => (FPT cmp yes no)
+(NE (FPFlagFalse cmp) yes no) => (FPF cmp yes no)
+(EQ (FPFlagTrue cmp) yes no) => (FPF cmp yes no)
+(EQ (FPFlagFalse cmp) yes no) => (FPT cmp yes no)
+(NE (XORconst [1] cmp:(SGT _ _)) yes no) => (EQ cmp yes no)
+(NE (XORconst [1] cmp:(SGTU _ _)) yes no) => (EQ cmp yes no)
+(NE (XORconst [1] cmp:(SGTconst _)) yes no) => (EQ cmp yes no)
+(NE (XORconst [1] cmp:(SGTUconst _)) yes no) => (EQ cmp yes no)
+(EQ (XORconst [1] cmp:(SGT _ _)) yes no) => (NE cmp yes no)
+(EQ (XORconst [1] cmp:(SGTU _ _)) yes no) => (NE cmp yes no)
+(EQ (XORconst [1] cmp:(SGTconst _)) yes no) => (NE cmp yes no)
+(EQ (XORconst [1] cmp:(SGTUconst _)) yes no) => (NE cmp yes no)
+(NE (SGTUconst [1] x) yes no) => (EQ x yes no)
+(EQ (SGTUconst [1] x) yes no) => (NE x yes no)
+(NE (SGTU x (MOVVconst [0])) yes no) => (NE x yes no)
+(EQ (SGTU x (MOVVconst [0])) yes no) => (EQ x yes no)
+(NE (SGTconst [0] x) yes no) => (LTZ x yes no)
+(EQ (SGTconst [0] x) yes no) => (GEZ x yes no)
+(NE (SGT x (MOVVconst [0])) yes no) => (GTZ x yes no)
+(EQ (SGT x (MOVVconst [0])) yes no) => (LEZ x yes no)
+
+// fold offset into address
+(ADDVconst [off1] (MOVVaddr [off2] {sym} ptr)) && is32Bit(off1+int64(off2)) => (MOVVaddr [int32(off1)+int32(off2)] {sym} ptr)
+
+// fold address into load/store
+(MOVBload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVBload [off1+int32(off2)] {sym} ptr mem)
+(MOVBUload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVBUload [off1+int32(off2)] {sym} ptr mem)
+(MOVHload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVHload [off1+int32(off2)] {sym} ptr mem)
+(MOVHUload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVHUload [off1+int32(off2)] {sym} ptr mem)
+(MOVWload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVWload [off1+int32(off2)] {sym} ptr mem)
+(MOVWUload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVWUload [off1+int32(off2)] {sym} ptr mem)
+(MOVVload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVVload [off1+int32(off2)] {sym} ptr mem)
+(MOVFload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVFload [off1+int32(off2)] {sym} ptr mem)
+(MOVDload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVDload [off1+int32(off2)] {sym} ptr mem)
+
+(MOVBstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2) => (MOVBstore [off1+int32(off2)] {sym} ptr val mem)
+(MOVHstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2) => (MOVHstore [off1+int32(off2)] {sym} ptr val mem)
+(MOVWstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2) => (MOVWstore [off1+int32(off2)] {sym} ptr val mem)
+(MOVVstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2) => (MOVVstore [off1+int32(off2)] {sym} ptr val mem)
+(MOVFstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2) => (MOVFstore [off1+int32(off2)] {sym} ptr val mem)
+(MOVDstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(int64(off1)+off2) => (MOVDstore [off1+int32(off2)] {sym} ptr val mem)
+(MOVBstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVBstorezero [off1+int32(off2)] {sym} ptr mem)
+(MOVHstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVHstorezero [off1+int32(off2)] {sym} ptr mem)
+(MOVWstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVWstorezero [off1+int32(off2)] {sym} ptr mem)
+(MOVVstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVVstorezero [off1+int32(off2)] {sym} ptr mem)
+
+(MOVBload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVBload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVBUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVBUload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVHload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVHUload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVWload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVWUload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVVload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVVload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVFload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVFload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVDload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVDload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+
+(MOVBstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVBstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVHstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVHstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVWstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVWstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVVstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVVstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVFstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVFstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVDstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVDstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVBstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVBstorezero [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVHstorezero [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVWstorezero [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+(MOVVstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVVstorezero [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+
+// store zero
+(MOVBstore [off] {sym} ptr (MOVVconst [0]) mem) => (MOVBstorezero [off] {sym} ptr mem)
+(MOVHstore [off] {sym} ptr (MOVVconst [0]) mem) => (MOVHstorezero [off] {sym} ptr mem)
+(MOVWstore [off] {sym} ptr (MOVVconst [0]) mem) => (MOVWstorezero [off] {sym} ptr mem)
+(MOVVstore [off] {sym} ptr (MOVVconst [0]) mem) => (MOVVstorezero [off] {sym} ptr mem)
+
+// don't extend after proper load
+(MOVBreg x:(MOVBload _ _)) => (MOVVreg x)
+(MOVBUreg x:(MOVBUload _ _)) => (MOVVreg x)
+(MOVHreg x:(MOVBload _ _)) => (MOVVreg x)
+(MOVHreg x:(MOVBUload _ _)) => (MOVVreg x)
+(MOVHreg x:(MOVHload _ _)) => (MOVVreg x)
+(MOVHUreg x:(MOVBUload _ _)) => (MOVVreg x)
+(MOVHUreg x:(MOVHUload _ _)) => (MOVVreg x)
+(MOVWreg x:(MOVBload _ _)) => (MOVVreg x)
+(MOVWreg x:(MOVBUload _ _)) => (MOVVreg x)
+(MOVWreg x:(MOVHload _ _)) => (MOVVreg x)
+(MOVWreg x:(MOVHUload _ _)) => (MOVVreg x)
+(MOVWreg x:(MOVWload _ _)) => (MOVVreg x)
+(MOVWUreg x:(MOVBUload _ _)) => (MOVVreg x)
+(MOVWUreg x:(MOVHUload _ _)) => (MOVVreg x)
+(MOVWUreg x:(MOVWUload _ _)) => (MOVVreg x)
+
+// fold double extensions
+(MOVBreg x:(MOVBreg _)) => (MOVVreg x)
+(MOVBUreg x:(MOVBUreg _)) => (MOVVreg x)
+(MOVHreg x:(MOVBreg _)) => (MOVVreg x)
+(MOVHreg x:(MOVBUreg _)) => (MOVVreg x)
+(MOVHreg x:(MOVHreg _)) => (MOVVreg x)
+(MOVHUreg x:(MOVBUreg _)) => (MOVVreg x)
+(MOVHUreg x:(MOVHUreg _)) => (MOVVreg x)
+(MOVWreg x:(MOVBreg _)) => (MOVVreg x)
+(MOVWreg x:(MOVBUreg _)) => (MOVVreg x)
+(MOVWreg x:(MOVHreg _)) => (MOVVreg x)
+(MOVWreg x:(MOVWreg _)) => (MOVVreg x)
+(MOVWUreg x:(MOVBUreg _)) => (MOVVreg x)
+(MOVWUreg x:(MOVHUreg _)) => (MOVVreg x)
+(MOVWUreg x:(MOVWUreg _)) => (MOVVreg x)
+
+// don't extend before store
+(MOVBstore [off] {sym} ptr (MOVBreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVBUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVHreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVHUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVWreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVWreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOVWreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
+
+// if a register move has only 1 use, just use the same register without emitting instruction
+// MOVVnop doesn't emit instruction, only for ensuring the type.
+(MOVVreg x) && x.Uses == 1 => (MOVVnop x)
+
+// fold constant into arithmatic ops
+(ADDV x (MOVVconst [c])) && is32Bit(c) => (ADDVconst [c] x)
+(SUBV x (MOVVconst [c])) && is32Bit(c) => (SUBVconst [c] x)
+(AND x (MOVVconst [c])) && is32Bit(c) => (ANDconst [c] x)
+(OR x (MOVVconst [c])) && is32Bit(c) => (ORconst [c] x)
+(XOR x (MOVVconst [c])) && is32Bit(c) => (XORconst [c] x)
+(NOR x (MOVVconst [c])) && is32Bit(c) => (NORconst [c] x)
+
+(SLLV _ (MOVVconst [c])) && uint64(c)>=64 => (MOVVconst [0])
+(SRLV _ (MOVVconst [c])) && uint64(c)>=64 => (MOVVconst [0])
+(SRAV x (MOVVconst [c])) && uint64(c)>=64 => (SRAVconst x [63])
+(SLLV x (MOVVconst [c])) => (SLLVconst x [c])
+(SRLV x (MOVVconst [c])) => (SRLVconst x [c])
+(SRAV x (MOVVconst [c])) => (SRAVconst x [c])
+
+(SGT (MOVVconst [c]) x) && is32Bit(c) => (SGTconst [c] x)
+(SGTU (MOVVconst [c]) x) && is32Bit(c) => (SGTUconst [c] x)
+
+// mul by constant
+(Select1 (MULVU x (MOVVconst [-1]))) => (NEGV x)
+(Select1 (MULVU _ (MOVVconst [0]))) => (MOVVconst [0])
+(Select1 (MULVU x (MOVVconst [1]))) => x
+(Select1 (MULVU x (MOVVconst [c]))) && isPowerOfTwo64(c) => (SLLVconst [log64(c)] x)
+
+// div by constant
+(Select1 (DIVVU x (MOVVconst [1]))) => x
+(Select1 (DIVVU x (MOVVconst [c]))) && isPowerOfTwo64(c) => (SRLVconst [log64(c)] x)
+(Select0 (DIVVU _ (MOVVconst [1]))) => (MOVVconst [0]) // mod
+(Select0 (DIVVU x (MOVVconst [c]))) && isPowerOfTwo64(c) => (ANDconst [c-1] x) // mod
+
+// generic simplifications
+(ADDV x (NEGV y)) => (SUBV x y)
+(SUBV x x) => (MOVVconst [0])
+(SUBV (MOVVconst [0]) x) => (NEGV x)
+(AND x x) => x
+(OR x x) => x
+(XOR x x) => (MOVVconst [0])
+
+// remove redundant *const ops
+(ADDVconst [0] x) => x
+(SUBVconst [0] x) => x
+(ANDconst [0] _) => (MOVVconst [0])
+(ANDconst [-1] x) => x
+(ORconst [0] x) => x
+(ORconst [-1] _) => (MOVVconst [-1])
+(XORconst [0] x) => x
+(XORconst [-1] x) => (NORconst [0] x)
+
+// generic constant folding
+(ADDVconst [c] (MOVVconst [d])) => (MOVVconst [c+d])
+(ADDVconst [c] (ADDVconst [d] x)) && is32Bit(c+d) => (ADDVconst [c+d] x)
+(ADDVconst [c] (SUBVconst [d] x)) && is32Bit(c-d) => (ADDVconst [c-d] x)
+(SUBVconst [c] (MOVVconst [d])) => (MOVVconst [d-c])
+(SUBVconst [c] (SUBVconst [d] x)) && is32Bit(-c-d) => (ADDVconst [-c-d] x)
+(SUBVconst [c] (ADDVconst [d] x)) && is32Bit(-c+d) => (ADDVconst [-c+d] x)
+(SLLVconst [c] (MOVVconst [d])) => (MOVVconst [d<<uint64(c)])
+(SRLVconst [c] (MOVVconst [d])) => (MOVVconst [int64(uint64(d)>>uint64(c))])
+(SRAVconst [c] (MOVVconst [d])) => (MOVVconst [d>>uint64(c)])
+(Select1 (MULVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c*d])
+(Select1 (DIVV (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c/d])
+(Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)/uint64(d))])
+(Select0 (DIVV (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c%d]) // mod
+(Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)%uint64(d))]) // mod
+(ANDconst [c] (MOVVconst [d])) => (MOVVconst [c&d])
+(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
+(ORconst [c] (MOVVconst [d])) => (MOVVconst [c|d])
+(ORconst [c] (ORconst [d] x)) && is32Bit(c|d) => (ORconst [c|d] x)
+(XORconst [c] (MOVVconst [d])) => (MOVVconst [c^d])
+(XORconst [c] (XORconst [d] x)) && is32Bit(c^d) => (XORconst [c^d] x)
+(NORconst [c] (MOVVconst [d])) => (MOVVconst [^(c|d)])
+(NEGV (MOVVconst [c])) => (MOVVconst [-c])
+(MOVBreg (MOVVconst [c])) => (MOVVconst [int64(int8(c))])
+(MOVBUreg (MOVVconst [c])) => (MOVVconst [int64(uint8(c))])
+(MOVHreg (MOVVconst [c])) => (MOVVconst [int64(int16(c))])
+(MOVHUreg (MOVVconst [c])) => (MOVVconst [int64(uint16(c))])
+(MOVWreg (MOVVconst [c])) => (MOVVconst [int64(int32(c))])
+(MOVWUreg (MOVVconst [c])) => (MOVVconst [int64(uint32(c))])
+(MOVVreg (MOVVconst [c])) => (MOVVconst [c])
+(LoweredAtomicStore(32|64) ptr (MOVVconst [0]) mem) => (LoweredAtomicStorezero(32|64) ptr mem)
+(LoweredAtomicAdd32 ptr (MOVVconst [c]) mem) && is32Bit(c) => (LoweredAtomicAddconst32 [int32(c)] ptr mem)
+(LoweredAtomicAdd64 ptr (MOVVconst [c]) mem) && is32Bit(c) => (LoweredAtomicAddconst64 [c] ptr mem)
+
+// constant comparisons
+(SGTconst [c] (MOVVconst [d])) && c>d => (MOVVconst [1])
+(SGTconst [c] (MOVVconst [d])) && c<=d => (MOVVconst [0])
+(SGTUconst [c] (MOVVconst [d])) && uint64(c)>uint64(d) => (MOVVconst [1])
+(SGTUconst [c] (MOVVconst [d])) && uint64(c)<=uint64(d) => (MOVVconst [0])
+
+// other known comparisons
+(SGTconst [c] (MOVBreg _)) && 0x7f < c => (MOVVconst [1])
+(SGTconst [c] (MOVBreg _)) && c <= -0x80 => (MOVVconst [0])
+(SGTconst [c] (MOVBUreg _)) && 0xff < c => (MOVVconst [1])
+(SGTconst [c] (MOVBUreg _)) && c < 0 => (MOVVconst [0])
+(SGTUconst [c] (MOVBUreg _)) && 0xff < uint64(c) => (MOVVconst [1])
+(SGTconst [c] (MOVHreg _)) && 0x7fff < c => (MOVVconst [1])
+(SGTconst [c] (MOVHreg _)) && c <= -0x8000 => (MOVVconst [0])
+(SGTconst [c] (MOVHUreg _)) && 0xffff < c => (MOVVconst [1])
+(SGTconst [c] (MOVHUreg _)) && c < 0 => (MOVVconst [0])
+(SGTUconst [c] (MOVHUreg _)) && 0xffff < uint64(c) => (MOVVconst [1])
+(SGTconst [c] (MOVWUreg _)) && c < 0 => (MOVVconst [0])
+(SGTconst [c] (ANDconst [m] _)) && 0 <= m && m < c => (MOVVconst [1])
+(SGTUconst [c] (ANDconst [m] _)) && uint64(m) < uint64(c) => (MOVVconst [1])
+(SGTconst [c] (SRLVconst _ [d])) && 0 <= c && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c) => (MOVVconst [1])
+(SGTUconst [c] (SRLVconst _ [d])) && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c) => (MOVVconst [1])
+
+// absorb constants into branches
+(EQ (MOVVconst [0]) yes no) => (First yes no)
+(EQ (MOVVconst [c]) yes no) && c != 0 => (First no yes)
+(NE (MOVVconst [0]) yes no) => (First no yes)
+(NE (MOVVconst [c]) yes no) && c != 0 => (First yes no)
+(LTZ (MOVVconst [c]) yes no) && c < 0 => (First yes no)
+(LTZ (MOVVconst [c]) yes no) && c >= 0 => (First no yes)
+(LEZ (MOVVconst [c]) yes no) && c <= 0 => (First yes no)
+(LEZ (MOVVconst [c]) yes no) && c > 0 => (First no yes)
+(GTZ (MOVVconst [c]) yes no) && c > 0 => (First yes no)
+(GTZ (MOVVconst [c]) yes no) && c <= 0 => (First no yes)
+(GEZ (MOVVconst [c]) yes no) && c >= 0 => (First yes no)
+(GEZ (MOVVconst [c]) yes no) && c < 0 => (First no yes)
diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go
new file mode 100644
index 0000000..e1e3933
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go
@@ -0,0 +1,482 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import "strings"
+
+// Notes:
+// - Integer types live in the low portion of registers. Upper portions are junk.
+// - Boolean types use the low-order byte of a register. 0=false, 1=true.
+// Upper bytes are junk.
+// - *const instructions may use a constant larger than the instruction can encode.
+// In this case the assembler expands to multiple instructions and uses tmp
+// register (R23).
+
+// Suffixes encode the bit width of various instructions.
+// V (vlong) = 64 bit
+// WU (word) = 32 bit unsigned
+// W (word) = 32 bit
+// H (half word) = 16 bit
+// HU = 16 bit unsigned
+// B (byte) = 8 bit
+// BU = 8 bit unsigned
+// F (float) = 32 bit float
+// D (double) = 64 bit float
+
+// Note: registers not used in regalloc are not included in this list,
+// so that regmask stays within int64
+// Be careful when hand coding regmasks.
+var regNamesMIPS64 = []string{
+ "R0", // constant 0
+ "R1",
+ "R2",
+ "R3",
+ "R4",
+ "R5",
+ "R6",
+ "R7",
+ "R8",
+ "R9",
+ "R10",
+ "R11",
+ "R12",
+ "R13",
+ "R14",
+ "R15",
+ "R16",
+ "R17",
+ "R18",
+ "R19",
+ "R20",
+ "R21",
+ "R22",
+ // R23 = REGTMP not used in regalloc
+ "R24",
+ "R25",
+ // R26 reserved by kernel
+ // R27 reserved by kernel
+ // R28 = REGSB not used in regalloc
+ "SP", // aka R29
+ "g", // aka R30
+ "R31", // aka REGLINK
+
+ "F0",
+ "F1",
+ "F2",
+ "F3",
+ "F4",
+ "F5",
+ "F6",
+ "F7",
+ "F8",
+ "F9",
+ "F10",
+ "F11",
+ "F12",
+ "F13",
+ "F14",
+ "F15",
+ "F16",
+ "F17",
+ "F18",
+ "F19",
+ "F20",
+ "F21",
+ "F22",
+ "F23",
+ "F24",
+ "F25",
+ "F26",
+ "F27",
+ "F28",
+ "F29",
+ "F30",
+ "F31",
+
+ "HI", // high bits of multiplication
+ "LO", // low bits of multiplication
+
+ // If you add registers, update asyncPreempt in runtime.
+
+ // pseudo-registers
+ "SB",
+}
+
+func init() {
+ // Make map from reg names to reg integers.
+ if len(regNamesMIPS64) > 64 {
+ panic("too many registers")
+ }
+ num := map[string]int{}
+ for i, name := range regNamesMIPS64 {
+ num[name] = 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 (
+ gp = buildReg("R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31")
+ gpg = gp | buildReg("g")
+ gpsp = gp | buildReg("SP")
+ gpspg = gpg | buildReg("SP")
+ gpspsbg = gpspg | buildReg("SB")
+ fp = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31")
+ lo = buildReg("LO")
+ hi = buildReg("HI")
+ callerSave = gp | fp | lo | hi | buildReg("g") // runtime.setg (and anything calling it) may clobber g
+ r1 = buildReg("R1")
+ r2 = buildReg("R2")
+ r3 = buildReg("R3")
+ r4 = buildReg("R4")
+ )
+ // Common regInfo
+ var (
+ gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
+ gp11 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
+ gp11sp = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
+ gp21 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
+ gp2hilo = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{hi, lo}}
+ gpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
+ gpstore = regInfo{inputs: []regMask{gpspsbg, gpg}}
+ gpstore0 = regInfo{inputs: []regMask{gpspsbg}}
+ gpxchg = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
+ gpcas = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{gp}}
+ fp01 = regInfo{inputs: nil, outputs: []regMask{fp}}
+ fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
+ //fp1flags = regInfo{inputs: []regMask{fp}}
+ //fpgp = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}
+ //gpfp = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}
+ fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
+ fp2flags = regInfo{inputs: []regMask{fp, fp}}
+ fpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{fp}}
+ fpstore = regInfo{inputs: []regMask{gpspsbg, fp}}
+ readflags = regInfo{inputs: nil, outputs: []regMask{gp}}
+ )
+ ops := []opData{
+ // binary ops
+ {name: "ADDV", argLength: 2, reg: gp21, asm: "ADDVU", commutative: true}, // arg0 + arg1
+ {name: "ADDVconst", argLength: 1, reg: gp11sp, asm: "ADDVU", aux: "Int64"}, // arg0 + auxInt. auxInt is 32-bit, also in other *const ops.
+ {name: "SUBV", argLength: 2, reg: gp21, asm: "SUBVU"}, // arg0 - arg1
+ {name: "SUBVconst", argLength: 1, reg: gp11, asm: "SUBVU", aux: "Int64"}, // arg0 - auxInt
+ {name: "MULV", argLength: 2, reg: gp2hilo, asm: "MULV", commutative: true, typ: "(Int64,Int64)"}, // arg0 * arg1, signed, results hi,lo
+ {name: "MULVU", argLength: 2, reg: gp2hilo, asm: "MULVU", commutative: true, typ: "(UInt64,UInt64)"}, // arg0 * arg1, unsigned, results hi,lo
+ {name: "DIVV", argLength: 2, reg: gp2hilo, asm: "DIVV", typ: "(Int64,Int64)"}, // arg0 / arg1, signed, results hi=arg0%arg1,lo=arg0/arg1
+ {name: "DIVVU", argLength: 2, reg: gp2hilo, asm: "DIVVU", typ: "(UInt64,UInt64)"}, // arg0 / arg1, signed, results hi=arg0%arg1,lo=arg0/arg1
+
+ {name: "ADDF", argLength: 2, reg: fp21, asm: "ADDF", commutative: true}, // arg0 + arg1
+ {name: "ADDD", argLength: 2, reg: fp21, asm: "ADDD", commutative: true}, // arg0 + arg1
+ {name: "SUBF", argLength: 2, reg: fp21, asm: "SUBF"}, // arg0 - arg1
+ {name: "SUBD", argLength: 2, reg: fp21, asm: "SUBD"}, // arg0 - arg1
+ {name: "MULF", argLength: 2, reg: fp21, asm: "MULF", commutative: true}, // arg0 * arg1
+ {name: "MULD", argLength: 2, reg: fp21, asm: "MULD", commutative: true}, // arg0 * arg1
+ {name: "DIVF", argLength: 2, reg: fp21, asm: "DIVF"}, // arg0 / arg1
+ {name: "DIVD", argLength: 2, reg: fp21, asm: "DIVD"}, // arg0 / arg1
+
+ {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0 & arg1
+ {name: "ANDconst", argLength: 1, reg: gp11, asm: "AND", aux: "Int64"}, // arg0 & auxInt
+ {name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true}, // arg0 | arg1
+ {name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int64"}, // arg0 | auxInt
+ {name: "XOR", argLength: 2, reg: gp21, asm: "XOR", commutative: true, typ: "UInt64"}, // arg0 ^ arg1
+ {name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64", typ: "UInt64"}, // arg0 ^ auxInt
+ {name: "NOR", argLength: 2, reg: gp21, asm: "NOR", commutative: true}, // ^(arg0 | arg1)
+ {name: "NORconst", argLength: 1, reg: gp11, asm: "NOR", aux: "Int64"}, // ^(arg0 | auxInt)
+
+ {name: "NEGV", argLength: 1, reg: gp11}, // -arg0
+ {name: "NEGF", argLength: 1, reg: fp11, asm: "NEGF"}, // -arg0, float32
+ {name: "NEGD", argLength: 1, reg: fp11, asm: "NEGD"}, // -arg0, float64
+ {name: "SQRTD", argLength: 1, reg: fp11, asm: "SQRTD"}, // sqrt(arg0), float64
+
+ // shifts
+ {name: "SLLV", argLength: 2, reg: gp21, asm: "SLLV"}, // arg0 << arg1, shift amount is mod 64
+ {name: "SLLVconst", argLength: 1, reg: gp11, asm: "SLLV", aux: "Int64"}, // arg0 << auxInt
+ {name: "SRLV", argLength: 2, reg: gp21, asm: "SRLV"}, // arg0 >> arg1, unsigned, shift amount is mod 64
+ {name: "SRLVconst", argLength: 1, reg: gp11, asm: "SRLV", aux: "Int64"}, // arg0 >> auxInt, unsigned
+ {name: "SRAV", argLength: 2, reg: gp21, asm: "SRAV"}, // arg0 >> arg1, signed, shift amount is mod 64
+ {name: "SRAVconst", argLength: 1, reg: gp11, asm: "SRAV", aux: "Int64"}, // arg0 >> auxInt, signed
+
+ // comparisons
+ {name: "SGT", argLength: 2, reg: gp21, asm: "SGT", typ: "Bool"}, // 1 if arg0 > arg1 (signed), 0 otherwise
+ {name: "SGTconst", argLength: 1, reg: gp11, asm: "SGT", aux: "Int64", typ: "Bool"}, // 1 if auxInt > arg0 (signed), 0 otherwise
+ {name: "SGTU", argLength: 2, reg: gp21, asm: "SGTU", typ: "Bool"}, // 1 if arg0 > arg1 (unsigned), 0 otherwise
+ {name: "SGTUconst", argLength: 1, reg: gp11, asm: "SGTU", aux: "Int64", typ: "Bool"}, // 1 if auxInt > arg0 (unsigned), 0 otherwise
+
+ {name: "CMPEQF", argLength: 2, reg: fp2flags, asm: "CMPEQF", typ: "Flags"}, // flags=true if arg0 = arg1, float32
+ {name: "CMPEQD", argLength: 2, reg: fp2flags, asm: "CMPEQD", typ: "Flags"}, // flags=true if arg0 = arg1, float64
+ {name: "CMPGEF", argLength: 2, reg: fp2flags, asm: "CMPGEF", typ: "Flags"}, // flags=true if arg0 >= arg1, float32
+ {name: "CMPGED", argLength: 2, reg: fp2flags, asm: "CMPGED", typ: "Flags"}, // flags=true if arg0 >= arg1, float64
+ {name: "CMPGTF", argLength: 2, reg: fp2flags, asm: "CMPGTF", typ: "Flags"}, // flags=true if arg0 > arg1, float32
+ {name: "CMPGTD", argLength: 2, reg: fp2flags, asm: "CMPGTD", typ: "Flags"}, // flags=true if arg0 > arg1, float64
+
+ // moves
+ {name: "MOVVconst", argLength: 0, reg: gp01, aux: "Int64", asm: "MOVV", typ: "UInt64", rematerializeable: true}, // auxint
+ {name: "MOVFconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVF", typ: "Float32", rematerializeable: true}, // auxint as 64-bit float, convert to 32-bit float
+ {name: "MOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVD", typ: "Float64", rematerializeable: true}, // auxint as 64-bit float
+
+ {name: "MOVVaddr", argLength: 1, reg: regInfo{inputs: []regMask{buildReg("SP") | buildReg("SB")}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVV", rematerializeable: true, symEffect: "Addr"}, // arg0 + auxInt + aux.(*gc.Sym), arg0=SP/SB
+
+ {name: "MOVBload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVB", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVBUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVBU", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVH", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVHU", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVWload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVW", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVWUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVWU", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVVload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVV", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVFload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVF", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVDload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVD", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+
+ {name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 1 byte of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVVstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVV", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVFstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVF", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+
+ {name: "MOVBstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 1 byte of zero to arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes of zero to arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVWstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of zero to arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVVstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVV", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of zero to arg0 + auxInt + aux. ar12=mem.
+
+ // conversions
+ {name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB"}, // move from arg0, sign-extended from byte
+ {name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // move from arg0, unsign-extended from byte
+ {name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVH"}, // move from arg0, sign-extended from half
+ {name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // move from arg0, unsign-extended from half
+ {name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"}, // move from arg0, sign-extended from word
+ {name: "MOVWUreg", argLength: 1, reg: gp11, asm: "MOVWU"}, // move from arg0, unsign-extended from word
+ {name: "MOVVreg", argLength: 1, reg: gp11, asm: "MOVV"}, // move from arg0
+
+ {name: "MOVVnop", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // nop, return arg0 in same register
+
+ {name: "MOVWF", argLength: 1, reg: fp11, asm: "MOVWF"}, // int32 -> float32
+ {name: "MOVWD", argLength: 1, reg: fp11, asm: "MOVWD"}, // int32 -> float64
+ {name: "MOVVF", argLength: 1, reg: fp11, asm: "MOVVF"}, // int64 -> float32
+ {name: "MOVVD", argLength: 1, reg: fp11, asm: "MOVVD"}, // int64 -> float64
+ {name: "TRUNCFW", argLength: 1, reg: fp11, asm: "TRUNCFW"}, // float32 -> int32
+ {name: "TRUNCDW", argLength: 1, reg: fp11, asm: "TRUNCDW"}, // float64 -> int32
+ {name: "TRUNCFV", argLength: 1, reg: fp11, asm: "TRUNCFV"}, // float32 -> int64
+ {name: "TRUNCDV", argLength: 1, reg: fp11, asm: "TRUNCDV"}, // float64 -> int64
+ {name: "MOVFD", argLength: 1, reg: fp11, asm: "MOVFD"}, // float32 -> float64
+ {name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
+
+ // function calls
+ {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
+ {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
+ {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
+
+ // duffzero
+ // arg0 = address of memory to zero
+ // arg1 = mem
+ // auxint = offset into duffzero code to start executing
+ // returns mem
+ // R1 aka mips.REGRT1 changed as side effect
+ {
+ name: "DUFFZERO",
+ aux: "Int64",
+ argLength: 2,
+ reg: regInfo{
+ inputs: []regMask{gp},
+ clobbers: buildReg("R1 R31"),
+ },
+ faultOnNilArg0: true,
+ },
+
+ // duffcopy
+ // arg0 = address of dst memory (in R2, changed as side effect)
+ // arg1 = address of src memory (in R1, changed as side effect)
+ // arg2 = mem
+ // auxint = offset into duffcopy code to start executing
+ // returns mem
+ {
+ name: "DUFFCOPY",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R2"), buildReg("R1")},
+ clobbers: buildReg("R1 R2 R31"),
+ },
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // large or unaligned zeroing
+ // arg0 = address of memory to zero (in R1, changed as side effect)
+ // arg1 = address of the last element to zero
+ // arg2 = mem
+ // auxint = alignment
+ // returns mem
+ // SUBV $8, R1
+ // MOVV R0, 8(R1)
+ // ADDV $8, R1
+ // BNE Rarg1, R1, -2(PC)
+ {
+ name: "LoweredZero",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R1"), gp},
+ clobbers: buildReg("R1"),
+ },
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ },
+
+ // large or unaligned move
+ // arg0 = address of dst memory (in R2, changed as side effect)
+ // arg1 = address of src memory (in R1, changed as side effect)
+ // arg2 = address of the last element of src
+ // arg3 = mem
+ // auxint = alignment
+ // returns mem
+ // SUBV $8, R1
+ // MOVV 8(R1), Rtmp
+ // MOVV Rtmp, (R2)
+ // ADDV $8, R1
+ // ADDV $8, R2
+ // BNE Rarg2, R1, -4(PC)
+ {
+ name: "LoweredMove",
+ aux: "Int64",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R2"), buildReg("R1"), gp},
+ clobbers: buildReg("R1 R2"),
+ },
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // atomic loads.
+ // load from arg0. arg1=mem.
+ // returns <value,memory> so they can be properly ordered with other loads.
+ {name: "LoweredAtomicLoad8", argLength: 2, reg: gpload, faultOnNilArg0: true},
+ {name: "LoweredAtomicLoad32", argLength: 2, reg: gpload, faultOnNilArg0: true},
+ {name: "LoweredAtomicLoad64", argLength: 2, reg: gpload, faultOnNilArg0: true},
+
+ // atomic stores.
+ // store arg1 to arg0. arg2=mem. returns memory.
+ {name: "LoweredAtomicStore8", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicStore64", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
+ // store zero to arg0. arg1=mem. returns memory.
+ {name: "LoweredAtomicStorezero32", argLength: 2, reg: gpstore0, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicStorezero64", argLength: 2, reg: gpstore0, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic exchange.
+ // store arg1 to arg0. arg2=mem. returns <old content of *arg0, memory>.
+ // SYNC
+ // LL (Rarg0), Rout
+ // MOVV Rarg1, Rtmp
+ // SC Rtmp, (Rarg0)
+ // BEQ Rtmp, -3(PC)
+ // SYNC
+ {name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // atomic add.
+ // *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>.
+ // SYNC
+ // LL (Rarg0), Rout
+ // ADDV Rarg1, Rout, Rtmp
+ // SC Rtmp, (Rarg0)
+ // BEQ Rtmp, -3(PC)
+ // SYNC
+ // ADDV Rarg1, Rout
+ {name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ // *arg0 += auxint. arg1=mem. returns <new content of *arg0, memory>. auxint is 32-bit.
+ {name: "LoweredAtomicAddconst32", argLength: 2, reg: regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}, aux: "Int32", resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicAddconst64", argLength: 2, reg: regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}, aux: "Int64", resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // atomic compare and swap.
+ // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory.
+ // if *arg0 == arg1 {
+ // *arg0 = arg2
+ // return (true, memory)
+ // } else {
+ // return (false, memory)
+ // }
+ // SYNC
+ // MOVV $0, Rout
+ // LL (Rarg0), Rtmp
+ // BNE Rtmp, Rarg1, 4(PC)
+ // MOVV Rarg2, Rout
+ // SC Rout, (Rarg0)
+ // BEQ Rout, -4(PC)
+ // SYNC
+ {name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // pseudo-ops
+ {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem.
+
+ {name: "FPFlagTrue", argLength: 1, reg: readflags}, // bool, true if FP flag is true
+ {name: "FPFlagFalse", argLength: 1, reg: readflags}, // bool, true if FP flag is false
+
+ // Scheduler ensures LoweredGetClosurePtr occurs only in entry block,
+ // and sorts it to the very beginning of the block to prevent other
+ // use of R22 (mips.REGCTXT, the closure pointer)
+ {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R22")}}, zeroWidth: true},
+
+ // LoweredGetCallerSP returns the SP of the caller of the current function.
+ {name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
+
+ // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+ // I.e., if f calls g "calls" getcallerpc,
+ // the result should be the PC within f that g will return to.
+ // See runtime/stubs.go for a more detailed discussion.
+ {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
+
+ // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+ // It saves all GP registers if necessary,
+ // but clobbers R31 (LR) because it's a call
+ // and R23 (REGTMP).
+ {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R20"), buildReg("R21")}, clobbers: (callerSave &^ gpg) | buildReg("R31")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
+
+ // There are three of these functions so that they can have three different register inputs.
+ // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
+ // default registers to match so we don't need to copy registers around unnecessarily.
+ {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r3, r4}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ }
+
+ blocks := []blockData{
+ {name: "EQ", controls: 1},
+ {name: "NE", controls: 1},
+ {name: "LTZ", controls: 1}, // < 0
+ {name: "LEZ", controls: 1}, // <= 0
+ {name: "GTZ", controls: 1}, // > 0
+ {name: "GEZ", controls: 1}, // >= 0
+ {name: "FPT", controls: 1}, // FP flag is true
+ {name: "FPF", controls: 1}, // FP flag is false
+ }
+
+ archs = append(archs, arch{
+ name: "MIPS64",
+ pkg: "cmd/internal/obj/mips",
+ genfile: "../../mips64/ssa.go",
+ ops: ops,
+ blocks: blocks,
+ regnames: regNamesMIPS64,
+ gpregmask: gp,
+ fpregmask: fp,
+ specialregmask: hi | lo,
+ framepointerreg: -1, // not used
+ linkreg: int8(num["R31"]),
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/MIPSOps.go b/src/cmd/compile/internal/ssa/gen/MIPSOps.go
new file mode 100644
index 0000000..75ab99e
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/MIPSOps.go
@@ -0,0 +1,439 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import "strings"
+
+// Notes:
+// - Integer types live in the low portion of registers. Upper portions are junk.
+// - Boolean types use the low-order byte of a register. 0=false, 1=true.
+// Upper bytes are junk.
+// - Unused portions of AuxInt are filled by sign-extending the used portion.
+// - *const instructions may use a constant larger than the instruction can encode.
+// In this case the assembler expands to multiple instructions and uses tmp
+// register (R23).
+
+// Suffixes encode the bit width of various instructions.
+// W (word) = 32 bit
+// H (half word) = 16 bit
+// HU = 16 bit unsigned
+// B (byte) = 8 bit
+// BU = 8 bit unsigned
+// F (float) = 32 bit float
+// D (double) = 64 bit float
+
+// Note: registers not used in regalloc are not included in this list,
+// so that regmask stays within int64
+// Be careful when hand coding regmasks.
+var regNamesMIPS = []string{
+ "R0", // constant 0
+ "R1",
+ "R2",
+ "R3",
+ "R4",
+ "R5",
+ "R6",
+ "R7",
+ "R8",
+ "R9",
+ "R10",
+ "R11",
+ "R12",
+ "R13",
+ "R14",
+ "R15",
+ "R16",
+ "R17",
+ "R18",
+ "R19",
+ "R20",
+ "R21",
+ "R22",
+ //REGTMP
+ "R24",
+ "R25",
+ // R26 reserved by kernel
+ // R27 reserved by kernel
+ "R28",
+ "SP", // aka R29
+ "g", // aka R30
+ "R31", // REGLINK
+
+ // odd FP registers contain high parts of 64-bit FP values
+ "F0",
+ "F2",
+ "F4",
+ "F6",
+ "F8",
+ "F10",
+ "F12",
+ "F14",
+ "F16",
+ "F18",
+ "F20",
+ "F22",
+ "F24",
+ "F26",
+ "F28",
+ "F30",
+
+ "HI", // high bits of multiplication
+ "LO", // low bits of multiplication
+
+ // If you add registers, update asyncPreempt in runtime.
+
+ // pseudo-registers
+ "SB",
+}
+
+func init() {
+ // Make map from reg names to reg integers.
+ if len(regNamesMIPS) > 64 {
+ panic("too many registers")
+ }
+ num := map[string]int{}
+ for i, name := range regNamesMIPS {
+ num[name] = 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 (
+ gp = buildReg("R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31")
+ gpg = gp | buildReg("g")
+ gpsp = gp | buildReg("SP")
+ gpspg = gpg | buildReg("SP")
+ gpspsbg = gpspg | buildReg("SB")
+ fp = buildReg("F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30")
+ lo = buildReg("LO")
+ hi = buildReg("HI")
+ callerSave = gp | fp | lo | hi | buildReg("g") // runtime.setg (and anything calling it) may clobber g
+ r1 = buildReg("R1")
+ r2 = buildReg("R2")
+ r3 = buildReg("R3")
+ r4 = buildReg("R4")
+ r5 = buildReg("R5")
+ )
+ // Common regInfo
+ var (
+ gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
+ gp11 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
+ gp11sp = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
+ gp21 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
+ gp31 = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}}
+ gp2hilo = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{hi, lo}}
+ gpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
+ gpstore = regInfo{inputs: []regMask{gpspsbg, gpg}}
+ gpxchg = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
+ gpcas = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{gp}}
+ gpstore0 = regInfo{inputs: []regMask{gpspsbg}}
+ fp01 = regInfo{inputs: nil, outputs: []regMask{fp}}
+ fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
+ fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
+ fp2flags = regInfo{inputs: []regMask{fp, fp}}
+ fpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{fp}}
+ fpstore = regInfo{inputs: []regMask{gpspsbg, fp}}
+ readflags = regInfo{inputs: nil, outputs: []regMask{gp}}
+ )
+ ops := []opData{
+ {name: "ADD", argLength: 2, reg: gp21, asm: "ADDU", commutative: true}, // arg0 + arg1
+ {name: "ADDconst", argLength: 1, reg: gp11sp, asm: "ADDU", aux: "Int32"}, // arg0 + auxInt
+ {name: "SUB", argLength: 2, reg: gp21, asm: "SUBU"}, // arg0 - arg1
+ {name: "SUBconst", argLength: 1, reg: gp11, asm: "SUBU", aux: "Int32"}, // arg0 - auxInt
+ {name: "MUL", argLength: 2, reg: regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}, clobbers: hi | lo}, asm: "MUL", commutative: true}, // arg0 * arg1
+ {name: "MULT", argLength: 2, reg: gp2hilo, asm: "MUL", commutative: true, typ: "(Int32,Int32)"}, // arg0 * arg1, signed, results hi,lo
+ {name: "MULTU", argLength: 2, reg: gp2hilo, asm: "MULU", commutative: true, typ: "(UInt32,UInt32)"}, // arg0 * arg1, unsigned, results hi,lo
+ {name: "DIV", argLength: 2, reg: gp2hilo, asm: "DIV", typ: "(Int32,Int32)"}, // arg0 / arg1, signed, results hi=arg0%arg1,lo=arg0/arg1
+ {name: "DIVU", argLength: 2, reg: gp2hilo, asm: "DIVU", typ: "(UInt32,UInt32)"}, // arg0 / arg1, signed, results hi=arg0%arg1,lo=arg0/arg1
+
+ {name: "ADDF", argLength: 2, reg: fp21, asm: "ADDF", commutative: true}, // arg0 + arg1
+ {name: "ADDD", argLength: 2, reg: fp21, asm: "ADDD", commutative: true}, // arg0 + arg1
+ {name: "SUBF", argLength: 2, reg: fp21, asm: "SUBF"}, // arg0 - arg1
+ {name: "SUBD", argLength: 2, reg: fp21, asm: "SUBD"}, // arg0 - arg1
+ {name: "MULF", argLength: 2, reg: fp21, asm: "MULF", commutative: true}, // arg0 * arg1
+ {name: "MULD", argLength: 2, reg: fp21, asm: "MULD", commutative: true}, // arg0 * arg1
+ {name: "DIVF", argLength: 2, reg: fp21, asm: "DIVF"}, // arg0 / arg1
+ {name: "DIVD", argLength: 2, reg: fp21, asm: "DIVD"}, // arg0 / arg1
+
+ {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0 & arg1
+ {name: "ANDconst", argLength: 1, reg: gp11, asm: "AND", aux: "Int32"}, // arg0 & auxInt
+ {name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true}, // arg0 | arg1
+ {name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int32"}, // arg0 | auxInt
+ {name: "XOR", argLength: 2, reg: gp21, asm: "XOR", commutative: true, typ: "UInt32"}, // arg0 ^ arg1
+ {name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int32", typ: "UInt32"}, // arg0 ^ auxInt
+ {name: "NOR", argLength: 2, reg: gp21, asm: "NOR", commutative: true}, // ^(arg0 | arg1)
+ {name: "NORconst", argLength: 1, reg: gp11, asm: "NOR", aux: "Int32"}, // ^(arg0 | auxInt)
+
+ {name: "NEG", argLength: 1, reg: gp11}, // -arg0
+ {name: "NEGF", argLength: 1, reg: fp11, asm: "NEGF"}, // -arg0, float32
+ {name: "NEGD", argLength: 1, reg: fp11, asm: "NEGD"}, // -arg0, float64
+ {name: "SQRTD", argLength: 1, reg: fp11, asm: "SQRTD"}, // sqrt(arg0), float64
+
+ // shifts
+ {name: "SLL", argLength: 2, reg: gp21, asm: "SLL"}, // arg0 << arg1, shift amount is mod 32
+ {name: "SLLconst", argLength: 1, reg: gp11, asm: "SLL", aux: "Int32"}, // arg0 << auxInt, shift amount must be 0 through 31 inclusive
+ {name: "SRL", argLength: 2, reg: gp21, asm: "SRL"}, // arg0 >> arg1, unsigned, shift amount is mod 32
+ {name: "SRLconst", argLength: 1, reg: gp11, asm: "SRL", aux: "Int32"}, // arg0 >> auxInt, shift amount must be 0 through 31 inclusive
+ {name: "SRA", argLength: 2, reg: gp21, asm: "SRA"}, // arg0 >> arg1, signed, shift amount is mod 32
+ {name: "SRAconst", argLength: 1, reg: gp11, asm: "SRA", aux: "Int32"}, // arg0 >> auxInt, signed, shift amount must be 0 through 31 inclusive
+
+ {name: "CLZ", argLength: 1, reg: gp11, asm: "CLZ"},
+
+ // comparisons
+ {name: "SGT", argLength: 2, reg: gp21, asm: "SGT", typ: "Bool"}, // 1 if arg0 > arg1 (signed), 0 otherwise
+ {name: "SGTconst", argLength: 1, reg: gp11, asm: "SGT", aux: "Int32", typ: "Bool"}, // 1 if auxInt > arg0 (signed), 0 otherwise
+ {name: "SGTzero", argLength: 1, reg: gp11, asm: "SGT", typ: "Bool"}, // 1 if arg0 > 0 (signed), 0 otherwise
+ {name: "SGTU", argLength: 2, reg: gp21, asm: "SGTU", typ: "Bool"}, // 1 if arg0 > arg1 (unsigned), 0 otherwise
+ {name: "SGTUconst", argLength: 1, reg: gp11, asm: "SGTU", aux: "Int32", typ: "Bool"}, // 1 if auxInt > arg0 (unsigned), 0 otherwise
+ {name: "SGTUzero", argLength: 1, reg: gp11, asm: "SGTU", typ: "Bool"}, // 1 if arg0 > 0 (unsigned), 0 otherwise
+
+ {name: "CMPEQF", argLength: 2, reg: fp2flags, asm: "CMPEQF", typ: "Flags"}, // flags=true if arg0 = arg1, float32
+ {name: "CMPEQD", argLength: 2, reg: fp2flags, asm: "CMPEQD", typ: "Flags"}, // flags=true if arg0 = arg1, float64
+ {name: "CMPGEF", argLength: 2, reg: fp2flags, asm: "CMPGEF", typ: "Flags"}, // flags=true if arg0 >= arg1, float32
+ {name: "CMPGED", argLength: 2, reg: fp2flags, asm: "CMPGED", typ: "Flags"}, // flags=true if arg0 >= arg1, float64
+ {name: "CMPGTF", argLength: 2, reg: fp2flags, asm: "CMPGTF", typ: "Flags"}, // flags=true if arg0 > arg1, float32
+ {name: "CMPGTD", argLength: 2, reg: fp2flags, asm: "CMPGTD", typ: "Flags"}, // flags=true if arg0 > arg1, float64
+
+ // moves
+ {name: "MOVWconst", argLength: 0, reg: gp01, aux: "Int32", asm: "MOVW", typ: "UInt32", rematerializeable: true}, // auxint
+ {name: "MOVFconst", argLength: 0, reg: fp01, aux: "Float32", asm: "MOVF", typ: "Float32", rematerializeable: true}, // auxint as 64-bit float, convert to 32-bit float
+ {name: "MOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVD", typ: "Float64", rematerializeable: true}, // auxint as 64-bit float
+
+ {name: "MOVWaddr", argLength: 1, reg: regInfo{inputs: []regMask{buildReg("SP") | buildReg("SB")}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVW", rematerializeable: true, symEffect: "Addr"}, // arg0 + auxInt + aux.(*gc.Sym), arg0=SP/SB
+
+ {name: "MOVBload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVB", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVBUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVBU", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVH", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVHU", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVWload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVW", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVFload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVF", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVDload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVD", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"}, // load from arg0 + auxInt + aux. arg1=mem.
+
+ {name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 1 byte of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVFstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVF", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+ {name: "MOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
+
+ {name: "MOVBstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 1 byte of zero to arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVHstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes of zero to arg0 + auxInt + aux. arg1=mem.
+ {name: "MOVWstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of zero to arg0 + auxInt + aux. arg1=mem.
+
+ // conversions
+ {name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB"}, // move from arg0, sign-extended from byte
+ {name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // move from arg0, unsign-extended from byte
+ {name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVH"}, // move from arg0, sign-extended from half
+ {name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // move from arg0, unsign-extended from half
+ {name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"}, // move from arg0
+
+ {name: "MOVWnop", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // nop, return arg0 in same register
+
+ // conditional move on zero (returns arg1 if arg2 is 0, otherwise arg0)
+ // order of parameters is reversed so we can use resultInArg0 (OpCMOVZ result arg1 arg2-> CMOVZ arg2reg, arg1reg, resultReg)
+ {name: "CMOVZ", argLength: 3, reg: gp31, asm: "CMOVZ", resultInArg0: true},
+ {name: "CMOVZzero", argLength: 2, reg: regInfo{inputs: []regMask{gp, gpg}, outputs: []regMask{gp}}, asm: "CMOVZ", resultInArg0: true},
+
+ {name: "MOVWF", argLength: 1, reg: fp11, asm: "MOVWF"}, // int32 -> float32
+ {name: "MOVWD", argLength: 1, reg: fp11, asm: "MOVWD"}, // int32 -> float64
+ {name: "TRUNCFW", argLength: 1, reg: fp11, asm: "TRUNCFW"}, // float32 -> int32
+ {name: "TRUNCDW", argLength: 1, reg: fp11, asm: "TRUNCDW"}, // float64 -> int32
+ {name: "MOVFD", argLength: 1, reg: fp11, asm: "MOVFD"}, // float32 -> float64
+ {name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
+
+ // function calls
+ {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
+ {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
+ {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
+
+ // atomic ops
+
+ // load from arg0. arg1=mem.
+ // returns <value,memory> so they can be properly ordered with other loads.
+ // SYNC
+ // MOV(B|W) (Rarg0), Rout
+ // SYNC
+ {name: "LoweredAtomicLoad8", argLength: 2, reg: gpload, faultOnNilArg0: true},
+ {name: "LoweredAtomicLoad32", argLength: 2, reg: gpload, faultOnNilArg0: true},
+
+ // store arg1 to arg0. arg2=mem. returns memory.
+ // SYNC
+ // MOV(B|W) Rarg1, (Rarg0)
+ // SYNC
+ {name: "LoweredAtomicStore8", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicStorezero", argLength: 2, reg: gpstore0, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic exchange.
+ // store arg1 to arg0. arg2=mem. returns <old content of *arg0, memory>.
+ // SYNC
+ // LL (Rarg0), Rout
+ // MOVW Rarg1, Rtmp
+ // SC Rtmp, (Rarg0)
+ // BEQ Rtmp, -3(PC)
+ // SYNC
+ {name: "LoweredAtomicExchange", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // atomic add.
+ // *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>.
+ // SYNC
+ // LL (Rarg0), Rout
+ // ADDU Rarg1, Rout, Rtmp
+ // SC Rtmp, (Rarg0)
+ // BEQ Rtmp, -3(PC)
+ // SYNC
+ // ADDU Rarg1, Rout
+ {name: "LoweredAtomicAdd", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicAddconst", argLength: 2, reg: regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}, aux: "Int32", resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // atomic compare and swap.
+ // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory.
+ // if *arg0 == arg1 {
+ // *arg0 = arg2
+ // return (true, memory)
+ // } else {
+ // return (false, memory)
+ // }
+ // SYNC
+ // MOVW $0, Rout
+ // LL (Rarg0), Rtmp
+ // BNE Rtmp, Rarg1, 4(PC)
+ // MOVW Rarg2, Rout
+ // SC Rout, (Rarg0)
+ // BEQ Rout, -4(PC)
+ // SYNC
+ {name: "LoweredAtomicCas", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // atomic and/or.
+ // *arg0 &= (|=) arg1. arg2=mem. returns memory.
+ // SYNC
+ // LL (Rarg0), Rtmp
+ // AND Rarg1, Rtmp
+ // SC Rtmp, (Rarg0)
+ // BEQ Rtmp, -3(PC)
+ // SYNC
+ {name: "LoweredAtomicAnd", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicOr", argLength: 3, reg: gpstore, asm: "OR", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // large or unaligned zeroing
+ // arg0 = address of memory to zero (in R1, changed as side effect)
+ // arg1 = address of the last element to zero
+ // arg2 = mem
+ // auxint = alignment
+ // returns mem
+ // SUBU $4, R1
+ // MOVW R0, 4(R1)
+ // ADDU $4, R1
+ // BNE Rarg1, R1, -2(PC)
+ {
+ name: "LoweredZero",
+ aux: "Int32",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R1"), gp},
+ clobbers: buildReg("R1"),
+ },
+ faultOnNilArg0: true,
+ },
+
+ // large or unaligned move
+ // arg0 = address of dst memory (in R2, changed as side effect)
+ // arg1 = address of src memory (in R1, changed as side effect)
+ // arg2 = address of the last element of src
+ // arg3 = mem
+ // auxint = alignment
+ // returns mem
+ // SUBU $4, R1
+ // MOVW 4(R1), Rtmp
+ // MOVW Rtmp, (R2)
+ // ADDU $4, R1
+ // ADDU $4, R2
+ // BNE Rarg2, R1, -4(PC)
+ {
+ name: "LoweredMove",
+ aux: "Int32",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R2"), buildReg("R1"), gp},
+ clobbers: buildReg("R1 R2"),
+ },
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // pseudo-ops
+ {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem.
+
+ {name: "FPFlagTrue", argLength: 1, reg: readflags}, // bool, true if FP flag is true
+ {name: "FPFlagFalse", argLength: 1, reg: readflags}, // bool, true if FP flag is false
+
+ // Scheduler ensures LoweredGetClosurePtr occurs only in entry block,
+ // and sorts it to the very beginning of the block to prevent other
+ // use of R22 (mips.REGCTXT, the closure pointer)
+ {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R22")}}, zeroWidth: true},
+
+ // LoweredGetCallerSP returns the SP of the caller of the current function.
+ {name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
+
+ // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+ // I.e., if f calls g "calls" getcallerpc,
+ // the result should be the PC within f that g will return to.
+ // See runtime/stubs.go for a more detailed discussion.
+ {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
+
+ // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+ // It saves all GP registers if necessary,
+ // but clobbers R31 (LR) because it's a call
+ // and R23 (REGTMP).
+ {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R20"), buildReg("R21")}, clobbers: (callerSave &^ gpg) | buildReg("R31")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
+
+ // There are three of these functions so that they can have three different register inputs.
+ // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
+ // default registers to match so we don't need to copy registers around unnecessarily.
+ {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r3, r4}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ // Extend ops are the same as Bounds ops except the indexes are 64-bit.
+ {name: "LoweredPanicExtendA", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r5, r3, r4}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
+ {name: "LoweredPanicExtendB", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r5, r2, r3}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
+ {name: "LoweredPanicExtendC", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r5, r1, r2}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
+ }
+
+ blocks := []blockData{
+ {name: "EQ", controls: 1},
+ {name: "NE", controls: 1},
+ {name: "LTZ", controls: 1}, // < 0
+ {name: "LEZ", controls: 1}, // <= 0
+ {name: "GTZ", controls: 1}, // > 0
+ {name: "GEZ", controls: 1}, // >= 0
+ {name: "FPT", controls: 1}, // FP flag is true
+ {name: "FPF", controls: 1}, // FP flag is false
+ }
+
+ archs = append(archs, arch{
+ name: "MIPS",
+ pkg: "cmd/internal/obj/mips",
+ genfile: "../../mips/ssa.go",
+ ops: ops,
+ blocks: blocks,
+ regnames: regNamesMIPS,
+ gpregmask: gp,
+ fpregmask: fp,
+ specialregmask: hi | lo,
+ framepointerreg: -1, // not used
+ linkreg: int8(num["R31"]),
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules
new file mode 100644
index 0000000..c064046
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules
@@ -0,0 +1,1461 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Lowering arithmetic
+(Add(Ptr|64|32|16|8) ...) => (ADD ...)
+(Add64F ...) => (FADD ...)
+(Add32F ...) => (FADDS ...)
+
+(Sub(Ptr|64|32|16|8) ...) => (SUB ...)
+(Sub32F ...) => (FSUBS ...)
+(Sub64F ...) => (FSUB ...)
+
+// Combine 64 bit integer multiply and adds
+(ADD l:(MULLD x y) z) && objabi.GOPPC64 >= 9 && l.Uses == 1 && clobber(l) => (MADDLD x y z)
+
+(Mod16 x y) => (Mod32 (SignExt16to32 x) (SignExt16to32 y))
+(Mod16u x y) => (Mod32u (ZeroExt16to32 x) (ZeroExt16to32 y))
+(Mod8 x y) => (Mod32 (SignExt8to32 x) (SignExt8to32 y))
+(Mod8u x y) => (Mod32u (ZeroExt8to32 x) (ZeroExt8to32 y))
+(Mod64 x y) && objabi.GOPPC64 >=9 => (MODSD x y)
+(Mod64 x y) && objabi.GOPPC64 <=8 => (SUB x (MULLD y (DIVD x y)))
+(Mod64u x y) && objabi.GOPPC64 >= 9 => (MODUD x y)
+(Mod64u x y) && objabi.GOPPC64 <= 8 => (SUB x (MULLD y (DIVDU x y)))
+(Mod32 x y) && objabi.GOPPC64 >= 9 => (MODSW x y)
+(Mod32 x y) && objabi.GOPPC64 <= 8 => (SUB x (MULLW y (DIVW x y)))
+(Mod32u x y) && objabi.GOPPC64 >= 9 => (MODUW x y)
+(Mod32u x y) && objabi.GOPPC64 <= 8 => (SUB x (MULLW y (DIVWU x y)))
+
+// (x + y) / 2 with x>=y => (x - y) / 2 + y
+(Avg64u <t> x y) => (ADD (SRDconst <t> (SUB <t> x y) [1]) y)
+
+(Add64carry ...) => (LoweredAdd64Carry ...)
+(Mul64 ...) => (MULLD ...)
+(Mul(32|16|8) ...) => (MULLW ...)
+(Mul64uhilo ...) => (LoweredMuluhilo ...)
+
+(Div64 [false] x y) => (DIVD x y)
+(Div64u ...) => (DIVDU ...)
+(Div32 [false] x y) => (DIVW x y)
+(Div32u ...) => (DIVWU ...)
+(Div16 [false] x y) => (DIVW (SignExt16to32 x) (SignExt16to32 y))
+(Div16u x y) => (DIVWU (ZeroExt16to32 x) (ZeroExt16to32 y))
+(Div8 x y) => (DIVW (SignExt8to32 x) (SignExt8to32 y))
+(Div8u x y) => (DIVWU (ZeroExt8to32 x) (ZeroExt8to32 y))
+
+(Hmul(64|64u|32|32u) ...) => (MULH(D|DU|W|WU) ...)
+
+(Mul32F ...) => (FMULS ...)
+(Mul64F ...) => (FMUL ...)
+
+(Div32F ...) => (FDIVS ...)
+(Div64F ...) => (FDIV ...)
+
+// Lowering float <=> int
+(Cvt32to32F x) => (FCFIDS (MTVSRD (SignExt32to64 x)))
+(Cvt32to64F x) => (FCFID (MTVSRD (SignExt32to64 x)))
+(Cvt64to32F x) => (FCFIDS (MTVSRD x))
+(Cvt64to64F x) => (FCFID (MTVSRD x))
+
+(Cvt32Fto32 x) => (MFVSRD (FCTIWZ x))
+(Cvt32Fto64 x) => (MFVSRD (FCTIDZ x))
+(Cvt64Fto32 x) => (MFVSRD (FCTIWZ x))
+(Cvt64Fto64 x) => (MFVSRD (FCTIDZ x))
+
+(Cvt32Fto64F ...) => (Copy ...) // Note v will have the wrong type for patterns dependent on Float32/Float64
+(Cvt64Fto32F ...) => (FRSP ...)
+
+(CvtBoolToUint8 ...) => (Copy ...)
+
+(Round(32|64)F ...) => (LoweredRound(32|64)F ...)
+
+(Sqrt ...) => (FSQRT ...)
+(Floor ...) => (FFLOOR ...)
+(Ceil ...) => (FCEIL ...)
+(Trunc ...) => (FTRUNC ...)
+(Round ...) => (FROUND ...)
+(Copysign x y) => (FCPSGN y x)
+(Abs ...) => (FABS ...)
+(FMA ...) => (FMADD ...)
+
+// Lowering extension
+// Note: we always extend to 64 bits even though some ops don't need that many result bits.
+(SignExt8to(16|32|64) ...) => (MOVBreg ...)
+(SignExt16to(32|64) ...) => (MOVHreg ...)
+(SignExt32to64 ...) => (MOVWreg ...)
+
+(ZeroExt8to(16|32|64) ...) => (MOVBZreg ...)
+(ZeroExt16to(32|64) ...) => (MOVHZreg ...)
+(ZeroExt32to64 ...) => (MOVWZreg ...)
+
+(Trunc(16|32|64)to8 <t> x) && isSigned(t) => (MOVBreg x)
+(Trunc(16|32|64)to8 x) => (MOVBZreg x)
+(Trunc(32|64)to16 <t> x) && isSigned(t) => (MOVHreg x)
+(Trunc(32|64)to16 x) => (MOVHZreg x)
+(Trunc64to32 <t> x) && isSigned(t) => (MOVWreg x)
+(Trunc64to32 x) => (MOVWZreg x)
+
+// Lowering constants
+(Const(64|32|16|8) [val]) => (MOVDconst [int64(val)])
+(Const(32|64)F ...) => (FMOV(S|D)const ...)
+(ConstNil) => (MOVDconst [0])
+(ConstBool [b]) => (MOVDconst [b2i(b)])
+
+// Constant folding
+(FABS (FMOVDconst [x])) => (FMOVDconst [math.Abs(x)])
+(FSQRT (FMOVDconst [x])) && x >= 0 => (FMOVDconst [math.Sqrt(x)])
+(FFLOOR (FMOVDconst [x])) => (FMOVDconst [math.Floor(x)])
+(FCEIL (FMOVDconst [x])) => (FMOVDconst [math.Ceil(x)])
+(FTRUNC (FMOVDconst [x])) => (FMOVDconst [math.Trunc(x)])
+
+// Rotates
+(RotateLeft8 <t> x (MOVDconst [c])) => (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
+(RotateLeft16 <t> x (MOVDconst [c])) => (Or16 (Lsh16x64 <t> x (MOVDconst [c&15])) (Rsh16Ux64 <t> x (MOVDconst [-c&15])))
+(RotateLeft32 x (MOVDconst [c])) => (ROTLWconst [c&31] x)
+(RotateLeft64 x (MOVDconst [c])) => (ROTLconst [c&63] x)
+
+// Rotate generation with const shift
+(ADD (SLDconst x [c]) (SRDconst x [d])) && d == 64-c => (ROTLconst [c] x)
+( OR (SLDconst x [c]) (SRDconst x [d])) && d == 64-c => (ROTLconst [c] x)
+(XOR (SLDconst x [c]) (SRDconst x [d])) && d == 64-c => (ROTLconst [c] x)
+
+(ADD (SLWconst x [c]) (SRWconst x [d])) && d == 32-c => (ROTLWconst [c] x)
+( OR (SLWconst x [c]) (SRWconst x [d])) && d == 32-c => (ROTLWconst [c] x)
+(XOR (SLWconst x [c]) (SRWconst x [d])) && d == 32-c => (ROTLWconst [c] x)
+
+// Rotate generation with non-const shift
+// these match patterns from math/bits/RotateLeft[32|64], but there could be others
+(ADD (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))) => (ROTL x y)
+(ADD (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))) => (ROTL x y)
+( OR (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))) => (ROTL x y)
+( OR (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))) => (ROTL x y)
+(XOR (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))) => (ROTL x y)
+(XOR (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))) => (ROTL x y)
+
+
+(ADD (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))) => (ROTLW x y)
+(ADD (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))) => (ROTLW x y)
+( OR (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))) => (ROTLW x y)
+( OR (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))) => (ROTLW x y)
+(XOR (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))) => (ROTLW x y)
+(XOR (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))) => (ROTLW x y)
+
+
+// Lowering rotates
+(RotateLeft32 x y) => (ROTLW x y)
+(RotateLeft64 x y) => (ROTL x y)
+
+// Constant rotate generation
+(ROTLW x (MOVDconst [c])) => (ROTLWconst x [c&31])
+(ROTL x (MOVDconst [c])) => (ROTLconst x [c&63])
+
+// Combine rotate and mask operations
+(ANDconst [m] (ROTLWconst [r] x)) && isPPC64WordRotateMask(m) => (RLWINM [encodePPC64RotateMask(r,m,32)] x)
+(AND (MOVDconst [m]) (ROTLWconst [r] x)) && isPPC64WordRotateMask(m) => (RLWINM [encodePPC64RotateMask(r,m,32)] x)
+(ANDconst [m] (ROTLW x r)) && isPPC64WordRotateMask(m) => (RLWNM [encodePPC64RotateMask(0,m,32)] x r)
+(AND (MOVDconst [m]) (ROTLW x r)) && isPPC64WordRotateMask(m) => (RLWNM [encodePPC64RotateMask(0,m,32)] x r)
+
+// Note, any rotated word bitmask is still a valid word bitmask.
+(ROTLWconst [r] (AND (MOVDconst [m]) x)) && isPPC64WordRotateMask(m) => (RLWINM [encodePPC64RotateMask(r,rotateLeft32(m,r),32)] x)
+(ROTLWconst [r] (ANDconst [m] x)) && isPPC64WordRotateMask(m) => (RLWINM [encodePPC64RotateMask(r,rotateLeft32(m,r),32)] x)
+
+(ANDconst [m] (SRWconst x [s])) && mergePPC64RShiftMask(m,s,32) == 0 => (MOVDconst [0])
+(ANDconst [m] (SRWconst x [s])) && mergePPC64AndSrwi(m,s) != 0 => (RLWINM [mergePPC64AndSrwi(m,s)] x)
+(AND (MOVDconst [m]) (SRWconst x [s])) && mergePPC64RShiftMask(m,s,32) == 0 => (MOVDconst [0])
+(AND (MOVDconst [m]) (SRWconst x [s])) && mergePPC64AndSrwi(m,s) != 0 => (RLWINM [mergePPC64AndSrwi(m,s)] x)
+
+(SRWconst (ANDconst [m] x) [s]) && mergePPC64RShiftMask(m>>uint(s),s,32) == 0 => (MOVDconst [0])
+(SRWconst (ANDconst [m] x) [s]) && mergePPC64AndSrwi(m>>uint(s),s) != 0 => (RLWINM [mergePPC64AndSrwi(m>>uint(s),s)] x)
+(SRWconst (AND (MOVDconst [m]) x) [s]) && mergePPC64RShiftMask(m>>uint(s),s,32) == 0 => (MOVDconst [0])
+(SRWconst (AND (MOVDconst [m]) x) [s]) && mergePPC64AndSrwi(m>>uint(s),s) != 0 => (RLWINM [mergePPC64AndSrwi(m>>uint(s),s)] x)
+
+// Merge shift right + shift left and clear left (e.g for a table lookup)
+(CLRLSLDI [c] (SRWconst [s] x)) && mergePPC64ClrlsldiSrw(int64(c),s) != 0 => (RLWINM [mergePPC64ClrlsldiSrw(int64(c),s)] x)
+(SLDconst [l] (SRWconst [r] x)) && mergePPC64SldiSrw(l,r) != 0 => (RLWINM [mergePPC64SldiSrw(l,r)] x)
+// The following reduction shows up frequently too. e.g b[(x>>14)&0xFF]
+(CLRLSLDI [c] i:(RLWINM [s] x)) && mergePPC64ClrlsldiRlwinm(c,s) != 0 => (RLWINM [mergePPC64ClrlsldiRlwinm(c,s)] x)
+
+// large constant shifts
+(Lsh64x64 _ (MOVDconst [c])) && uint64(c) >= 64 => (MOVDconst [0])
+(Rsh64Ux64 _ (MOVDconst [c])) && uint64(c) >= 64 => (MOVDconst [0])
+(Lsh32x64 _ (MOVDconst [c])) && uint64(c) >= 32 => (MOVDconst [0])
+(Rsh32Ux64 _ (MOVDconst [c])) && uint64(c) >= 32 => (MOVDconst [0])
+(Lsh16x64 _ (MOVDconst [c])) && uint64(c) >= 16 => (MOVDconst [0])
+(Rsh16Ux64 _ (MOVDconst [c])) && uint64(c) >= 16 => (MOVDconst [0])
+(Lsh8x64 _ (MOVDconst [c])) && uint64(c) >= 8 => (MOVDconst [0])
+(Rsh8Ux64 _ (MOVDconst [c])) && uint64(c) >= 8 => (MOVDconst [0])
+
+// large constant signed right shift, we leave the sign bit
+(Rsh64x64 x (MOVDconst [c])) && uint64(c) >= 64 => (SRADconst x [63])
+(Rsh32x64 x (MOVDconst [c])) && uint64(c) >= 32 => (SRAWconst x [63])
+(Rsh16x64 x (MOVDconst [c])) && uint64(c) >= 16 => (SRAWconst (SignExt16to32 x) [63])
+(Rsh8x64 x (MOVDconst [c])) && uint64(c) >= 8 => (SRAWconst (SignExt8to32 x) [63])
+
+// constant shifts
+(Lsh64x64 x (MOVDconst [c])) && uint64(c) < 64 => (SLDconst x [c])
+(Rsh64x64 x (MOVDconst [c])) && uint64(c) < 64 => (SRADconst x [c])
+(Rsh64Ux64 x (MOVDconst [c])) && uint64(c) < 64 => (SRDconst x [c])
+(Lsh32x64 x (MOVDconst [c])) && uint64(c) < 32 => (SLWconst x [c])
+(Rsh32x64 x (MOVDconst [c])) && uint64(c) < 32 => (SRAWconst x [c])
+(Rsh32Ux64 x (MOVDconst [c])) && uint64(c) < 32 => (SRWconst x [c])
+(Lsh16x64 x (MOVDconst [c])) && uint64(c) < 16 => (SLWconst x [c])
+(Rsh16x64 x (MOVDconst [c])) && uint64(c) < 16 => (SRAWconst (SignExt16to32 x) [c])
+(Rsh16Ux64 x (MOVDconst [c])) && uint64(c) < 16 => (SRWconst (ZeroExt16to32 x) [c])
+(Lsh8x64 x (MOVDconst [c])) && uint64(c) < 8 => (SLWconst x [c])
+(Rsh8x64 x (MOVDconst [c])) && uint64(c) < 8 => (SRAWconst (SignExt8to32 x) [c])
+(Rsh8Ux64 x (MOVDconst [c])) && uint64(c) < 8 => (SRWconst (ZeroExt8to32 x) [c])
+
+(Lsh64x32 x (MOVDconst [c])) && uint32(c) < 64 => (SLDconst x [c&63])
+(Rsh64x32 x (MOVDconst [c])) && uint32(c) < 64 => (SRADconst x [c&63])
+(Rsh64Ux32 x (MOVDconst [c])) && uint32(c) < 64 => (SRDconst x [c&63])
+(Lsh32x32 x (MOVDconst [c])) && uint32(c) < 32 => (SLWconst x [c&31])
+(Rsh32x32 x (MOVDconst [c])) && uint32(c) < 32 => (SRAWconst x [c&31])
+(Rsh32Ux32 x (MOVDconst [c])) && uint32(c) < 32 => (SRWconst x [c&31])
+(Lsh16x32 x (MOVDconst [c])) && uint32(c) < 16 => (SLWconst x [c&31])
+(Rsh16x32 x (MOVDconst [c])) && uint32(c) < 16 => (SRAWconst (SignExt16to32 x) [c&15])
+(Rsh16Ux32 x (MOVDconst [c])) && uint32(c) < 16 => (SRWconst (ZeroExt16to32 x) [c&15])
+(Lsh8x32 x (MOVDconst [c])) && uint32(c) < 8 => (SLWconst x [c&7])
+(Rsh8x32 x (MOVDconst [c])) && uint32(c) < 8 => (SRAWconst (SignExt8to32 x) [c&7])
+(Rsh8Ux32 x (MOVDconst [c])) && uint32(c) < 8 => (SRWconst (ZeroExt8to32 x) [c&7])
+
+// Lower bounded shifts first. No need to check shift value.
+(Lsh64x(64|32|16|8) x y) && shiftIsBounded(v) => (SLD x y)
+(Lsh32x(64|32|16|8) x y) && shiftIsBounded(v) => (SLW x y)
+(Lsh16x(64|32|16|8) x y) && shiftIsBounded(v) => (SLW x y)
+(Lsh8x(64|32|16|8) x y) && shiftIsBounded(v) => (SLW x y)
+(Rsh64Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SRD x y)
+(Rsh32Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SRW x y)
+(Rsh16Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SRW (MOVHZreg x) y)
+(Rsh8Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SRW (MOVBZreg x) y)
+(Rsh64x(64|32|16|8) x y) && shiftIsBounded(v) => (SRAD x y)
+(Rsh32x(64|32|16|8) x y) && shiftIsBounded(v) => (SRAW x y)
+(Rsh16x(64|32|16|8) x y) && shiftIsBounded(v) => (SRAW (MOVHreg x) y)
+(Rsh8x(64|32|16|8) x y) && shiftIsBounded(v) => (SRAW (MOVBreg x) y)
+
+// non-constant rotates
+// These are subexpressions found in statements that can become rotates
+// In these cases the shift count is known to be < 64 so the more complicated expressions
+// with Mask & Carry is not needed
+(Lsh64x64 x (AND y (MOVDconst [63]))) => (SLD x (ANDconst <typ.Int64> [63] y))
+(Lsh64x64 x (ANDconst <typ.Int64> [63] y)) => (SLD x (ANDconst <typ.Int64> [63] y))
+(Rsh64Ux64 x (AND y (MOVDconst [63]))) => (SRD x (ANDconst <typ.Int64> [63] y))
+(Rsh64Ux64 x (ANDconst <typ.UInt> [63] y)) => (SRD x (ANDconst <typ.UInt> [63] y))
+(Rsh64Ux64 x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y))) => (SRD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))
+(Rsh64Ux64 x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y))) => (SRD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))
+(Rsh64Ux64 x (SUB <typ.UInt> (MOVDconst [64]) (AND <typ.UInt> y (MOVDconst [63])))) => (SRD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))
+(Rsh64Ux64 x (SUBFCconst <typ.UInt> [64] (AND <typ.UInt> y (MOVDconst [63])))) => (SRD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))
+(Rsh64x64 x (AND y (MOVDconst [63]))) => (SRAD x (ANDconst <typ.Int64> [63] y))
+(Rsh64x64 x (ANDconst <typ.UInt> [63] y)) => (SRAD x (ANDconst <typ.UInt> [63] y))
+(Rsh64x64 x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y))) => (SRAD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))
+(Rsh64x64 x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y))) => (SRAD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))
+(Rsh64x64 x (SUB <typ.UInt> (MOVDconst [64]) (AND <typ.UInt> y (MOVDconst [63])))) => (SRAD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))
+(Rsh64x64 x (SUBFCconst <typ.UInt> [64] (AND <typ.UInt> y (MOVDconst [63])))) => (SRAD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))
+
+(Lsh64x64 x y) => (SLD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+(Rsh64x64 x y) => (SRAD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+(Rsh64Ux64 x y) => (SRD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+
+(Lsh32x64 x (AND y (MOVDconst [31]))) => (SLW x (ANDconst <typ.Int32> [31] y))
+(Lsh32x64 x (ANDconst <typ.Int32> [31] y)) => (SLW x (ANDconst <typ.Int32> [31] y))
+
+(Rsh32Ux64 x (AND y (MOVDconst [31]))) => (SRW x (ANDconst <typ.Int32> [31] y))
+(Rsh32Ux64 x (ANDconst <typ.UInt> [31] y)) => (SRW x (ANDconst <typ.UInt> [31] y))
+(Rsh32Ux64 x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y))) => (SRW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))
+(Rsh32Ux64 x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y))) => (SRW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))
+(Rsh32Ux64 x (SUB <typ.UInt> (MOVDconst [32]) (AND <typ.UInt> y (MOVDconst [31])))) => (SRW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))
+(Rsh32Ux64 x (SUBFCconst <typ.UInt> [32] (AND <typ.UInt> y (MOVDconst [31])))) => (SRW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))
+
+(Rsh32x64 x (AND y (MOVDconst [31]))) => (SRAW x (ANDconst <typ.Int32> [31] y))
+(Rsh32x64 x (ANDconst <typ.UInt> [31] y)) => (SRAW x (ANDconst <typ.UInt> [31] y))
+(Rsh32x64 x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y))) => (SRAW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))
+(Rsh32x64 x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y))) => (SRAW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))
+(Rsh32x64 x (SUB <typ.UInt> (MOVDconst [32]) (AND <typ.UInt> y (MOVDconst [31])))) => (SRAW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))
+(Rsh32x64 x (SUBFCconst <typ.UInt> [32] (AND <typ.UInt> y (MOVDconst [31])))) => (SRAW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))
+
+(Rsh32x64 x y) => (SRAW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+(Rsh32Ux64 x y) => (SRW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+(Lsh32x64 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+
+(Rsh16x64 x y) => (SRAW (SignExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+(Rsh16Ux64 x y) => (SRW (ZeroExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+(Lsh16x64 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+
+(Rsh8x64 x y) => (SRAW (SignExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+(Rsh8Ux64 x y) => (SRW (ZeroExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+(Lsh8x64 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+
+(Rsh64x32 x y) => (SRAD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+(Rsh64Ux32 x y) => (SRD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+(Lsh64x32 x y) => (SLD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+(Rsh32x32 x y) => (SRAW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+(Rsh32Ux32 x y) => (SRW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+(Lsh32x32 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+
+(Rsh16x32 x y) => (SRAW (SignExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+(Rsh16Ux32 x y) => (SRW (ZeroExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+(Lsh16x32 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+
+(Rsh8x32 x y) => (SRAW (SignExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+(Rsh8Ux32 x y) => (SRW (ZeroExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+(Lsh8x32 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+
+
+(Rsh64x16 x y) => (SRAD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [64]))))
+(Rsh64Ux16 x y) => (SRD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [64]))))
+(Lsh64x16 x y) => (SLD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [64]))))
+
+(Rsh32x16 x y) => (SRAW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [32]))))
+(Rsh32Ux16 x y) => (SRW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [32]))))
+(Lsh32x16 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [32]))))
+
+(Rsh16x16 x y) => (SRAW (SignExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [16]))))
+(Rsh16Ux16 x y) => (SRW (ZeroExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [16]))))
+(Lsh16x16 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [16]))))
+
+(Rsh8x16 x y) => (SRAW (SignExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [8]))))
+(Rsh8Ux16 x y) => (SRW (ZeroExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [8]))))
+(Lsh8x16 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [8]))))
+
+
+(Rsh64x8 x y) => (SRAD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [64]))))
+(Rsh64Ux8 x y) => (SRD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [64]))))
+(Lsh64x8 x y) => (SLD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [64]))))
+
+(Rsh32x8 x y) => (SRAW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [32]))))
+(Rsh32Ux8 x y) => (SRW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [32]))))
+(Lsh32x8 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [32]))))
+
+(Rsh16x8 x y) => (SRAW (SignExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [16]))))
+(Rsh16Ux8 x y) => (SRW (ZeroExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [16]))))
+(Lsh16x8 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [16]))))
+
+(Rsh8x8 x y) => (SRAW (SignExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [8]))))
+(Rsh8Ux8 x y) => (SRW (ZeroExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [8]))))
+(Lsh8x8 x y) => (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [8]))))
+
+// Cleaning up shift ops
+(ISEL [0] (ANDconst [d] y) (MOVDconst [-1]) (CMPU (ANDconst [d] y) (MOVDconst [c]))) && c >= d => (ANDconst [d] y)
+(ISEL [0] (ANDconst [d] y) (MOVDconst [-1]) (CMPUconst [c] (ANDconst [d] y))) && c >= d => (ANDconst [d] y)
+(ORN x (MOVDconst [-1])) => x
+
+(S(RAD|RD|LD) x (MOVDconst [c])) => (S(RAD|RD|LD)const [c&63 | (c>>6&1*63)] x)
+(S(RAW|RW|LW) x (MOVDconst [c])) => (S(RAW|RW|LW)const [c&31 | (c>>5&1*31)] x)
+
+(Addr {sym} base) => (MOVDaddr {sym} [0] base)
+(LocalAddr {sym} base _) => (MOVDaddr {sym} base)
+(OffPtr [off] ptr) => (ADD (MOVDconst <typ.Int64> [off]) ptr)
+
+// TODO: optimize these cases?
+(Ctz32NonZero ...) => (Ctz32 ...)
+(Ctz64NonZero ...) => (Ctz64 ...)
+
+(Ctz64 x) && objabi.GOPPC64<=8 => (POPCNTD (ANDN <typ.Int64> (ADDconst <typ.Int64> [-1] x) x))
+(Ctz64 x) => (CNTTZD x)
+(Ctz32 x) && objabi.GOPPC64<=8 => (POPCNTW (MOVWZreg (ANDN <typ.Int> (ADDconst <typ.Int> [-1] x) x)))
+(Ctz32 x) => (CNTTZW (MOVWZreg x))
+(Ctz16 x) => (POPCNTW (MOVHZreg (ANDN <typ.Int16> (ADDconst <typ.Int16> [-1] x) x)))
+(Ctz8 x) => (POPCNTB (MOVBZreg (ANDN <typ.UInt8> (ADDconst <typ.UInt8> [-1] x) x)))
+
+(BitLen64 x) => (SUBFCconst [64] (CNTLZD <typ.Int> x))
+(BitLen32 x) => (SUBFCconst [32] (CNTLZW <typ.Int> x))
+
+(PopCount64 ...) => (POPCNTD ...)
+(PopCount32 x) => (POPCNTW (MOVWZreg x))
+(PopCount16 x) => (POPCNTW (MOVHZreg x))
+(PopCount8 x) => (POPCNTB (MOVBZreg x))
+
+(And(64|32|16|8) ...) => (AND ...)
+(Or(64|32|16|8) ...) => (OR ...)
+(Xor(64|32|16|8) ...) => (XOR ...)
+
+(Neg(64|32|16|8) ...) => (NEG ...)
+(Neg64F ...) => (FNEG ...)
+(Neg32F ...) => (FNEG ...)
+
+(Com(64|32|16|8) x) => (NOR x x)
+
+// Lowering boolean ops
+(AndB ...) => (AND ...)
+(OrB ...) => (OR ...)
+(Not x) => (XORconst [1] x)
+
+// Use ANDN for AND x NOT y
+(AND x (NOR y y)) => (ANDN x y)
+
+// Lowering comparisons
+(EqB x y) => (ANDconst [1] (EQV x y))
+// Sign extension dependence on operand sign sets up for sign/zero-extension elision later
+(Eq8 x y) && isSigned(x.Type) && isSigned(y.Type) => (Equal (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+(Eq16 x y) && isSigned(x.Type) && isSigned(y.Type) => (Equal (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+(Eq8 x y) => (Equal (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Eq16 x y) => (Equal (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Eq32 x y) => (Equal (CMPW x y))
+(Eq64 x y) => (Equal (CMP x y))
+(Eq32F x y) => (Equal (FCMPU x y))
+(Eq64F x y) => (Equal (FCMPU x y))
+(EqPtr x y) => (Equal (CMP x y))
+
+(NeqB ...) => (XOR ...)
+// Like Eq8 and Eq16, prefer sign extension likely to enable later elision.
+(Neq8 x y) && isSigned(x.Type) && isSigned(y.Type) => (NotEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+(Neq16 x y) && isSigned(x.Type) && isSigned(y.Type) => (NotEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+(Neq8 x y) => (NotEqual (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Neq16 x y) => (NotEqual (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Neq32 x y) => (NotEqual (CMPW x y))
+(Neq64 x y) => (NotEqual (CMP x y))
+(Neq32F x y) => (NotEqual (FCMPU x y))
+(Neq64F x y) => (NotEqual (FCMPU x y))
+(NeqPtr x y) => (NotEqual (CMP x y))
+
+(Less8 x y) => (LessThan (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+(Less16 x y) => (LessThan (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+(Less32 x y) => (LessThan (CMPW x y))
+(Less64 x y) => (LessThan (CMP x y))
+(Less32F x y) => (FLessThan (FCMPU x y))
+(Less64F x y) => (FLessThan (FCMPU x y))
+
+(Less8U x y) => (LessThan (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Less16U x y) => (LessThan (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Less32U x y) => (LessThan (CMPWU x y))
+(Less64U x y) => (LessThan (CMPU x y))
+
+(Leq8 x y) => (LessEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+(Leq16 x y) => (LessEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+(Leq32 x y) => (LessEqual (CMPW x y))
+(Leq64 x y) => (LessEqual (CMP x y))
+(Leq32F x y) => (FLessEqual (FCMPU x y))
+(Leq64F x y) => (FLessEqual (FCMPU x y))
+
+(Leq8U x y) => (LessEqual (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Leq16U x y) => (LessEqual (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Leq32U x y) => (LessEqual (CMPWU x y))
+(Leq64U x y) => (LessEqual (CMPU x y))
+
+// Absorb pseudo-ops into blocks.
+(If (Equal cc) yes no) => (EQ cc yes no)
+(If (NotEqual cc) yes no) => (NE cc yes no)
+(If (LessThan cc) yes no) => (LT cc yes no)
+(If (LessEqual cc) yes no) => (LE cc yes no)
+(If (GreaterThan cc) yes no) => (GT cc yes no)
+(If (GreaterEqual cc) yes no) => (GE cc yes no)
+(If (FLessThan cc) yes no) => (FLT cc yes no)
+(If (FLessEqual cc) yes no) => (FLE cc yes no)
+(If (FGreaterThan cc) yes no) => (FGT cc yes no)
+(If (FGreaterEqual cc) yes no) => (FGE cc yes no)
+
+(If cond yes no) => (NE (CMPWconst [0] cond) yes no)
+
+// Absorb boolean tests into block
+(NE (CMPWconst [0] (Equal cc)) yes no) => (EQ cc yes no)
+(NE (CMPWconst [0] (NotEqual cc)) yes no) => (NE cc yes no)
+(NE (CMPWconst [0] (LessThan cc)) yes no) => (LT cc yes no)
+(NE (CMPWconst [0] (LessEqual cc)) yes no) => (LE cc yes no)
+(NE (CMPWconst [0] (GreaterThan cc)) yes no) => (GT cc yes no)
+(NE (CMPWconst [0] (GreaterEqual cc)) yes no) => (GE cc yes no)
+(NE (CMPWconst [0] (FLessThan cc)) yes no) => (FLT cc yes no)
+(NE (CMPWconst [0] (FLessEqual cc)) yes no) => (FLE cc yes no)
+(NE (CMPWconst [0] (FGreaterThan cc)) yes no) => (FGT cc yes no)
+(NE (CMPWconst [0] (FGreaterEqual cc)) yes no) => (FGE cc yes no)
+
+// Elide compares of bit tests // TODO need to make both CC and result of ANDCC available.
+(EQ (CMPconst [0] (ANDconst [c] x)) yes no) => (EQ (ANDCCconst [c] x) yes no)
+(NE (CMPconst [0] (ANDconst [c] x)) yes no) => (NE (ANDCCconst [c] x) yes no)
+(EQ (CMPWconst [0] (ANDconst [c] x)) yes no) => (EQ (ANDCCconst [c] x) yes no)
+(NE (CMPWconst [0] (ANDconst [c] x)) yes no) => (NE (ANDCCconst [c] x) yes no)
+
+// absorb flag constants into branches
+(EQ (FlagEQ) yes no) => (First yes no)
+(EQ (FlagLT) yes no) => (First no yes)
+(EQ (FlagGT) yes no) => (First no yes)
+
+(NE (FlagEQ) yes no) => (First no yes)
+(NE (FlagLT) yes no) => (First yes no)
+(NE (FlagGT) yes no) => (First yes no)
+
+(LT (FlagEQ) yes no) => (First no yes)
+(LT (FlagLT) yes no) => (First yes no)
+(LT (FlagGT) yes no) => (First no yes)
+
+(LE (FlagEQ) yes no) => (First yes no)
+(LE (FlagLT) yes no) => (First yes no)
+(LE (FlagGT) yes no) => (First no yes)
+
+(GT (FlagEQ) yes no) => (First no yes)
+(GT (FlagLT) yes no) => (First no yes)
+(GT (FlagGT) yes no) => (First yes no)
+
+(GE (FlagEQ) yes no) => (First yes no)
+(GE (FlagLT) yes no) => (First no yes)
+(GE (FlagGT) yes no) => (First yes no)
+
+// 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)
+(EQ (InvertFlags cmp) yes no) => (EQ cmp yes no)
+(NE (InvertFlags cmp) yes no) => (NE cmp yes no)
+
+// constant comparisons
+(CMPWconst (MOVDconst [x]) [y]) && int32(x)==int32(y) => (FlagEQ)
+(CMPWconst (MOVDconst [x]) [y]) && int32(x)<int32(y) => (FlagLT)
+(CMPWconst (MOVDconst [x]) [y]) && int32(x)>int32(y) => (FlagGT)
+
+(CMPconst (MOVDconst [x]) [y]) && x==y => (FlagEQ)
+(CMPconst (MOVDconst [x]) [y]) && x<y => (FlagLT)
+(CMPconst (MOVDconst [x]) [y]) && x>y => (FlagGT)
+
+(CMPWUconst (MOVDconst [x]) [y]) && int32(x)==int32(y) => (FlagEQ)
+(CMPWUconst (MOVDconst [x]) [y]) && uint32(x)<uint32(y) => (FlagLT)
+(CMPWUconst (MOVDconst [x]) [y]) && uint32(x)>uint32(y) => (FlagGT)
+
+(CMPUconst (MOVDconst [x]) [y]) && x==y => (FlagEQ)
+(CMPUconst (MOVDconst [x]) [y]) && uint64(x)<uint64(y) => (FlagLT)
+(CMPUconst (MOVDconst [x]) [y]) && uint64(x)>uint64(y) => (FlagGT)
+
+// other known comparisons
+//(CMPconst (MOVBUreg _) [c]) && 0xff < c => (FlagLT)
+//(CMPconst (MOVHUreg _) [c]) && 0xffff < c => (FlagLT)
+//(CMPconst (ANDconst _ [m]) [n]) && 0 <= int32(m) && int32(m) < int32(n) => (FlagLT)
+//(CMPconst (SRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 32 && (1<<uint32(32-c)) <= uint32(n) => (FlagLT)
+
+// absorb flag constants into boolean values
+(Equal (FlagEQ)) => (MOVDconst [1])
+(Equal (FlagLT)) => (MOVDconst [0])
+(Equal (FlagGT)) => (MOVDconst [0])
+
+(NotEqual (FlagEQ)) => (MOVDconst [0])
+(NotEqual (FlagLT)) => (MOVDconst [1])
+(NotEqual (FlagGT)) => (MOVDconst [1])
+
+(LessThan (FlagEQ)) => (MOVDconst [0])
+(LessThan (FlagLT)) => (MOVDconst [1])
+(LessThan (FlagGT)) => (MOVDconst [0])
+
+(LessEqual (FlagEQ)) => (MOVDconst [1])
+(LessEqual (FlagLT)) => (MOVDconst [1])
+(LessEqual (FlagGT)) => (MOVDconst [0])
+
+(GreaterThan (FlagEQ)) => (MOVDconst [0])
+(GreaterThan (FlagLT)) => (MOVDconst [0])
+(GreaterThan (FlagGT)) => (MOVDconst [1])
+
+(GreaterEqual (FlagEQ)) => (MOVDconst [1])
+(GreaterEqual (FlagLT)) => (MOVDconst [0])
+(GreaterEqual (FlagGT)) => (MOVDconst [1])
+
+// absorb InvertFlags into boolean values
+(Equal (InvertFlags x)) => (Equal x)
+(NotEqual (InvertFlags x)) => (NotEqual x)
+(LessThan (InvertFlags x)) => (GreaterThan x)
+(GreaterThan (InvertFlags x)) => (LessThan x)
+(LessEqual (InvertFlags x)) => (GreaterEqual x)
+(GreaterEqual (InvertFlags x)) => (LessEqual x)
+
+// Elide compares of bit tests // TODO need to make both CC and result of ANDCC available.
+((EQ|NE|LT|LE|GT|GE) (CMPconst [0] (ANDconst [c] x)) yes no) => ((EQ|NE|LT|LE|GT|GE) (ANDCCconst [c] x) yes no)
+((EQ|NE|LT|LE|GT|GE) (CMPWconst [0] (ANDconst [c] x)) yes no) => ((EQ|NE|LT|LE|GT|GE) (ANDCCconst [c] x) yes no)
+((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => ((EQ|NE|LT|LE|GT|GE) (ANDCC x y) yes no)
+((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(OR x y)) yes no) && z.Uses == 1 => ((EQ|NE|LT|LE|GT|GE) (ORCC x y) yes no)
+((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(XOR x y)) yes no) && z.Uses == 1 => ((EQ|NE|LT|LE|GT|GE) (XORCC x y) yes no)
+
+(CondSelect x y bool) && flagArg(bool) != nil => (ISEL [2] x y bool)
+(CondSelect x y bool) && flagArg(bool) == nil => (ISEL [2] x y (CMPWconst [0] bool))
+
+// Lowering loads
+(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) => (MOVDload ptr mem)
+(Load <t> ptr mem) && is32BitInt(t) && isSigned(t) => (MOVWload ptr mem)
+(Load <t> ptr mem) && is32BitInt(t) && !isSigned(t) => (MOVWZload ptr mem)
+(Load <t> ptr mem) && is16BitInt(t) && isSigned(t) => (MOVHload ptr mem)
+(Load <t> ptr mem) && is16BitInt(t) && !isSigned(t) => (MOVHZload ptr mem)
+(Load <t> ptr mem) && t.IsBoolean() => (MOVBZload ptr mem)
+(Load <t> ptr mem) && is8BitInt(t) && isSigned(t) => (MOVBreg (MOVBZload ptr mem)) // PPC has no signed-byte load.
+(Load <t> ptr mem) && is8BitInt(t) && !isSigned(t) => (MOVBZload ptr mem)
+
+(Load <t> ptr mem) && is32BitFloat(t) => (FMOVSload ptr mem)
+(Load <t> ptr mem) && is64BitFloat(t) => (FMOVDload ptr mem)
+
+(Store {t} ptr val mem) && t.Size() == 8 && is64BitFloat(val.Type) => (FMOVDstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 && is32BitFloat(val.Type) => (FMOVDstore ptr val mem) // glitch from (Cvt32Fto64F x) => x -- type is wrong
+(Store {t} ptr val mem) && t.Size() == 4 && is32BitFloat(val.Type) => (FMOVSstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 && (is64BitInt(val.Type) || isPtr(val.Type)) => (MOVDstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && is32BitInt(val.Type) => (MOVWstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 2 => (MOVHstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 1 => (MOVBstore ptr val mem)
+
+// Using Zero instead of LoweredZero allows the
+// target address to be folded where possible.
+(Zero [0] _ mem) => mem
+(Zero [1] destptr mem) => (MOVBstorezero destptr mem)
+(Zero [2] destptr mem) =>
+ (MOVHstorezero destptr mem)
+(Zero [3] destptr mem) =>
+ (MOVBstorezero [2] destptr
+ (MOVHstorezero destptr mem))
+(Zero [4] destptr mem) =>
+ (MOVWstorezero destptr mem)
+(Zero [5] destptr mem) =>
+ (MOVBstorezero [4] destptr
+ (MOVWstorezero destptr mem))
+(Zero [6] destptr mem) =>
+ (MOVHstorezero [4] destptr
+ (MOVWstorezero destptr mem))
+(Zero [7] destptr mem) =>
+ (MOVBstorezero [6] destptr
+ (MOVHstorezero [4] destptr
+ (MOVWstorezero destptr mem)))
+
+// MOVD for store with DS must have offsets that are multiple of 4
+(Zero [8] {t} destptr mem) && t.Alignment()%4 == 0 =>
+ (MOVDstorezero destptr mem)
+(Zero [8] destptr mem) =>
+ (MOVWstorezero [4] destptr
+ (MOVWstorezero [0] destptr mem))
+// Handle these cases only if aligned properly, otherwise use general case below
+(Zero [12] {t} destptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstorezero [8] destptr
+ (MOVDstorezero [0] destptr mem))
+(Zero [16] {t} destptr mem) && t.Alignment()%4 == 0 =>
+ (MOVDstorezero [8] destptr
+ (MOVDstorezero [0] destptr mem))
+(Zero [24] {t} destptr mem) && t.Alignment()%4 == 0 =>
+ (MOVDstorezero [16] destptr
+ (MOVDstorezero [8] destptr
+ (MOVDstorezero [0] destptr mem)))
+(Zero [32] {t} destptr mem) && t.Alignment()%4 == 0 =>
+ (MOVDstorezero [24] destptr
+ (MOVDstorezero [16] destptr
+ (MOVDstorezero [8] destptr
+ (MOVDstorezero [0] destptr mem))))
+
+// Handle cases not handled above
+// Lowered Short cases do not generate loops, and as a result don't clobber
+// the address registers or flags.
+(Zero [s] ptr mem) && objabi.GOPPC64 <= 8 && s < 64 => (LoweredZeroShort [s] ptr mem)
+(Zero [s] ptr mem) && objabi.GOPPC64 <= 8 => (LoweredZero [s] ptr mem)
+(Zero [s] ptr mem) && s < 128 && objabi.GOPPC64 >= 9 => (LoweredQuadZeroShort [s] ptr mem)
+(Zero [s] ptr mem) && objabi.GOPPC64 >= 9 => (LoweredQuadZero [s] ptr mem)
+
+// moves
+// Only the MOVD and MOVW instructions require 4 byte
+// alignment in the offset field. The other MOVx instructions
+// allow any alignment.
+(Move [0] _ _ mem) => mem
+(Move [1] dst src mem) => (MOVBstore dst (MOVBZload src mem) mem)
+(Move [2] dst src mem) =>
+ (MOVHstore dst (MOVHZload src mem) mem)
+(Move [4] dst src mem) =>
+ (MOVWstore dst (MOVWZload src mem) mem)
+// MOVD for load and store must have offsets that are multiple of 4
+(Move [8] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVDstore dst (MOVDload src mem) mem)
+(Move [8] dst src mem) =>
+ (MOVWstore [4] dst (MOVWZload [4] src mem)
+ (MOVWstore dst (MOVWZload src mem) mem))
+(Move [3] dst src mem) =>
+ (MOVBstore [2] dst (MOVBZload [2] src mem)
+ (MOVHstore dst (MOVHload src mem) mem))
+(Move [5] dst src mem) =>
+ (MOVBstore [4] dst (MOVBZload [4] src mem)
+ (MOVWstore dst (MOVWZload src mem) mem))
+(Move [6] dst src mem) =>
+ (MOVHstore [4] dst (MOVHZload [4] src mem)
+ (MOVWstore dst (MOVWZload src mem) mem))
+(Move [7] dst src mem) =>
+ (MOVBstore [6] dst (MOVBZload [6] src mem)
+ (MOVHstore [4] dst (MOVHZload [4] src mem)
+ (MOVWstore dst (MOVWZload src mem) mem)))
+
+// Large move uses a loop. Since the address is computed and the
+// offset is zero, any alignment can be used.
+(Move [s] dst src mem) && s > 8 && objabi.GOPPC64 <= 8 && logLargeCopy(v, s) =>
+ (LoweredMove [s] dst src mem)
+(Move [s] dst src mem) && s > 8 && s <= 64 && objabi.GOPPC64 >= 9 =>
+ (LoweredQuadMoveShort [s] dst src mem)
+(Move [s] dst src mem) && s > 8 && objabi.GOPPC64 >= 9 && logLargeCopy(v, s) =>
+ (LoweredQuadMove [s] dst src mem)
+
+// Calls
+// Lowering calls
+(StaticCall ...) => (CALLstatic ...)
+(ClosureCall ...) => (CALLclosure ...)
+(InterCall ...) => (CALLinter ...)
+
+// Miscellaneous
+(GetClosurePtr ...) => (LoweredGetClosurePtr ...)
+(GetCallerSP ...) => (LoweredGetCallerSP ...)
+(GetCallerPC ...) => (LoweredGetCallerPC ...)
+(IsNonNil ptr) => (NotEqual (CMPconst [0] ptr))
+(IsInBounds idx len) => (LessThan (CMPU idx len))
+(IsSliceInBounds idx len) => (LessEqual (CMPU idx len))
+(NilCheck ...) => (LoweredNilCheck ...)
+
+// Write barrier.
+(WB ...) => (LoweredWB ...)
+
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
+
+// Optimizations
+// Note that PPC "logical" immediates come in 0:15 and 16:31 unsigned immediate forms,
+// so ORconst, XORconst easily expand into a pair.
+
+// Include very-large constants in the const-const case.
+(AND (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c&d])
+(OR (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c|d])
+(XOR (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c^d])
+(ORN (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c|^d])
+(ANDN (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c&^d])
+(NOR (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [^(c|d)])
+
+// Discover consts
+(AND x (MOVDconst [c])) && isU16Bit(c) => (ANDconst [c] x)
+(XOR x (MOVDconst [c])) && isU32Bit(c) => (XORconst [c] x)
+(OR x (MOVDconst [c])) && isU32Bit(c) => (ORconst [c] x)
+
+// Simplify consts
+(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
+(ORconst [c] (ORconst [d] x)) => (ORconst [c|d] x)
+(XORconst [c] (XORconst [d] x)) => (XORconst [c^d] x)
+(ANDconst [-1] x) => x
+(ANDconst [0] _) => (MOVDconst [0])
+(XORconst [0] x) => x
+(ORconst [-1] _) => (MOVDconst [-1])
+(ORconst [0] x) => x
+
+// zero-extend of small and => small and
+(MOVBZreg y:(ANDconst [c] _)) && uint64(c) <= 0xFF => y
+(MOVHZreg y:(ANDconst [c] _)) && uint64(c) <= 0xFFFF => y
+(MOVWZreg y:(ANDconst [c] _)) && uint64(c) <= 0xFFFFFFFF => y
+(MOVWZreg y:(AND (MOVDconst [c]) _)) && uint64(c) <= 0xFFFFFFFF => y
+
+// sign extend of small-positive and => small-positive-and
+(MOVBreg y:(ANDconst [c] _)) && uint64(c) <= 0x7F => y
+(MOVHreg y:(ANDconst [c] _)) && uint64(c) <= 0x7FFF => y
+(MOVWreg y:(ANDconst [c] _)) && uint64(c) <= 0xFFFF => y // 0xFFFF is largest immediate constant, when regarded as 32-bit is > 0
+(MOVWreg y:(AND (MOVDconst [c]) _)) && uint64(c) <= 0x7FFFFFFF => y
+
+// small and of zero-extend => either zero-extend or small and
+(ANDconst [c] y:(MOVBZreg _)) && c&0xFF == 0xFF => y
+(ANDconst [0xFF] y:(MOVBreg _)) => y
+(ANDconst [c] y:(MOVHZreg _)) && c&0xFFFF == 0xFFFF => y
+(ANDconst [0xFFFF] y:(MOVHreg _)) => y
+
+(AND (MOVDconst [c]) y:(MOVWZreg _)) && c&0xFFFFFFFF == 0xFFFFFFFF => y
+(AND (MOVDconst [0xFFFFFFFF]) y:(MOVWreg x)) => (MOVWZreg x)
+// normal case
+(ANDconst [c] (MOV(B|BZ)reg x)) => (ANDconst [c&0xFF] x)
+(ANDconst [c] (MOV(H|HZ)reg x)) => (ANDconst [c&0xFFFF] x)
+(ANDconst [c] (MOV(W|WZ)reg x)) => (ANDconst [c&0xFFFFFFFF] x)
+
+// Eliminate unnecessary sign/zero extend following right shift
+(MOV(B|H|W)Zreg (SRWconst [c] (MOVBZreg x))) => (SRWconst [c] (MOVBZreg x))
+(MOV(H|W)Zreg (SRWconst [c] (MOVHZreg x))) => (SRWconst [c] (MOVHZreg x))
+(MOVWZreg (SRWconst [c] (MOVWZreg x))) => (SRWconst [c] (MOVWZreg x))
+(MOV(B|H|W)reg (SRAWconst [c] (MOVBreg x))) => (SRAWconst [c] (MOVBreg x))
+(MOV(H|W)reg (SRAWconst [c] (MOVHreg x))) => (SRAWconst [c] (MOVHreg x))
+(MOVWreg (SRAWconst [c] (MOVWreg x))) => (SRAWconst [c] (MOVWreg x))
+
+(MOVWZreg (SRWconst [c] x)) && sizeof(x.Type) <= 32 => (SRWconst [c] x)
+(MOVHZreg (SRWconst [c] x)) && sizeof(x.Type) <= 16 => (SRWconst [c] x)
+(MOVBZreg (SRWconst [c] x)) && sizeof(x.Type) == 8 => (SRWconst [c] x)
+(MOVWreg (SRAWconst [c] x)) && sizeof(x.Type) <= 32 => (SRAWconst [c] x)
+(MOVHreg (SRAWconst [c] x)) && sizeof(x.Type) <= 16 => (SRAWconst [c] x)
+(MOVBreg (SRAWconst [c] x)) && sizeof(x.Type) == 8 => (SRAWconst [c] x)
+
+// initial right shift will handle sign/zero extend
+(MOVBZreg (SRDconst [c] x)) && c>=56 => (SRDconst [c] x)
+(MOVBreg (SRDconst [c] x)) && c>56 => (SRDconst [c] x)
+(MOVBreg (SRDconst [c] x)) && c==56 => (SRADconst [c] x)
+(MOVBreg (SRADconst [c] x)) && c>=56 => (SRADconst [c] x)
+(MOVBZreg (SRWconst [c] x)) && c>=24 => (SRWconst [c] x)
+(MOVBreg (SRWconst [c] x)) && c>24 => (SRWconst [c] x)
+(MOVBreg (SRWconst [c] x)) && c==24 => (SRAWconst [c] x)
+(MOVBreg (SRAWconst [c] x)) && c>=24 => (SRAWconst [c] x)
+
+(MOVHZreg (SRDconst [c] x)) && c>=48 => (SRDconst [c] x)
+(MOVHreg (SRDconst [c] x)) && c>48 => (SRDconst [c] x)
+(MOVHreg (SRDconst [c] x)) && c==48 => (SRADconst [c] x)
+(MOVHreg (SRADconst [c] x)) && c>=48 => (SRADconst [c] x)
+(MOVHZreg (SRWconst [c] x)) && c>=16 => (SRWconst [c] x)
+(MOVHreg (SRWconst [c] x)) && c>16 => (SRWconst [c] x)
+(MOVHreg (SRAWconst [c] x)) && c>=16 => (SRAWconst [c] x)
+(MOVHreg (SRWconst [c] x)) && c==16 => (SRAWconst [c] x)
+
+(MOVWZreg (SRDconst [c] x)) && c>=32 => (SRDconst [c] x)
+(MOVWreg (SRDconst [c] x)) && c>32 => (SRDconst [c] x)
+(MOVWreg (SRADconst [c] x)) && c>=32 => (SRADconst [c] x)
+(MOVWreg (SRDconst [c] x)) && c==32 => (SRADconst [c] x)
+
+// Various redundant zero/sign extension combinations.
+(MOVBZreg y:(MOVBZreg _)) => y // repeat
+(MOVBreg y:(MOVBreg _)) => y // repeat
+(MOVBreg (MOVBZreg x)) => (MOVBreg x)
+(MOVBZreg (MOVBreg x)) => (MOVBZreg x)
+
+// H - there are more combinations than these
+
+(MOVHZreg y:(MOVHZreg _)) => y // repeat
+(MOVHZreg y:(MOVBZreg _)) => y // wide of narrow
+(MOVHZreg y:(MOVHBRload _ _)) => y
+
+(MOVHreg y:(MOVHreg _)) => y // repeat
+(MOVHreg y:(MOVBreg _)) => y // wide of narrow
+
+(MOVHreg y:(MOVHZreg x)) => (MOVHreg x)
+(MOVHZreg y:(MOVHreg x)) => (MOVHZreg x)
+
+// W - there are more combinations than these
+
+(MOVWZreg y:(MOVWZreg _)) => y // repeat
+(MOVWZreg y:(MOVHZreg _)) => y // wide of narrow
+(MOVWZreg y:(MOVBZreg _)) => y // wide of narrow
+(MOVWZreg y:(MOVHBRload _ _)) => y
+(MOVWZreg y:(MOVWBRload _ _)) => y
+
+(MOVWreg y:(MOVWreg _)) => y // repeat
+(MOVWreg y:(MOVHreg _)) => y // wide of narrow
+(MOVWreg y:(MOVBreg _)) => y // wide of narrow
+
+(MOVWreg y:(MOVWZreg x)) => (MOVWreg x)
+(MOVWZreg y:(MOVWreg x)) => (MOVWZreg x)
+
+// Truncate then logical then truncate: omit first, lesser or equal truncate
+(MOVWZreg ((OR|XOR|AND) <t> x (MOVWZreg y))) => (MOVWZreg ((OR|XOR|AND) <t> x y))
+(MOVHZreg ((OR|XOR|AND) <t> x (MOVWZreg y))) => (MOVHZreg ((OR|XOR|AND) <t> x y))
+(MOVHZreg ((OR|XOR|AND) <t> x (MOVHZreg y))) => (MOVHZreg ((OR|XOR|AND) <t> x y))
+(MOVBZreg ((OR|XOR|AND) <t> x (MOVWZreg y))) => (MOVBZreg ((OR|XOR|AND) <t> x y))
+(MOVBZreg ((OR|XOR|AND) <t> x (MOVHZreg y))) => (MOVBZreg ((OR|XOR|AND) <t> x y))
+(MOVBZreg ((OR|XOR|AND) <t> x (MOVBZreg y))) => (MOVBZreg ((OR|XOR|AND) <t> x y))
+
+(MOV(B|H|W)Zreg z:(ANDconst [c] (MOVBZload ptr x))) => z
+(MOVBZreg z:(AND y (MOVBZload ptr x))) => z
+(MOV(H|W)Zreg z:(ANDconst [c] (MOVHZload ptr x))) => z
+(MOVHZreg z:(AND y (MOVHZload ptr x))) => z
+(MOVWZreg z:(ANDconst [c] (MOVWZload ptr x))) => z
+(MOVWZreg z:(AND y (MOVWZload ptr x))) => z
+
+// Arithmetic constant ops
+
+(ADD x (MOVDconst [c])) && is32Bit(c) => (ADDconst [c] x)
+(ADDconst [c] (ADDconst [d] x)) && is32Bit(c+d) => (ADDconst [c+d] x)
+(ADDconst [0] x) => x
+(SUB x (MOVDconst [c])) && is32Bit(-c) => (ADDconst [-c] x)
+
+(ADDconst [c] (MOVDaddr [d] {sym} x)) && is32Bit(c+int64(d)) => (MOVDaddr [int32(c+int64(d))] {sym} x)
+(ADDconst [c] x:(SP)) && is32Bit(c) => (MOVDaddr [int32(c)] x) // so it is rematerializeable
+
+(MULL(W|D) x (MOVDconst [c])) && is16Bit(c) => (MULL(W|D)const [int32(c)] x)
+
+// Subtract from (with carry, but ignored) constant.
+// Note, these clobber the carry bit.
+(SUB (MOVDconst [c]) x) && is32Bit(c) => (SUBFCconst [c] x)
+(SUBFCconst [c] (NEG x)) => (ADDconst [c] x)
+(SUBFCconst [c] (SUBFCconst [d] x)) && is32Bit(c-d) => (ADDconst [c-d] x)
+(SUBFCconst [0] x) => (NEG x)
+(ADDconst [c] (SUBFCconst [d] x)) && is32Bit(c+d) => (SUBFCconst [c+d] x)
+(NEG (ADDconst [c] x)) && is32Bit(-c) => (SUBFCconst [-c] x)
+(NEG (SUBFCconst [c] x)) && is32Bit(-c) => (ADDconst [-c] x)
+
+// Use register moves instead of stores and loads to move int<=>float values
+// Common with math Float64bits, Float64frombits
+(MOVDload [off] {sym} ptr (FMOVDstore [off] {sym} ptr x _)) => (MFVSRD x)
+(FMOVDload [off] {sym} ptr (MOVDstore [off] {sym} ptr x _)) => (MTVSRD x)
+
+(FMOVDstore [off] {sym} ptr (MTVSRD x) mem) => (MOVDstore [off] {sym} ptr x mem)
+(MOVDstore [off] {sym} ptr (MFVSRD x) mem) => (FMOVDstore [off] {sym} ptr x mem)
+
+(MTVSRD (MOVDconst [c])) && !math.IsNaN(math.Float64frombits(uint64(c))) => (FMOVDconst [math.Float64frombits(uint64(c))])
+(MFVSRD (FMOVDconst [c])) => (MOVDconst [int64(math.Float64bits(c))])
+
+(MTVSRD x:(MOVDload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (FMOVDload [off] {sym} ptr mem)
+(MFVSRD x:(FMOVDload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVDload [off] {sym} ptr mem)
+
+// Fold offsets for stores.
+(MOVDstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0 => (MOVDstore [off1+int32(off2)] {sym} x val mem)
+(MOVWstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(int64(off1)+off2) => (MOVWstore [off1+int32(off2)] {sym} x val mem)
+(MOVHstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(int64(off1)+off2) => (MOVHstore [off1+int32(off2)] {sym} x val mem)
+(MOVBstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(int64(off1)+off2) => (MOVBstore [off1+int32(off2)] {sym} x val mem)
+
+(FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is16Bit(int64(off1)+off2) => (FMOVSstore [off1+int32(off2)] {sym} ptr val mem)
+(FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is16Bit(int64(off1)+off2) => (FMOVDstore [off1+int32(off2)] {sym} ptr val mem)
+
+// Fold address into load/store.
+// The assembler needs to generate several instructions and use
+// temp register for accessing global, and each time it will reload
+// the temp register. So don't fold address of global, unless there
+// is only one use.
+(MOVBstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVHstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVWstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(MOVDstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0 =>
+ (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+
+(FMOVSstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+(FMOVDstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+
+(MOVBZload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (MOVBZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHZload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (MOVHZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0 =>
+ (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWZload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (MOVWZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVDload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0 =>
+ (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(FMOVSload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(FMOVDload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+ && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) =>
+ (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+
+// Fold offsets for loads.
+(FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem) && is16Bit(int64(off1)+off2) => (FMOVSload [off1+int32(off2)] {sym} ptr mem)
+(FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem) && is16Bit(int64(off1)+off2) => (FMOVDload [off1+int32(off2)] {sym} ptr mem)
+
+(MOVDload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0 => (MOVDload [off1+int32(off2)] {sym} x mem)
+(MOVWload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0 => (MOVWload [off1+int32(off2)] {sym} x mem)
+(MOVWZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(int64(off1)+off2) => (MOVWZload [off1+int32(off2)] {sym} x mem)
+(MOVHload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(int64(off1)+off2) => (MOVHload [off1+int32(off2)] {sym} x mem)
+(MOVHZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(int64(off1)+off2) => (MOVHZload [off1+int32(off2)] {sym} x mem)
+(MOVBZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(int64(off1)+off2) => (MOVBZload [off1+int32(off2)] {sym} x mem)
+
+// Determine load + addressing that can be done as a register indexed load
+(MOV(D|W|WZ|H|HZ|BZ)load [0] {sym} p:(ADD ptr idx) mem) && sym == nil && p.Uses == 1 => (MOV(D|W|WZ|H|HZ|BZ)loadidx ptr idx mem)
+
+// Determine indexed loads with constant values that can be done without index
+(MOV(D|W)loadidx ptr (MOVDconst [c]) mem) && is16Bit(c) && c%4 == 0 => (MOV(D|W)load [int32(c)] ptr mem)
+(MOV(WZ|H|HZ|BZ)loadidx ptr (MOVDconst [c]) mem) && is16Bit(c) => (MOV(WZ|H|HZ|BZ)load [int32(c)] ptr mem)
+(MOV(D|W)loadidx (MOVDconst [c]) ptr mem) && is16Bit(c) && c%4 == 0 => (MOV(D|W)load [int32(c)] ptr mem)
+(MOV(WZ|H|HZ|BZ)loadidx (MOVDconst [c]) ptr mem) && is16Bit(c) => (MOV(WZ|H|HZ|BZ)load [int32(c)] ptr mem)
+
+// Store of zero => storezero
+(MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVDstorezero [off] {sym} ptr mem)
+(MOVWstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVWstorezero [off] {sym} ptr mem)
+(MOVHstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVHstorezero [off] {sym} ptr mem)
+(MOVBstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVBstorezero [off] {sym} ptr mem)
+
+// Fold offsets for storezero
+(MOVDstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0 =>
+ (MOVDstorezero [off1+int32(off2)] {sym} x mem)
+(MOVWstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(int64(off1)+off2) =>
+ (MOVWstorezero [off1+int32(off2)] {sym} x mem)
+(MOVHstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(int64(off1)+off2) =>
+ (MOVHstorezero [off1+int32(off2)] {sym} x mem)
+(MOVBstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(int64(off1)+off2) =>
+ (MOVBstorezero [off1+int32(off2)] {sym} x mem)
+
+// Stores with addressing that can be done as indexed stores
+(MOV(D|W|H|B)store [0] {sym} p:(ADD ptr idx) val mem) && sym == nil && p.Uses == 1 => (MOV(D|W|H|B)storeidx ptr idx val mem)
+
+// Stores with constant index values can be done without indexed instructions
+(MOVDstoreidx ptr (MOVDconst [c]) val mem) && is16Bit(c) && c%4 == 0 => (MOVDstore [int32(c)] ptr val mem)
+(MOV(W|H|B)storeidx ptr (MOVDconst [c]) val mem) && is16Bit(c) => (MOV(W|H|B)store [int32(c)] ptr val mem)
+(MOVDstoreidx (MOVDconst [c]) ptr val mem) && is16Bit(c) && c%4 == 0 => (MOVDstore [int32(c)] ptr val mem)
+(MOV(W|H|B)storeidx (MOVDconst [c]) ptr val mem) && is16Bit(c) => (MOV(W|H|B)store [int32(c)] ptr val mem)
+
+// Fold symbols into storezero
+(MOVDstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2)
+ && (x.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0 =>
+ (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
+(MOVWstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2)
+ && (x.Op != OpSB || p.Uses == 1) =>
+ (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
+(MOVHstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2)
+ && (x.Op != OpSB || p.Uses == 1) =>
+ (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
+(MOVBstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2)
+ && (x.Op != OpSB || p.Uses == 1) =>
+ (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
+
+// atomic intrinsics
+(AtomicLoad(8|32|64|Ptr) ptr mem) => (LoweredAtomicLoad(8|32|64|Ptr) [1] ptr mem)
+(AtomicLoadAcq(32|64) ptr mem) => (LoweredAtomicLoad(32|64) [0] ptr mem)
+
+(AtomicStore(8|32|64) ptr val mem) => (LoweredAtomicStore(8|32|64) [1] ptr val mem)
+(AtomicStoreRel(32|64) ptr val mem) => (LoweredAtomicStore(32|64) [0] ptr val mem)
+//(AtomicStorePtrNoWB ptr val mem) => (STLR ptr val mem)
+
+(AtomicExchange(32|64) ...) => (LoweredAtomicExchange(32|64) ...)
+
+(AtomicAdd(32|64) ...) => (LoweredAtomicAdd(32|64) ...)
+
+(AtomicCompareAndSwap(32|64) ptr old new_ mem) => (LoweredAtomicCas(32|64) [1] ptr old new_ mem)
+(AtomicCompareAndSwapRel32 ptr old new_ mem) => (LoweredAtomicCas32 [0] ptr old new_ mem)
+
+(AtomicAnd8 ...) => (LoweredAtomicAnd8 ...)
+(AtomicAnd32 ...) => (LoweredAtomicAnd32 ...)
+(AtomicOr8 ...) => (LoweredAtomicOr8 ...)
+(AtomicOr32 ...) => (LoweredAtomicOr32 ...)
+
+(Slicemask <t> x) => (SRADconst (NEG <t> x) [63])
+
+// Note that MOV??reg returns a 64-bit int, x is not necessarily that wide
+// This may interact with other patterns in the future. (Compare with arm64)
+(MOV(B|H|W)Zreg x:(MOVBZload _ _)) => x
+(MOV(B|H|W)Zreg x:(MOVBZloadidx _ _ _)) => x
+(MOV(H|W)Zreg x:(MOVHZload _ _)) => x
+(MOV(H|W)Zreg x:(MOVHZloadidx _ _ _)) => x
+(MOV(H|W)reg x:(MOVHload _ _)) => x
+(MOV(H|W)reg x:(MOVHloadidx _ _ _)) => x
+(MOVWZreg x:(MOVWZload _ _)) => x
+(MOVWZreg x:(MOVWZloadidx _ _ _)) => x
+(MOVWreg x:(MOVWload _ _)) => x
+(MOVWreg x:(MOVWloadidx _ _ _)) => x
+
+// don't extend if argument is already extended
+(MOVBreg x:(Arg <t>)) && is8BitInt(t) && isSigned(t) => x
+(MOVBZreg x:(Arg <t>)) && is8BitInt(t) && !isSigned(t) => x
+(MOVHreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && isSigned(t) => x
+(MOVHZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && !isSigned(t) => x
+(MOVWreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t) => x
+(MOVWZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t) => x
+
+(MOVBZreg (MOVDconst [c])) => (MOVDconst [int64(uint8(c))])
+(MOVBreg (MOVDconst [c])) => (MOVDconst [int64(int8(c))])
+(MOVHZreg (MOVDconst [c])) => (MOVDconst [int64(uint16(c))])
+(MOVHreg (MOVDconst [c])) => (MOVDconst [int64(int16(c))])
+(MOVWreg (MOVDconst [c])) => (MOVDconst [int64(int32(c))])
+(MOVWZreg (MOVDconst [c])) => (MOVDconst [int64(uint32(c))])
+
+// Implement clrsldi and clrslwi extended mnemonics as described in
+// ISA 3.0 section C.8. AuxInt field contains values needed for
+// the instructions, packed together since there is only one available.
+(SLDconst [c] z:(MOVBZreg x)) && c < 8 && z.Uses == 1 => (CLRLSLDI [newPPC64ShiftAuxInt(c,56,63,64)] x)
+(SLDconst [c] z:(MOVHZreg x)) && c < 16 && z.Uses == 1 => (CLRLSLDI [newPPC64ShiftAuxInt(c,48,63,64)] x)
+(SLDconst [c] z:(MOVWZreg x)) && c < 32 && z.Uses == 1 => (CLRLSLDI [newPPC64ShiftAuxInt(c,32,63,64)] x)
+
+(SLDconst [c] z:(ANDconst [d] x)) && z.Uses == 1 && isPPC64ValidShiftMask(d) && c <= (64-getPPC64ShiftMaskLength(d)) => (CLRLSLDI [newPPC64ShiftAuxInt(c,64-getPPC64ShiftMaskLength(d),63,64)] x)
+(SLDconst [c] z:(AND (MOVDconst [d]) x)) && z.Uses == 1 && isPPC64ValidShiftMask(d) && c<=(64-getPPC64ShiftMaskLength(d)) => (CLRLSLDI [newPPC64ShiftAuxInt(c,64-getPPC64ShiftMaskLength(d),63,64)] x)
+(SLWconst [c] z:(MOVBZreg x)) && z.Uses == 1 && c < 8 => (CLRLSLWI [newPPC64ShiftAuxInt(c,24,31,32)] x)
+(SLWconst [c] z:(MOVHZreg x)) && z.Uses == 1 && c < 16 => (CLRLSLWI [newPPC64ShiftAuxInt(c,16,31,32)] x)
+(SLWconst [c] z:(ANDconst [d] x)) && z.Uses == 1 && isPPC64ValidShiftMask(d) && c<=(32-getPPC64ShiftMaskLength(d)) => (CLRLSLWI [newPPC64ShiftAuxInt(c,32-getPPC64ShiftMaskLength(d),31,32)] x)
+(SLWconst [c] z:(AND (MOVDconst [d]) x)) && z.Uses == 1 && isPPC64ValidShiftMask(d) && c<=(32-getPPC64ShiftMaskLength(d)) => (CLRLSLWI [newPPC64ShiftAuxInt(c,32-getPPC64ShiftMaskLength(d),31,32)] x)
+// special case for power9
+(SL(W|D)const [c] z:(MOVWreg x)) && c < 32 && objabi.GOPPC64 >= 9 => (EXTSWSLconst [c] x)
+
+// Lose widening ops fed to stores
+(MOVBstore [off] {sym} ptr (MOV(B|BZ|H|HZ|W|WZ)reg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOV(H|HZ|W|WZ)reg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOV(W|WZ)reg x) mem) => (MOVWstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (SRWconst (MOV(H|HZ)reg x) [c]) mem) && c <= 8 => (MOVBstore [off] {sym} ptr (SRWconst <typ.UInt32> x [c]) mem)
+(MOVBstore [off] {sym} ptr (SRWconst (MOV(W|WZ)reg x) [c]) mem) && c <= 24 => (MOVBstore [off] {sym} ptr (SRWconst <typ.UInt32> x [c]) mem)
+(MOVBstoreidx ptr idx (MOV(B|BZ|H|HZ|W|WZ)reg x) mem) => (MOVBstoreidx ptr idx x mem)
+(MOVHstoreidx ptr idx (MOV(H|HZ|W|WZ)reg x) mem) => (MOVHstoreidx ptr idx x mem)
+(MOVWstoreidx ptr idx (MOV(W|WZ)reg x) mem) => (MOVWstoreidx ptr idx x mem)
+(MOVBstoreidx ptr idx (SRWconst (MOV(H|HZ)reg x) [c]) mem) && c <= 8 => (MOVBstoreidx ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+(MOVBstoreidx ptr idx (SRWconst (MOV(W|WZ)reg x) [c]) mem) && c <= 24 => (MOVBstoreidx ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+(MOVHBRstore {sym} ptr (MOV(H|HZ|W|WZ)reg x) mem) => (MOVHBRstore {sym} ptr x mem)
+(MOVWBRstore {sym} ptr (MOV(W|WZ)reg x) mem) => (MOVWBRstore {sym} ptr x mem)
+
+// Lose W-widening ops fed to compare-W
+(CMPW x (MOVWreg y)) => (CMPW x y)
+(CMPW (MOVWreg x) y) => (CMPW x y)
+(CMPWU x (MOVWZreg y)) => (CMPWU x y)
+(CMPWU (MOVWZreg x) y) => (CMPWU x y)
+
+(CMP x (MOVDconst [c])) && is16Bit(c) => (CMPconst x [c])
+(CMP (MOVDconst [c]) y) && is16Bit(c) => (InvertFlags (CMPconst y [c]))
+(CMPW x (MOVDconst [c])) && is16Bit(c) => (CMPWconst x [int32(c)])
+(CMPW (MOVDconst [c]) y) && is16Bit(c) => (InvertFlags (CMPWconst y [int32(c)]))
+
+(CMPU x (MOVDconst [c])) && isU16Bit(c) => (CMPUconst x [c])
+(CMPU (MOVDconst [c]) y) && isU16Bit(c) => (InvertFlags (CMPUconst y [c]))
+(CMPWU x (MOVDconst [c])) && isU16Bit(c) => (CMPWUconst x [int32(c)])
+(CMPWU (MOVDconst [c]) y) && isU16Bit(c) => (InvertFlags (CMPWUconst y [int32(c)]))
+
+// Canonicalize the order of arguments to comparisons - helps with CSE.
+((CMP|CMPW|CMPU|CMPWU) x y) && x.ID > y.ID => (InvertFlags ((CMP|CMPW|CMPU|CMPWU) y x))
+
+// ISEL auxInt values 0=LT 1=GT 2=EQ arg2 ? arg0 : arg1
+// ISEL auxInt values 4=GE 5=LE 6=NE arg2 ? arg1 : arg0
+// ISELB special case where arg0, arg1 values are 0, 1
+
+(Equal cmp) => (ISELB [2] (MOVDconst [1]) cmp)
+(NotEqual cmp) => (ISELB [6] (MOVDconst [1]) cmp)
+(LessThan cmp) => (ISELB [0] (MOVDconst [1]) cmp)
+(FLessThan cmp) => (ISELB [0] (MOVDconst [1]) cmp)
+(FLessEqual cmp) => (ISEL [2] (MOVDconst [1]) (ISELB [0] (MOVDconst [1]) cmp) cmp)
+(GreaterEqual cmp) => (ISELB [4] (MOVDconst [1]) cmp)
+(GreaterThan cmp) => (ISELB [1] (MOVDconst [1]) cmp)
+(FGreaterThan cmp) => (ISELB [1] (MOVDconst [1]) cmp)
+(FGreaterEqual cmp) => (ISEL [2] (MOVDconst [1]) (ISELB [1] (MOVDconst [1]) cmp) cmp)
+(LessEqual cmp) => (ISELB [5] (MOVDconst [1]) cmp)
+
+(ISELB [0] _ (FlagLT)) => (MOVDconst [1])
+(ISELB [0] _ (Flag(GT|EQ))) => (MOVDconst [0])
+(ISELB [1] _ (FlagGT)) => (MOVDconst [1])
+(ISELB [1] _ (Flag(LT|EQ))) => (MOVDconst [0])
+(ISELB [2] _ (FlagEQ)) => (MOVDconst [1])
+(ISELB [2] _ (Flag(LT|GT))) => (MOVDconst [0])
+(ISELB [4] _ (FlagLT)) => (MOVDconst [0])
+(ISELB [4] _ (Flag(GT|EQ))) => (MOVDconst [1])
+(ISELB [5] _ (FlagGT)) => (MOVDconst [0])
+(ISELB [5] _ (Flag(LT|EQ))) => (MOVDconst [1])
+(ISELB [6] _ (FlagEQ)) => (MOVDconst [0])
+(ISELB [6] _ (Flag(LT|GT))) => (MOVDconst [1])
+
+(ISEL [2] x _ (FlagEQ)) => x
+(ISEL [2] _ y (Flag(LT|GT))) => y
+
+(ISEL [6] _ y (FlagEQ)) => y
+(ISEL [6] x _ (Flag(LT|GT))) => x
+
+(ISEL [0] _ y (Flag(EQ|GT))) => y
+(ISEL [0] x _ (FlagLT)) => x
+
+(ISEL [5] _ x (Flag(EQ|LT))) => x
+(ISEL [5] y _ (FlagGT)) => y
+
+(ISEL [1] _ y (Flag(EQ|LT))) => y
+(ISEL [1] x _ (FlagGT)) => x
+
+(ISEL [4] x _ (Flag(EQ|GT))) => x
+(ISEL [4] _ y (FlagLT)) => y
+
+(ISELB [n] (MOVDconst [1]) (InvertFlags bool)) && n%4 == 0 => (ISELB [n+1] (MOVDconst [1]) bool)
+(ISELB [n] (MOVDconst [1]) (InvertFlags bool)) && n%4 == 1 => (ISELB [n-1] (MOVDconst [1]) bool)
+(ISELB [n] (MOVDconst [1]) (InvertFlags bool)) && n%4 == 2 => (ISELB [n] (MOVDconst [1]) bool)
+(ISEL [n] x y (InvertFlags bool)) && n%4 == 0 => (ISEL [n+1] x y bool)
+(ISEL [n] x y (InvertFlags bool)) && n%4 == 1 => (ISEL [n-1] x y bool)
+(ISEL [n] x y (InvertFlags bool)) && n%4 == 2 => (ISEL [n] x y bool)
+
+// A particular pattern seen in cgo code:
+(AND (MOVDconst [c]) x:(MOVBZload _ _)) => (ANDconst [c&0xFF] x)
+
+// floating point negative abs
+(FNEG (FABS x)) => (FNABS x)
+(FNEG (FNABS x)) => (FABS x)
+
+// floating-point fused multiply-add/sub
+(FADD (FMUL x y) z) => (FMADD x y z)
+(FSUB (FMUL x y) z) => (FMSUB x y z)
+(FADDS (FMULS x y) z) => (FMADDS x y z)
+(FSUBS (FMULS x y) z) => (FMSUBS x y z)
+
+
+// The following statements are found in encoding/binary functions UintXX (load) and PutUintXX (store)
+// and convert the statements in these functions from multiple single byte loads or stores to
+// the single largest possible load or store.
+// Some are marked big or little endian based on the order in which the bytes are loaded or stored,
+// not on the ordering of the machine. These are intended for little endian machines.
+// To implement for big endian machines, most rules would have to be duplicated but the
+// resulting rule would be reversed, i. e., MOVHZload on little endian would be MOVHBRload on big endian
+// and vice versa.
+// b[0] | b[1]<<8 => load 16-bit Little endian
+(OR <t> x0:(MOVBZload [i0] {s} p mem)
+ o1:(SL(W|D)const x1:(MOVBZload [i1] {s} p mem) [8]))
+ && !config.BigEndian
+ && i1 == i0+1
+ && x0.Uses ==1 && x1.Uses == 1
+ && o1.Uses == 1
+ && mergePoint(b, x0, x1) != nil
+ && clobber(x0, x1, o1)
+ => @mergePoint(b,x0,x1) (MOVHZload <t> {s} [i0] p mem)
+
+// b[0]<<8 | b[1] => load 16-bit Big endian on Little endian arch.
+// Use byte-reverse indexed load for 2 bytes.
+(OR <t> x0:(MOVBZload [i1] {s} p mem)
+ o1:(SL(W|D)const x1:(MOVBZload [i0] {s} p mem) [8]))
+ && !config.BigEndian
+ && i1 == i0+1
+ && x0.Uses ==1 && x1.Uses == 1
+ && o1.Uses == 1
+ && mergePoint(b, x0, x1) != nil
+ && clobber(x0, x1, o1)
+ => @mergePoint(b,x0,x1) (MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+
+// b[0]<<n+8 | b[1]<<n => load 16-bit Big endian (where n%8== 0)
+// Use byte-reverse indexed load for 2 bytes,
+// then shift left to the correct position. Used to match subrules
+// from longer rules.
+(OR <t> s0:(SL(W|D)const x0:(MOVBZload [i1] {s} p mem) [n1])
+ s1:(SL(W|D)const x1:(MOVBZload [i0] {s} p mem) [n2]))
+ && !config.BigEndian
+ && i1 == i0+1
+ && n1%8 == 0
+ && n2 == n1+8
+ && x0.Uses == 1 && x1.Uses == 1
+ && s0.Uses == 1 && s1.Uses == 1
+ && mergePoint(b, x0, x1) != nil
+ && clobber(x0, x1, s0, s1)
+ => @mergePoint(b,x0,x1) (SLDconst <t> (MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [n1])
+
+// b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24 => load 32-bit Little endian
+// Use byte-reverse indexed load for 4 bytes.
+(OR <t> s1:(SL(W|D)const x2:(MOVBZload [i3] {s} p mem) [24])
+ o0:(OR <t> s0:(SL(W|D)const x1:(MOVBZload [i2] {s} p mem) [16])
+ x0:(MOVHZload [i0] {s} p mem)))
+ && !config.BigEndian
+ && i2 == i0+2
+ && i3 == i0+3
+ && x0.Uses ==1 && x1.Uses == 1 && x2.Uses == 1
+ && o0.Uses == 1
+ && s0.Uses == 1 && s1.Uses == 1
+ && mergePoint(b, x0, x1, x2) != nil
+ && clobber(x0, x1, x2, s0, s1, o0)
+ => @mergePoint(b,x0,x1,x2) (MOVWZload <t> {s} [i0] p mem)
+
+// b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3] => load 32-bit Big endian order on Little endian arch
+// Use byte-reverse indexed load for 4 bytes with computed address.
+// Could be used to match subrules of a longer rule.
+(OR <t> s1:(SL(W|D)const x2:(MOVBZload [i0] {s} p mem) [24])
+ o0:(OR <t> s0:(SL(W|D)const x1:(MOVBZload [i1] {s} p mem) [16])
+ x0:(MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i2] {s} p) mem)))
+ && !config.BigEndian
+ && i1 == i0+1
+ && i2 == i0+2
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && o0.Uses == 1
+ && s0.Uses == 1 && s1.Uses == 1
+ && mergePoint(b, x0, x1, x2) != nil
+ && clobber(x0, x1, x2, s0, s1, o0)
+ => @mergePoint(b,x0,x1,x2) (MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+
+// b[3] | b[2]<<8 | b[1]<<16 | b[0]<<24 => load 32-bit Big endian order on Little endian arch
+// Use byte-reverse indexed load for 4 bytes with computed address.
+// Could be used to match subrules of a longer rule.
+(OR <t> x0:(MOVBZload [i3] {s} p mem)
+ o0:(OR <t> s0:(SL(W|D)const x1:(MOVBZload [i2] {s} p mem) [8])
+ s1:(SL(W|D)const x2:(MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [16])))
+ && !config.BigEndian
+ && i2 == i0+2
+ && i3 == i0+3
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && o0.Uses == 1
+ && s0.Uses == 1 && s1.Uses == 1
+ && mergePoint(b, x0, x1, x2) != nil
+ && clobber(x0, x1, x2, s0, s1, o0)
+ => @mergePoint(b,x0,x1,x2) (MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+
+// b[0]<<56 | b[1]<<48 | b[2]<<40 | b[3]<<32 => load 32-bit Big endian order on Little endian arch
+// Use byte-reverse indexed load to for 4 bytes with computed address.
+// Used to match longer rules.
+(OR <t> s2:(SLDconst x2:(MOVBZload [i3] {s} p mem) [32])
+ o0:(OR <t> s1:(SLDconst x1:(MOVBZload [i2] {s} p mem) [40])
+ s0:(SLDconst x0:(MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [48])))
+ && !config.BigEndian
+ && i2 == i0+2
+ && i3 == i0+3
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && o0.Uses == 1
+ && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1
+ && mergePoint(b, x0, x1, x2) != nil
+ && clobber(x0, x1, x2, s0, s1, s2, o0)
+ => @mergePoint(b,x0,x1,x2) (SLDconst <t> (MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [32])
+
+// b[3]<<32 | b[2]<<40 | b[1]<<48 | b[0]<<56 => load 32-bit Big endian order on Little endian arch
+// Use byte-reverse indexed load for 4 bytes with constant address.
+// Used to match longer rules.
+(OR <t> s2:(SLDconst x2:(MOVBZload [i0] {s} p mem) [56])
+ o0:(OR <t> s1:(SLDconst x1:(MOVBZload [i1] {s} p mem) [48])
+ s0:(SLDconst x0:(MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i2] {s} p) mem) [32])))
+ && !config.BigEndian
+ && i1 == i0+1
+ && i2 == i0+2
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && o0.Uses == 1
+ && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1
+ && mergePoint(b, x0, x1, x2) != nil
+ && clobber(x0, x1, x2, s0, s1, s2, o0)
+ => @mergePoint(b,x0,x1,x2) (SLDconst <t> (MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [32])
+
+// b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24 | b[4] <<32 | b[5]<<40 | b[6]<<48 | b[7]<<56 => load 64-bit Little endian
+// Rules with commutative ops and many operands will result in extremely large functions in rewritePPC64,
+// so matching shorter previously defined subrules is important.
+// Offset must be multiple of 4 for MOVD
+(OR <t> s6:(SLDconst x7:(MOVBZload [i7] {s} p mem) [56])
+ o5:(OR <t> s5:(SLDconst x6:(MOVBZload [i6] {s} p mem) [48])
+ o4:(OR <t> s4:(SLDconst x5:(MOVBZload [i5] {s} p mem) [40])
+ o3:(OR <t> s3:(SLDconst x4:(MOVBZload [i4] {s} p mem) [32])
+ x0:(MOVWZload {s} [i0] p mem)))))
+ && !config.BigEndian
+ && i0%4 == 0
+ && i4 == i0+4
+ && i5 == i0+5
+ && i6 == i0+6
+ && i7 == i0+7
+ && x0.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses ==1 && x7.Uses == 1
+ && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1
+ && s3.Uses == 1 && s4.Uses == 1 && s5.Uses == 1 && s6.Uses == 1
+ && mergePoint(b, x0, x4, x5, x6, x7) != nil
+ && clobber(x0, x4, x5, x6, x7, s3, s4, s5, s6, o3, o4, o5)
+ => @mergePoint(b,x0,x4,x5,x6,x7) (MOVDload <t> {s} [i0] p mem)
+
+// b[7] | b[6]<<8 | b[5]<<16 | b[4]<<24 | b[3]<<32 | b[2]<<40 | b[1]<<48 | b[0]<<56 load 64-bit Big endian ordered bytes on Little endian arch
+// Use byte-reverse indexed load of 8 bytes.
+// Rules with commutative ops and many operands can result in extremely large functions in rewritePPC64,
+// so matching shorter previously defined subrules is important.
+(OR <t> s0:(SLDconst x0:(MOVBZload [i0] {s} p mem) [56])
+ o0:(OR <t> s1:(SLDconst x1:(MOVBZload [i1] {s} p mem) [48])
+ o1:(OR <t> s2:(SLDconst x2:(MOVBZload [i2] {s} p mem) [40])
+ o2:(OR <t> s3:(SLDconst x3:(MOVBZload [i3] {s} p mem) [32])
+ x4:(MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i4] p) mem)))))
+ && !config.BigEndian
+ && i1 == i0+1
+ && i2 == i0+2
+ && i3 == i0+3
+ && i4 == i0+4
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
+ && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
+ && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1
+ && mergePoint(b, x0, x1, x2, x3, x4) != nil
+ && clobber(x0, x1, x2, x3, x4, o0, o1, o2, s0, s1, s2, s3)
+ => @mergePoint(b,x0,x1,x2,x3,x4) (MOVDBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+
+// b[0]<<56 | b[1]<<48 | b[2]<<40 | b[3]<<32 | b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7] => load 64-bit Big endian ordered bytes on Little endian arch
+// Use byte-reverse indexed load of 8 bytes.
+// Rules with commutative ops and many operands can result in extremely large functions in rewritePPC64,
+// so matching shorter previously defined subrules is important.
+(OR <t> x7:(MOVBZload [i7] {s} p mem)
+ o5:(OR <t> s6:(SLDconst x6:(MOVBZload [i6] {s} p mem) [8])
+ o4:(OR <t> s5:(SLDconst x5:(MOVBZload [i5] {s} p mem) [16])
+ o3:(OR <t> s4:(SLDconst x4:(MOVBZload [i4] {s} p mem) [24])
+ s0:(SL(W|D)const x3:(MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [32])))))
+ && !config.BigEndian
+ && i4 == i0+4
+ && i5 == i0+5
+ && i6 == i0+6
+ && i7 == i0+7
+ && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
+ && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1
+ && s0.Uses == 1 && s4.Uses == 1 && s5.Uses == 1 && s6.Uses == 1
+ && mergePoint(b, x3, x4, x5, x6, x7) != nil
+ && clobber(x3, x4, x5, x6, x7, o3, o4, o5, s0, s4, s5, s6)
+ => @mergePoint(b,x3,x4,x5,x6,x7) (MOVDBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+
+// 2 byte store Little endian as in:
+// b[0] = byte(v >> 16)
+// b[1] = byte(v >> 24)
+// Added for use in matching longer rules.
+(MOVBstore [i1] {s} p (SR(W|D)const w [24])
+ x0:(MOVBstore [i0] {s} p (SR(W|D)const w [16]) mem))
+ && !config.BigEndian
+ && x0.Uses == 1
+ && i1 == i0+1
+ && clobber(x0)
+ => (MOVHstore [i0] {s} p (SRWconst <typ.UInt16> w [16]) mem)
+
+// 2 byte store Little endian as in:
+// b[0] = byte(v)
+// b[1] = byte(v >> 8)
+(MOVBstore [i1] {s} p (SR(W|D)const w [8])
+ x0:(MOVBstore [i0] {s} p w mem))
+ && !config.BigEndian
+ && x0.Uses == 1
+ && i1 == i0+1
+ && clobber(x0)
+ => (MOVHstore [i0] {s} p w mem)
+
+// 4 byte store Little endian as in:
+// b[0:1] = uint16(v)
+// b[2:3] = uint16(v >> 16)
+(MOVHstore [i1] {s} p (SR(W|D)const w [16])
+ x0:(MOVHstore [i0] {s} p w mem))
+ && !config.BigEndian
+ && x0.Uses == 1
+ && i1 == i0+2
+ && clobber(x0)
+ => (MOVWstore [i0] {s} p w mem)
+
+// 4 byte store Big endian as in:
+// b[0] = byte(v >> 24)
+// b[1] = byte(v >> 16)
+// b[2] = byte(v >> 8)
+// b[3] = byte(v)
+// Use byte-reverse indexed 4 byte store.
+(MOVBstore [i3] {s} p w
+ x0:(MOVBstore [i2] {s} p (SRWconst w [8])
+ x1:(MOVBstore [i1] {s} p (SRWconst w [16])
+ x2:(MOVBstore [i0] {s} p (SRWconst w [24]) mem))))
+ && !config.BigEndian
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
+ && i1 == i0+1 && i2 == i0+2 && i3 == i0+3
+ && clobber(x0, x1, x2)
+ => (MOVWBRstore (MOVDaddr <typ.Uintptr> [i0] {s} p) w mem)
+
+// The 2 byte store appears after the 4 byte store so that the
+// match for the 2 byte store is not done first.
+// If the 4 byte store is based on the 2 byte store then there are
+// variations on the MOVDaddr subrule that would require additional
+// rules to be written.
+
+// 2 byte store Big endian as in:
+// b[0] = byte(v >> 8)
+// b[1] = byte(v)
+(MOVBstore [i1] {s} p w x0:(MOVBstore [i0] {s} p (SRWconst w [8]) mem))
+ && !config.BigEndian
+ && x0.Uses == 1
+ && i1 == i0+1
+ && clobber(x0)
+ => (MOVHBRstore (MOVDaddr <typ.Uintptr> [i0] {s} p) w mem)
+
+// 8 byte store Little endian as in:
+// b[0] = byte(v)
+// b[1] = byte(v >> 8)
+// b[2] = byte(v >> 16)
+// b[3] = byte(v >> 24)
+// b[4] = byte(v >> 32)
+// b[5] = byte(v >> 40)
+// b[6] = byte(v >> 48)
+// b[7] = byte(v >> 56)
+// Built on previously defined rules
+// Offset must be multiple of 4 for MOVDstore
+(MOVBstore [i7] {s} p (SRDconst w [56])
+ x0:(MOVBstore [i6] {s} p (SRDconst w [48])
+ x1:(MOVBstore [i5] {s} p (SRDconst w [40])
+ x2:(MOVBstore [i4] {s} p (SRDconst w [32])
+ x3:(MOVWstore [i0] {s} p w mem)))))
+ && !config.BigEndian
+ && i0%4 == 0
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
+ && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7
+ && clobber(x0, x1, x2, x3)
+ => (MOVDstore [i0] {s} p w mem)
+
+// 8 byte store Big endian as in:
+// b[0] = byte(v >> 56)
+// b[1] = byte(v >> 48)
+// b[2] = byte(v >> 40)
+// b[3] = byte(v >> 32)
+// b[4] = byte(v >> 24)
+// b[5] = byte(v >> 16)
+// b[6] = byte(v >> 8)
+// b[7] = byte(v)
+// Use byte-reverse indexed 8 byte store.
+(MOVBstore [i7] {s} p w
+ x0:(MOVBstore [i6] {s} p (SRDconst w [8])
+ x1:(MOVBstore [i5] {s} p (SRDconst w [16])
+ x2:(MOVBstore [i4] {s} p (SRDconst w [24])
+ x3:(MOVBstore [i3] {s} p (SRDconst w [32])
+ x4:(MOVBstore [i2] {s} p (SRDconst w [40])
+ x5:(MOVBstore [i1] {s} p (SRDconst w [48])
+ x6:(MOVBstore [i0] {s} p (SRDconst w [56]) mem))))))))
+ && !config.BigEndian
+ && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1
+ && i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7
+ && clobber(x0, x1, x2, x3, x4, x5, x6)
+ => (MOVDBRstore (MOVDaddr <typ.Uintptr> [i0] {s} p) w mem)
diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go
new file mode 100644
index 0000000..f7198b9
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go
@@ -0,0 +1,717 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import "strings"
+
+// Notes:
+// - Less-than-64-bit integer types live in the low portion of registers.
+// For now, the upper portion is junk; sign/zero-extension might be optimized in the future, but not yet.
+// - Boolean types are zero or 1; stored in a byte, but loaded with AMOVBZ so the upper bytes of a register are zero.
+// - *const instructions may use a constant larger than the instruction can encode.
+// In this case the assembler expands to multiple instructions and uses tmp
+// register (R31).
+
+var regNamesPPC64 = []string{
+ "R0", // REGZERO, not used, but simplifies counting in regalloc
+ "SP", // REGSP
+ "SB", // REGSB
+ "R3",
+ "R4",
+ "R5",
+ "R6",
+ "R7",
+ "R8",
+ "R9",
+ "R10",
+ "R11", // REGCTXT for closures
+ "R12",
+ "R13", // REGTLS
+ "R14",
+ "R15",
+ "R16",
+ "R17",
+ "R18",
+ "R19",
+ "R20",
+ "R21",
+ "R22",
+ "R23",
+ "R24",
+ "R25",
+ "R26",
+ "R27",
+ "R28",
+ "R29",
+ "g", // REGG. Using name "g" and setting Config.hasGReg makes it "just happen".
+ "R31", // REGTMP
+
+ "F0",
+ "F1",
+ "F2",
+ "F3",
+ "F4",
+ "F5",
+ "F6",
+ "F7",
+ "F8",
+ "F9",
+ "F10",
+ "F11",
+ "F12",
+ "F13",
+ "F14",
+ "F15",
+ "F16",
+ "F17",
+ "F18",
+ "F19",
+ "F20",
+ "F21",
+ "F22",
+ "F23",
+ "F24",
+ "F25",
+ "F26",
+ "F27",
+ "F28",
+ "F29",
+ "F30",
+ "F31",
+
+ // If you add registers, update asyncPreempt in runtime.
+
+ // "CR0",
+ // "CR1",
+ // "CR2",
+ // "CR3",
+ // "CR4",
+ // "CR5",
+ // "CR6",
+ // "CR7",
+
+ // "CR",
+ // "XER",
+ // "LR",
+ // "CTR",
+}
+
+func init() {
+ // Make map from reg names to reg integers.
+ if len(regNamesPPC64) > 64 {
+ panic("too many registers")
+ }
+ num := map[string]int{}
+ for i, name := range regNamesPPC64 {
+ num[name] = 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
+ }
+
+ var (
+ gp = buildReg("R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29")
+ fp = buildReg("F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26")
+ sp = buildReg("SP")
+ sb = buildReg("SB")
+ gr = buildReg("g")
+ // cr = buildReg("CR")
+ // ctr = buildReg("CTR")
+ // lr = buildReg("LR")
+ tmp = buildReg("R31")
+ ctxt = buildReg("R11")
+ callptr = buildReg("R12")
+ // tls = buildReg("R13")
+ gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
+ gp11 = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}
+ gp21 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp}}
+ gp21a0 = regInfo{inputs: []regMask{gp, gp | sp | sb}, outputs: []regMask{gp}}
+ gp31 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp}}
+ gp22 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp, gp}}
+ gp32 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp, gp}}
+ gp1cr = regInfo{inputs: []regMask{gp | sp | sb}}
+ gp2cr = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}}
+ crgp = regInfo{inputs: nil, outputs: []regMask{gp}}
+ crgp11 = regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}
+ crgp21 = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
+ gpload = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}
+ gploadidx = regInfo{inputs: []regMask{gp | sp | sb, gp}, outputs: []regMask{gp}}
+ gpstore = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}}
+ gpstoreidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, gp | sp | sb}}
+ gpstorezero = regInfo{inputs: []regMask{gp | sp | sb}} // ppc64.REGZERO is reserved zero value
+ gpxchg = regInfo{inputs: []regMask{gp | sp | sb, gp}, outputs: []regMask{gp}}
+ gpcas = regInfo{inputs: []regMask{gp | sp | sb, gp, gp}, outputs: []regMask{gp}}
+ fp01 = regInfo{inputs: nil, outputs: []regMask{fp}}
+ fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
+ fpgp = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}
+ gpfp = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}
+ fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
+ fp31 = regInfo{inputs: []regMask{fp, fp, fp}, outputs: []regMask{fp}}
+ fp2cr = regInfo{inputs: []regMask{fp, fp}}
+ fpload = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{fp}}
+ fploadidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{fp}}
+ fpstore = regInfo{inputs: []regMask{gp | sp | sb, fp}}
+ fpstoreidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, fp}}
+ callerSave = regMask(gp | fp | gr)
+ r3 = buildReg("R3")
+ r4 = buildReg("R4")
+ r5 = buildReg("R5")
+ r6 = buildReg("R6")
+ )
+ ops := []opData{
+ {name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1
+ {name: "ADDconst", argLength: 1, reg: gp11, asm: "ADD", aux: "Int64"}, // arg0 + auxInt
+ {name: "FADD", argLength: 2, reg: fp21, asm: "FADD", commutative: true}, // arg0+arg1
+ {name: "FADDS", argLength: 2, reg: fp21, asm: "FADDS", commutative: true}, // arg0+arg1
+ {name: "SUB", argLength: 2, reg: gp21, asm: "SUB"}, // arg0-arg1
+ {name: "SUBFCconst", argLength: 1, reg: gp11, asm: "SUBC", aux: "Int64"}, // auxInt - arg0 (with carry)
+ {name: "FSUB", argLength: 2, reg: fp21, asm: "FSUB"}, // arg0-arg1
+ {name: "FSUBS", argLength: 2, reg: fp21, asm: "FSUBS"}, // arg0-arg1
+
+ {name: "MULLD", argLength: 2, reg: gp21, asm: "MULLD", typ: "Int64", commutative: true}, // arg0*arg1 (signed 64-bit)
+ {name: "MULLW", argLength: 2, reg: gp21, asm: "MULLW", typ: "Int32", commutative: true}, // arg0*arg1 (signed 32-bit)
+ {name: "MULLDconst", argLength: 1, reg: gp11, asm: "MULLD", aux: "Int32", typ: "Int64"}, // arg0*auxInt (signed 64-bit)
+ {name: "MULLWconst", argLength: 1, reg: gp11, asm: "MULLW", aux: "Int32", typ: "Int64"}, // arg0*auxInt (signed 64-bit)
+ {name: "MADDLD", argLength: 3, reg: gp31, asm: "MADDLD", typ: "Int64"}, // (arg0*arg1)+arg2 (signed 64-bit)
+
+ {name: "MULHD", argLength: 2, reg: gp21, asm: "MULHD", commutative: true}, // (arg0 * arg1) >> 64, signed
+ {name: "MULHW", argLength: 2, reg: gp21, asm: "MULHW", commutative: true}, // (arg0 * arg1) >> 32, signed
+ {name: "MULHDU", argLength: 2, reg: gp21, asm: "MULHDU", commutative: true}, // (arg0 * arg1) >> 64, unsigned
+ {name: "MULHWU", argLength: 2, reg: gp21, asm: "MULHWU", commutative: true}, // (arg0 * arg1) >> 32, unsigned
+ {name: "LoweredMuluhilo", argLength: 2, reg: gp22, resultNotInArgs: true}, // arg0 * arg1, returns (hi, lo)
+
+ {name: "FMUL", argLength: 2, reg: fp21, asm: "FMUL", commutative: true}, // arg0*arg1
+ {name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true}, // arg0*arg1
+
+ {name: "FMADD", argLength: 3, reg: fp31, asm: "FMADD"}, // arg0*arg1 + arg2
+ {name: "FMADDS", argLength: 3, reg: fp31, asm: "FMADDS"}, // arg0*arg1 + arg2
+ {name: "FMSUB", argLength: 3, reg: fp31, asm: "FMSUB"}, // arg0*arg1 - arg2
+ {name: "FMSUBS", argLength: 3, reg: fp31, asm: "FMSUBS"}, // arg0*arg1 - arg2
+
+ {name: "SRAD", argLength: 2, reg: gp21, asm: "SRAD"}, // signed arg0 >> (arg1&127), 64 bit width (note: 127, not 63!)
+ {name: "SRAW", argLength: 2, reg: gp21, asm: "SRAW"}, // signed arg0 >> (arg1&63), 32 bit width
+ {name: "SRD", argLength: 2, reg: gp21, asm: "SRD"}, // unsigned arg0 >> (arg1&127), 64 bit width
+ {name: "SRW", argLength: 2, reg: gp21, asm: "SRW"}, // unsigned arg0 >> (arg1&63), 32 bit width
+ {name: "SLD", argLength: 2, reg: gp21, asm: "SLD"}, // arg0 << (arg1&127), 64 bit width
+ {name: "SLW", argLength: 2, reg: gp21, asm: "SLW"}, // arg0 << (arg1&63), 32 bit width
+
+ {name: "ROTL", argLength: 2, reg: gp21, asm: "ROTL"}, // arg0 rotate left by arg1 mod 64
+ {name: "ROTLW", argLength: 2, reg: gp21, asm: "ROTLW"}, // uint32(arg0) rotate left by arg1 mod 32
+ // The following are ops to implement the extended mnemonics for shifts as described in section C.8 of the ISA.
+ // The constant shift values are packed into the aux int32.
+ {name: "RLDICL", argLength: 1, reg: gp11, asm: "RLDICL", aux: "Int32"}, // arg0 extract bits identified by shift params"
+ {name: "CLRLSLWI", argLength: 1, reg: gp11, asm: "CLRLSLWI", aux: "Int32"}, //
+ {name: "CLRLSLDI", argLength: 1, reg: gp11, asm: "CLRLSLDI", aux: "Int32"}, //
+
+ {name: "LoweredAdd64Carry", argLength: 3, reg: gp32, resultNotInArgs: true}, // arg0 + arg1 + carry, returns (sum, carry)
+
+ {name: "SRADconst", argLength: 1, reg: gp11, asm: "SRAD", aux: "Int64"}, // signed arg0 >> auxInt, 0 <= auxInt < 64, 64 bit width
+ {name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "Int64"}, // signed arg0 >> auxInt, 0 <= auxInt < 32, 32 bit width
+ {name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "Int64"}, // unsigned arg0 >> auxInt, 0 <= auxInt < 64, 64 bit width
+ {name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "Int64"}, // unsigned arg0 >> auxInt, 0 <= auxInt < 32, 32 bit width
+ {name: "SLDconst", argLength: 1, reg: gp11, asm: "SLD", aux: "Int64"}, // arg0 << auxInt, 0 <= auxInt < 64, 64 bit width
+ {name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "Int64"}, // arg0 << auxInt, 0 <= auxInt < 32, 32 bit width
+
+ {name: "ROTLconst", argLength: 1, reg: gp11, asm: "ROTL", aux: "Int64"}, // arg0 rotate left by auxInt bits
+ {name: "ROTLWconst", argLength: 1, reg: gp11, asm: "ROTLW", aux: "Int64"}, // uint32(arg0) rotate left by auxInt bits
+ {name: "EXTSWSLconst", argLength: 1, reg: gp11, asm: "EXTSWSLI", aux: "Int64"},
+
+ {name: "RLWINM", argLength: 1, reg: gp11, asm: "RLWNM", aux: "Int64"}, // Rotate and mask by immediate "rlwinm". encodePPC64RotateMask describes aux
+ {name: "RLWNM", argLength: 2, reg: gp21, asm: "RLWNM", aux: "Int64"}, // Rotate and mask by "rlwnm". encodePPC64RotateMask describes aux
+ {name: "RLWMI", argLength: 2, reg: gp21a0, asm: "RLWMI", aux: "Int64", resultInArg0: true}, // "rlwimi" similar aux encoding as above
+
+ {name: "CNTLZD", argLength: 1, reg: gp11, asm: "CNTLZD", clobberFlags: true}, // count leading zeros
+ {name: "CNTLZW", argLength: 1, reg: gp11, asm: "CNTLZW", clobberFlags: true}, // count leading zeros (32 bit)
+
+ {name: "CNTTZD", argLength: 1, reg: gp11, asm: "CNTTZD"}, // count trailing zeros
+ {name: "CNTTZW", argLength: 1, reg: gp11, asm: "CNTTZW"}, // count trailing zeros (32 bit)
+
+ {name: "POPCNTD", argLength: 1, reg: gp11, asm: "POPCNTD"}, // number of set bits in arg0
+ {name: "POPCNTW", argLength: 1, reg: gp11, asm: "POPCNTW"}, // number of set bits in each word of arg0 placed in corresponding word
+ {name: "POPCNTB", argLength: 1, reg: gp11, asm: "POPCNTB"}, // number of set bits in each byte of arg0 placed in corresponding byte
+
+ {name: "FDIV", argLength: 2, reg: fp21, asm: "FDIV"}, // arg0/arg1
+ {name: "FDIVS", argLength: 2, reg: fp21, asm: "FDIVS"}, // arg0/arg1
+
+ {name: "DIVD", argLength: 2, reg: gp21, asm: "DIVD", typ: "Int64"}, // arg0/arg1 (signed 64-bit)
+ {name: "DIVW", argLength: 2, reg: gp21, asm: "DIVW", typ: "Int32"}, // arg0/arg1 (signed 32-bit)
+ {name: "DIVDU", argLength: 2, reg: gp21, asm: "DIVDU", typ: "Int64"}, // arg0/arg1 (unsigned 64-bit)
+ {name: "DIVWU", argLength: 2, reg: gp21, asm: "DIVWU", typ: "Int32"}, // arg0/arg1 (unsigned 32-bit)
+
+ {name: "MODUD", argLength: 2, reg: gp21, asm: "MODUD", typ: "UInt64"}, // arg0 % arg1 (unsigned 64-bit)
+ {name: "MODSD", argLength: 2, reg: gp21, asm: "MODSD", typ: "Int64"}, // arg0 % arg1 (signed 64-bit)
+ {name: "MODUW", argLength: 2, reg: gp21, asm: "MODUW", typ: "UInt32"}, // arg0 % arg1 (unsigned 32-bit)
+ {name: "MODSW", argLength: 2, reg: gp21, asm: "MODSW", typ: "Int32"}, // arg0 % arg1 (signed 32-bit)
+ // MOD is implemented as rem := arg0 - (arg0/arg1) * arg1
+
+ // Conversions are all float-to-float register operations. "Integer" refers to encoding in the FP register.
+ {name: "FCTIDZ", argLength: 1, reg: fp11, asm: "FCTIDZ", typ: "Float64"}, // convert float to 64-bit int round towards zero
+ {name: "FCTIWZ", argLength: 1, reg: fp11, asm: "FCTIWZ", typ: "Float64"}, // convert float to 32-bit int round towards zero
+ {name: "FCFID", argLength: 1, reg: fp11, asm: "FCFID", typ: "Float64"}, // convert 64-bit integer to float
+ {name: "FCFIDS", argLength: 1, reg: fp11, asm: "FCFIDS", typ: "Float32"}, // convert 32-bit integer to float
+ {name: "FRSP", argLength: 1, reg: fp11, asm: "FRSP", typ: "Float64"}, // round float to 32-bit value
+
+ // Movement between float and integer registers with no change in bits; accomplished with stores+loads on PPC.
+ // Because the 32-bit load-literal-bits instructions have impoverished addressability, always widen the
+ // data instead and use FMOVDload and FMOVDstore instead (this will also dodge endianess issues).
+ // There are optimizations that should apply -- (Xi2f64 (MOVWload (not-ADD-ptr+offset) ) ) could use
+ // the word-load instructions. (Xi2f64 (MOVDload ptr )) can be (FMOVDload ptr)
+
+ {name: "MFVSRD", argLength: 1, reg: fpgp, asm: "MFVSRD", typ: "Int64"}, // move 64 bits of F register into G register
+ {name: "MTVSRD", argLength: 1, reg: gpfp, asm: "MTVSRD", typ: "Float64"}, // move 64 bits of G register into F register
+
+ {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0&arg1
+ {name: "ANDN", argLength: 2, reg: gp21, asm: "ANDN"}, // arg0&^arg1
+ {name: "ANDCC", argLength: 2, reg: gp2cr, asm: "ANDCC", commutative: true, typ: "Flags"}, // arg0&arg1 sets CC
+ {name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true}, // arg0|arg1
+ {name: "ORN", argLength: 2, reg: gp21, asm: "ORN"}, // arg0|^arg1
+ {name: "ORCC", argLength: 2, reg: gp2cr, asm: "ORCC", commutative: true, typ: "Flags"}, // arg0|arg1 sets CC
+ {name: "NOR", argLength: 2, reg: gp21, asm: "NOR", commutative: true}, // ^(arg0|arg1)
+ {name: "XOR", argLength: 2, reg: gp21, asm: "XOR", typ: "Int64", commutative: true}, // arg0^arg1
+ {name: "XORCC", argLength: 2, reg: gp2cr, asm: "XORCC", commutative: true, typ: "Flags"}, // arg0^arg1 sets CC
+ {name: "EQV", argLength: 2, reg: gp21, asm: "EQV", typ: "Int64", commutative: true}, // arg0^^arg1
+ {name: "NEG", argLength: 1, reg: gp11, asm: "NEG"}, // -arg0 (integer)
+ {name: "FNEG", argLength: 1, reg: fp11, asm: "FNEG"}, // -arg0 (floating point)
+ {name: "FSQRT", argLength: 1, reg: fp11, asm: "FSQRT"}, // sqrt(arg0) (floating point)
+ {name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS"}, // sqrt(arg0) (floating point, single precision)
+ {name: "FFLOOR", argLength: 1, reg: fp11, asm: "FRIM"}, // floor(arg0), float64
+ {name: "FCEIL", argLength: 1, reg: fp11, asm: "FRIP"}, // ceil(arg0), float64
+ {name: "FTRUNC", argLength: 1, reg: fp11, asm: "FRIZ"}, // trunc(arg0), float64
+ {name: "FROUND", argLength: 1, reg: fp11, asm: "FRIN"}, // round(arg0), float64
+ {name: "FABS", argLength: 1, reg: fp11, asm: "FABS"}, // abs(arg0), float64
+ {name: "FNABS", argLength: 1, reg: fp11, asm: "FNABS"}, // -abs(arg0), float64
+ {name: "FCPSGN", argLength: 2, reg: fp21, asm: "FCPSGN"}, // copysign arg0 -> arg1, float64
+
+ {name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int64"}, // arg0|aux
+ {name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64"}, // arg0^aux
+ {name: "ANDconst", argLength: 1, reg: regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}, asm: "ANDCC", aux: "Int64", clobberFlags: true}, // arg0&aux // and-immediate sets CC on PPC, always.
+ {name: "ANDCCconst", argLength: 1, reg: regInfo{inputs: []regMask{gp | sp | sb}}, asm: "ANDCC", aux: "Int64", typ: "Flags"}, // arg0&aux == 0 // and-immediate sets CC on PPC, always.
+
+ {name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB", typ: "Int64"}, // sign extend int8 to int64
+ {name: "MOVBZreg", argLength: 1, reg: gp11, asm: "MOVBZ", typ: "Int64"}, // zero extend uint8 to uint64
+ {name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVH", typ: "Int64"}, // sign extend int16 to int64
+ {name: "MOVHZreg", argLength: 1, reg: gp11, asm: "MOVHZ", typ: "Int64"}, // zero extend uint16 to uint64
+ {name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW", typ: "Int64"}, // sign extend int32 to int64
+ {name: "MOVWZreg", argLength: 1, reg: gp11, asm: "MOVWZ", typ: "Int64"}, // zero extend uint32 to uint64
+
+ // Load bytes in the endian order of the arch from arg0+aux+auxint into a 64 bit register.
+ {name: "MOVBZload", argLength: 2, reg: gpload, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load byte zero extend
+ {name: "MOVHload", argLength: 2, reg: gpload, asm: "MOVH", aux: "SymOff", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes sign extend
+ {name: "MOVHZload", argLength: 2, reg: gpload, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes zero extend
+ {name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVW", aux: "SymOff", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes sign extend
+ {name: "MOVWZload", argLength: 2, reg: gpload, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes zero extend
+ {name: "MOVDload", argLength: 2, reg: gpload, asm: "MOVD", aux: "SymOff", typ: "Int64", faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes
+
+ // Load bytes in reverse endian order of the arch from arg0 into a 64 bit register, all zero extend.
+ // The generated instructions are indexed loads with no offset field in the instruction so the aux fields are not used.
+ // In these cases the index register field is set to 0 and the full address is in the base register.
+ {name: "MOVDBRload", argLength: 2, reg: gpload, asm: "MOVDBR", aux: "SymOff", typ: "Int64", faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes reverse order
+ {name: "MOVWBRload", argLength: 2, reg: gpload, asm: "MOVWBR", aux: "SymOff", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes zero extend reverse order
+ {name: "MOVHBRload", argLength: 2, reg: gpload, asm: "MOVHBR", aux: "SymOff", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes zero extend reverse order
+
+ // In these cases an index register is used in addition to a base register
+ // Loads from memory location arg[0] + arg[1].
+ {name: "MOVBZloadidx", argLength: 3, reg: gploadidx, asm: "MOVBZ", typ: "UInt8"}, // zero extend uint8 to uint64
+ {name: "MOVHloadidx", argLength: 3, reg: gploadidx, asm: "MOVH", typ: "Int16"}, // sign extend int16 to int64
+ {name: "MOVHZloadidx", argLength: 3, reg: gploadidx, asm: "MOVHZ", typ: "UInt16"}, // zero extend uint16 to uint64
+ {name: "MOVWloadidx", argLength: 3, reg: gploadidx, asm: "MOVW", typ: "Int32"}, // sign extend int32 to int64
+ {name: "MOVWZloadidx", argLength: 3, reg: gploadidx, asm: "MOVWZ", typ: "UInt32"}, // zero extend uint32 to uint64
+ {name: "MOVDloadidx", argLength: 3, reg: gploadidx, asm: "MOVD", typ: "Int64"},
+ {name: "MOVHBRloadidx", argLength: 3, reg: gploadidx, asm: "MOVHBR", typ: "Int16"}, // sign extend int16 to int64
+ {name: "MOVWBRloadidx", argLength: 3, reg: gploadidx, asm: "MOVWBR", typ: "Int32"}, // sign extend int32 to int64
+ {name: "MOVDBRloadidx", argLength: 3, reg: gploadidx, asm: "MOVDBR", typ: "Int64"},
+ {name: "FMOVDloadidx", argLength: 3, reg: fploadidx, asm: "FMOVD", typ: "Float64"},
+ {name: "FMOVSloadidx", argLength: 3, reg: fploadidx, asm: "FMOVS", typ: "Float32"},
+
+ // Store bytes in the reverse endian order of the arch into arg0.
+ // These are indexed stores with no offset field in the instruction so the auxint fields are not used.
+ {name: "MOVDBRstore", argLength: 3, reg: gpstore, asm: "MOVDBR", aux: "Sym", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes reverse order
+ {name: "MOVWBRstore", argLength: 3, reg: gpstore, asm: "MOVWBR", aux: "Sym", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes reverse order
+ {name: "MOVHBRstore", argLength: 3, reg: gpstore, asm: "MOVHBR", aux: "Sym", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes reverse order
+
+ // Floating point loads from arg0+aux+auxint
+ {name: "FMOVDload", argLength: 2, reg: fpload, asm: "FMOVD", aux: "SymOff", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"}, // load double float
+ {name: "FMOVSload", argLength: 2, reg: fpload, asm: "FMOVS", aux: "SymOff", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"}, // load single float
+
+ // Store bytes in the endian order of the arch into arg0+aux+auxint
+ {name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store byte
+ {name: "MOVHstore", argLength: 3, reg: gpstore, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes
+ {name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes
+ {name: "MOVDstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes
+
+ // Store floating point value into arg0+aux+auxint
+ {name: "FMOVDstore", argLength: 3, reg: fpstore, asm: "FMOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store double flot
+ {name: "FMOVSstore", argLength: 3, reg: fpstore, asm: "FMOVS", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store single float
+
+ // Stores using index and base registers
+ // Stores to arg[0] + arg[1]
+ {name: "MOVBstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVB", typ: "Mem"}, // store bye
+ {name: "MOVHstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVH", typ: "Mem"}, // store half word
+ {name: "MOVWstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVW", typ: "Mem"}, // store word
+ {name: "MOVDstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVD", typ: "Mem"}, // store double word
+ {name: "FMOVDstoreidx", argLength: 4, reg: fpstoreidx, asm: "FMOVD", typ: "Mem"}, // store double float
+ {name: "FMOVSstoreidx", argLength: 4, reg: fpstoreidx, asm: "FMOVS", typ: "Mem"}, // store single float
+ {name: "MOVHBRstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVHBR", typ: "Mem"}, // store half word reversed byte using index reg
+ {name: "MOVWBRstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVWBR", typ: "Mem"}, // store word reversed byte using index reg
+ {name: "MOVDBRstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVDBR", typ: "Mem"}, // store double word reversed byte using index reg
+
+ // The following ops store 0 into arg0+aux+auxint arg1=mem
+ {name: "MOVBstorezero", argLength: 2, reg: gpstorezero, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store zero 1 byte
+ {name: "MOVHstorezero", argLength: 2, reg: gpstorezero, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store zero 2 bytes
+ {name: "MOVWstorezero", argLength: 2, reg: gpstorezero, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store zero 4 bytes
+ {name: "MOVDstorezero", argLength: 2, reg: gpstorezero, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store zero 8 bytes
+
+ {name: "MOVDaddr", argLength: 1, reg: regInfo{inputs: []regMask{sp | sb | gp}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVD", rematerializeable: true, symEffect: "Addr"}, // arg0 + auxInt + aux.(*gc.Sym), arg0=SP/SB/GP
+
+ {name: "MOVDconst", argLength: 0, reg: gp01, aux: "Int64", asm: "MOVD", typ: "Int64", rematerializeable: true}, //
+ {name: "FMOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "FMOVD", rematerializeable: true}, //
+ {name: "FMOVSconst", argLength: 0, reg: fp01, aux: "Float32", asm: "FMOVS", rematerializeable: true}, //
+ {name: "FCMPU", argLength: 2, reg: fp2cr, asm: "FCMPU", typ: "Flags"},
+
+ {name: "CMP", argLength: 2, reg: gp2cr, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPU", argLength: 2, reg: gp2cr, asm: "CMPU", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPW", argLength: 2, reg: gp2cr, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPWU", argLength: 2, reg: gp2cr, asm: "CMPWU", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPconst", argLength: 1, reg: gp1cr, asm: "CMP", aux: "Int64", typ: "Flags"},
+ {name: "CMPUconst", argLength: 1, reg: gp1cr, asm: "CMPU", aux: "Int64", typ: "Flags"},
+ {name: "CMPWconst", argLength: 1, reg: gp1cr, asm: "CMPW", aux: "Int32", typ: "Flags"},
+ {name: "CMPWUconst", argLength: 1, reg: gp1cr, asm: "CMPWU", aux: "Int32", typ: "Flags"},
+
+ // ISEL auxInt values 0=LT 1=GT 2=EQ arg2 ? arg0 : arg1
+ // ISEL auxInt values 4=GE 5=LE 6=NE arg2 ? arg1 : arg0
+ // ISELB special case where arg0, arg1 values are 0, 1 for boolean result
+ {name: "ISEL", argLength: 3, reg: crgp21, asm: "ISEL", aux: "Int32", typ: "Int32"}, // see above
+ {name: "ISELB", argLength: 2, reg: crgp11, asm: "ISEL", aux: "Int32", typ: "Int32"}, // see above
+
+ // pseudo-ops
+ {name: "Equal", argLength: 1, reg: crgp}, // bool, true flags encode x==y false otherwise.
+ {name: "NotEqual", argLength: 1, reg: crgp}, // bool, true flags encode x!=y false otherwise.
+ {name: "LessThan", argLength: 1, reg: crgp}, // bool, true flags encode x<y false otherwise.
+ {name: "FLessThan", argLength: 1, reg: crgp}, // bool, true flags encode x<y false otherwise.
+ {name: "LessEqual", argLength: 1, reg: crgp}, // bool, true flags encode x<=y false otherwise.
+ {name: "FLessEqual", argLength: 1, reg: crgp}, // bool, true flags encode x<=y false otherwise; PPC <= === !> which is wrong for NaN
+ {name: "GreaterThan", argLength: 1, reg: crgp}, // bool, true flags encode x>y false otherwise.
+ {name: "FGreaterThan", argLength: 1, reg: crgp}, // bool, true flags encode x>y false otherwise.
+ {name: "GreaterEqual", argLength: 1, reg: crgp}, // bool, true flags encode x>=y false otherwise.
+ {name: "FGreaterEqual", argLength: 1, reg: crgp}, // bool, true flags encode x>=y false otherwise.; PPC >= === !< which is wrong for NaN
+
+ // Scheduler ensures LoweredGetClosurePtr occurs only in entry block,
+ // and sorts it to the very beginning of the block to prevent other
+ // use of the closure pointer.
+ {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{ctxt}}, zeroWidth: true},
+
+ // LoweredGetCallerSP returns the SP of the caller of the current function.
+ {name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
+
+ // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+ // I.e., if f calls g "calls" getcallerpc,
+ // the result should be the PC within f that g will return to.
+ // See runtime/stubs.go for a more detailed discussion.
+ {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
+
+ //arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
+ {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gp | sp | sb}, clobbers: tmp}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
+ // Round ops to block fused-multiply-add extraction.
+ {name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
+ {name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
+
+ {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
+ {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{callptr, ctxt, 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
+ {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{callptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
+
+ // large or unaligned zeroing
+ // arg0 = address of memory to zero (in R3, changed as side effect)
+ // returns mem
+ //
+ // a loop is generated when there is more than one iteration
+ // needed to clear 4 doublewords
+ //
+ // XXLXOR VS32,VS32,VS32
+ // MOVD $len/32,R31
+ // MOVD R31,CTR
+ // MOVD $16,R31
+ // loop:
+ // STXVD2X VS32,(R0)(R3)
+ // STXVD2X VS32,(R31),R3)
+ // ADD R3,32
+ // BC loop
+
+ // remaining doubleword clears generated as needed
+ // MOVD R0,(R3)
+ // MOVD R0,8(R3)
+ // MOVD R0,16(R3)
+ // MOVD R0,24(R3)
+
+ // one or more of these to clear remainder < 8 bytes
+ // MOVW R0,n1(R3)
+ // MOVH R0,n2(R3)
+ // MOVB R0,n3(R3)
+ {
+ name: "LoweredZero",
+ aux: "Int64",
+ argLength: 2,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R20")},
+ clobbers: buildReg("R20"),
+ },
+ clobberFlags: true,
+ typ: "Mem",
+ faultOnNilArg0: true,
+ unsafePoint: true,
+ },
+ {
+ name: "LoweredZeroShort",
+ aux: "Int64",
+ argLength: 2,
+ reg: regInfo{
+ inputs: []regMask{gp}},
+ typ: "Mem",
+ faultOnNilArg0: true,
+ unsafePoint: true,
+ },
+ {
+ name: "LoweredQuadZeroShort",
+ aux: "Int64",
+ argLength: 2,
+ reg: regInfo{
+ inputs: []regMask{gp},
+ },
+ typ: "Mem",
+ faultOnNilArg0: true,
+ unsafePoint: true,
+ },
+ {
+ name: "LoweredQuadZero",
+ aux: "Int64",
+ argLength: 2,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R20")},
+ clobbers: buildReg("R20"),
+ },
+ clobberFlags: true,
+ typ: "Mem",
+ faultOnNilArg0: true,
+ unsafePoint: true,
+ },
+
+ // R31 is temp register
+ // Loop code:
+ // MOVD len/32,R31 set up loop ctr
+ // MOVD R31,CTR
+ // MOVD $16,R31 index register
+ // loop:
+ // LXVD2X (R0)(R4),VS32
+ // LXVD2X (R31)(R4),VS33
+ // ADD R4,$32 increment src
+ // STXVD2X VS32,(R0)(R3)
+ // STXVD2X VS33,(R31)(R3)
+ // ADD R3,$32 increment dst
+ // BC 16,0,loop branch ctr
+ // For this purpose, VS32 and VS33 are treated as
+ // scratch registers. Since regalloc does not
+ // track vector registers, even if it could be marked
+ // as clobbered it would have no effect.
+ // TODO: If vector registers are managed by regalloc
+ // mark these as clobbered.
+ //
+ // Bytes not moved by this loop are moved
+ // with a combination of the following instructions,
+ // starting with the largest sizes and generating as
+ // many as needed, using the appropriate offset value.
+ // MOVD n(R4),R14
+ // MOVD R14,n(R3)
+ // MOVW n1(R4),R14
+ // MOVW R14,n1(R3)
+ // MOVH n2(R4),R14
+ // MOVH R14,n2(R3)
+ // MOVB n3(R4),R14
+ // MOVB R14,n3(R3)
+
+ {
+ name: "LoweredMove",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R20"), buildReg("R21")},
+ clobbers: buildReg("R20 R21"),
+ },
+ clobberFlags: true,
+ typ: "Mem",
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true,
+ },
+ {
+ name: "LoweredMoveShort",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{gp, gp},
+ },
+ typ: "Mem",
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true,
+ },
+
+ // The following is similar to the LoweredMove, but uses
+ // LXV instead of LXVD2X, which does not require an index
+ // register and will do 4 in a loop instead of only.
+ {
+ name: "LoweredQuadMove",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R20"), buildReg("R21")},
+ clobbers: buildReg("R20 R21"),
+ },
+ clobberFlags: true,
+ typ: "Mem",
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true,
+ },
+
+ {
+ name: "LoweredQuadMoveShort",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{gp, gp},
+ },
+ typ: "Mem",
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true,
+ },
+
+ {name: "LoweredAtomicStore8", argLength: 3, reg: gpstore, typ: "Mem", aux: "Int64", faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, typ: "Mem", aux: "Int64", faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicStore64", argLength: 3, reg: gpstore, typ: "Mem", aux: "Int64", faultOnNilArg0: true, hasSideEffects: true},
+
+ {name: "LoweredAtomicLoad8", argLength: 2, reg: gpload, typ: "UInt8", aux: "Int64", clobberFlags: true, faultOnNilArg0: true},
+ {name: "LoweredAtomicLoad32", argLength: 2, reg: gpload, typ: "UInt32", aux: "Int64", clobberFlags: true, faultOnNilArg0: true},
+ {name: "LoweredAtomicLoad64", argLength: 2, reg: gpload, typ: "Int64", aux: "Int64", clobberFlags: true, faultOnNilArg0: true},
+ {name: "LoweredAtomicLoadPtr", argLength: 2, reg: gpload, typ: "Int64", aux: "Int64", clobberFlags: true, faultOnNilArg0: true},
+
+ // atomic add32, 64
+ // LWSYNC
+ // LDAR (Rarg0), Rout
+ // ADD Rarg1, Rout
+ // STDCCC Rout, (Rarg0)
+ // BNE -3(PC)
+ // return new sum
+ {name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic exchange32, 64
+ // LWSYNC
+ // LDAR (Rarg0), Rout
+ // STDCCC Rarg1, (Rarg0)
+ // BNE -2(PC)
+ // ISYNC
+ // return old val
+ {name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic compare and swap.
+ // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory. auxint must be zero.
+ // if *arg0 == arg1 {
+ // *arg0 = arg2
+ // return (true, memory)
+ // } else {
+ // return (false, memory)
+ // }
+ // SYNC
+ // LDAR (Rarg0), Rtmp
+ // CMP Rarg1, Rtmp
+ // BNE 3(PC)
+ // STDCCC Rarg2, (Rarg0)
+ // BNE -4(PC)
+ // CBNZ Rtmp, -4(PC)
+ // CSET EQ, Rout
+ {name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, aux: "Int64", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, aux: "Int64", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // atomic 8/32 and/or.
+ // *arg0 &= (|=) arg1. arg2=mem. returns memory. auxint must be zero.
+ // LBAR/LWAT (Rarg0), Rtmp
+ // AND/OR Rarg1, Rtmp
+ // STBCCC/STWCCC Rtmp, (Rarg0), Rtmp
+ // BNE Rtmp, -3(PC)
+ {name: "LoweredAtomicAnd8", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicAnd32", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicOr8", argLength: 3, reg: gpstore, asm: "OR", faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicOr32", argLength: 3, reg: gpstore, asm: "OR", faultOnNilArg0: true, hasSideEffects: true},
+
+ // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+ // It preserves R0 through R17 (except special registers R1, R2, R11, R12, R13), g, and its arguments R20 and R21,
+ // but may clobber anything else, including R31 (REGTMP).
+ {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R20"), buildReg("R21")}, clobbers: (callerSave &^ buildReg("R0 R3 R4 R5 R6 R7 R8 R9 R10 R14 R15 R16 R17 R20 R21 g")) | buildReg("R31")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
+
+ // There are three of these functions so that they can have three different register inputs.
+ // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
+ // default registers to match so we don't need to copy registers around unnecessarily.
+ {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r5, r6}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r4, r5}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r3, r4}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+
+ // (InvertFlags (CMP a b)) == (CMP b a)
+ // So if we want (LessThan (CMP a b)) but we can't do that because a is a constant,
+ // then we do (LessThan (InvertFlags (CMP b a))) instead.
+ // Rewrites will convert this to (GreaterThan (CMP b a)).
+ // InvertFlags is a pseudo-op which can't appear in assembly output.
+ {name: "InvertFlags", argLength: 1}, // reverse direction of arg0
+
+ // Constant flag values. For any comparison, there are 3 possible
+ // outcomes: either the three from the signed total order (<,==,>)
+ // or the three from the unsigned total order, depending on which
+ // comparison operation was used (CMP or CMPU -- PPC is different from
+ // the other architectures, which have a single comparison producing
+ // both signed and unsigned comparison results.)
+
+ // These ops are for temporary use by rewrite rules. They
+ // cannot appear in the generated assembly.
+ {name: "FlagEQ"}, // equal
+ {name: "FlagLT"}, // signed < or unsigned <
+ {name: "FlagGT"}, // signed > or unsigned >
+ }
+
+ blocks := []blockData{
+ {name: "EQ", controls: 1},
+ {name: "NE", controls: 1},
+ {name: "LT", controls: 1},
+ {name: "LE", controls: 1},
+ {name: "GT", controls: 1},
+ {name: "GE", controls: 1},
+ {name: "FLT", controls: 1},
+ {name: "FLE", controls: 1},
+ {name: "FGT", controls: 1},
+ {name: "FGE", controls: 1},
+ }
+
+ archs = append(archs, arch{
+ name: "PPC64",
+ pkg: "cmd/internal/obj/ppc64",
+ genfile: "../../ppc64/ssa.go",
+ ops: ops,
+ blocks: blocks,
+ regnames: regNamesPPC64,
+ gpregmask: gp,
+ fpregmask: fp,
+ framepointerreg: int8(num["SP"]),
+ linkreg: -1, // not used
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/README b/src/cmd/compile/internal/ssa/gen/README
new file mode 100644
index 0000000..6d2c6bb
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/README
@@ -0,0 +1,7 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+This package generates opcode tables, rewrite rules, etc. for the ssa compiler.
+Run it with go-1.13 (or above):
+ go run *.go
diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules
new file mode 100644
index 0000000..4380a5e
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules
@@ -0,0 +1,737 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Optimizations TODO:
+// * Use SLTI and SLTIU for comparisons to constants, instead of SLT/SLTU with constants in registers
+// * Use the zero register instead of moving 0 into a register.
+// * Add rules to avoid generating a temp bool value for (If (SLT[U] ...) ...).
+// * Optimize left and right shift by simplifying SLTIU, Neg, and ADD for constants.
+// * Arrange for non-trivial Zero and Move lowerings to use aligned loads and stores.
+// * Eliminate zero immediate shifts, adds, etc.
+// * Avoid using Neq32 for writeBarrier.enabled checks.
+
+// Lowering arithmetic
+(Add64 ...) => (ADD ...)
+(AddPtr ...) => (ADD ...)
+(Add32 ...) => (ADD ...)
+(Add16 ...) => (ADD ...)
+(Add8 ...) => (ADD ...)
+(Add32F ...) => (FADDS ...)
+(Add64F ...) => (FADDD ...)
+
+(Sub64 ...) => (SUB ...)
+(SubPtr ...) => (SUB ...)
+(Sub32 ...) => (SUB ...)
+(Sub16 ...) => (SUB ...)
+(Sub8 ...) => (SUB ...)
+(Sub32F ...) => (FSUBS ...)
+(Sub64F ...) => (FSUBD ...)
+
+(Mul64 ...) => (MUL ...)
+(Mul32 ...) => (MULW ...)
+(Mul16 x y) => (MULW (SignExt16to32 x) (SignExt16to32 y))
+(Mul8 x y) => (MULW (SignExt8to32 x) (SignExt8to32 y))
+(Mul32F ...) => (FMULS ...)
+(Mul64F ...) => (FMULD ...)
+
+(Div32F ...) => (FDIVS ...)
+(Div64F ...) => (FDIVD ...)
+
+(Div64 x y [false]) => (DIV x y)
+(Div64u ...) => (DIVU ...)
+(Div32 x y [false]) => (DIVW x y)
+(Div32u ...) => (DIVUW ...)
+(Div16 x y [false]) => (DIVW (SignExt16to32 x) (SignExt16to32 y))
+(Div16u x y) => (DIVUW (ZeroExt16to32 x) (ZeroExt16to32 y))
+(Div8 x y) => (DIVW (SignExt8to32 x) (SignExt8to32 y))
+(Div8u x y) => (DIVUW (ZeroExt8to32 x) (ZeroExt8to32 y))
+
+(Hmul64 ...) => (MULH ...)
+(Hmul64u ...) => (MULHU ...)
+(Hmul32 x y) => (SRAI [32] (MUL (SignExt32to64 x) (SignExt32to64 y)))
+(Hmul32u x y) => (SRLI [32] (MUL (ZeroExt32to64 x) (ZeroExt32to64 y)))
+
+// (x + y) / 2 => (x / 2) + (y / 2) + (x & y & 1)
+(Avg64u <t> x y) => (ADD (ADD <t> (SRLI <t> [1] x) (SRLI <t> [1] y)) (ANDI <t> [1] (AND <t> x y)))
+
+(Mod64 x y [false]) => (REM x y)
+(Mod64u ...) => (REMU ...)
+(Mod32 x y [false]) => (REMW x y)
+(Mod32u ...) => (REMUW ...)
+(Mod16 x y [false]) => (REMW (SignExt16to32 x) (SignExt16to32 y))
+(Mod16u x y) => (REMUW (ZeroExt16to32 x) (ZeroExt16to32 y))
+(Mod8 x y) => (REMW (SignExt8to32 x) (SignExt8to32 y))
+(Mod8u x y) => (REMUW (ZeroExt8to32 x) (ZeroExt8to32 y))
+
+(And64 ...) => (AND ...)
+(And32 ...) => (AND ...)
+(And16 ...) => (AND ...)
+(And8 ...) => (AND ...)
+
+(Or64 ...) => (OR ...)
+(Or32 ...) => (OR ...)
+(Or16 ...) => (OR ...)
+(Or8 ...) => (OR ...)
+
+(Xor64 ...) => (XOR ...)
+(Xor32 ...) => (XOR ...)
+(Xor16 ...) => (XOR ...)
+(Xor8 ...) => (XOR ...)
+
+(Neg64 ...) => (NEG ...)
+(Neg32 ...) => (NEG ...)
+(Neg16 ...) => (NEG ...)
+(Neg8 ...) => (NEG ...)
+(Neg32F ...) => (FNEGS ...)
+(Neg64F ...) => (FNEGD ...)
+
+(Com64 ...) => (NOT ...)
+(Com32 ...) => (NOT ...)
+(Com16 ...) => (NOT ...)
+(Com8 ...) => (NOT ...)
+
+(Sqrt ...) => (FSQRTD ...)
+
+// Sign and zero extension.
+
+(SignExt8to16 ...) => (MOVBreg ...)
+(SignExt8to32 ...) => (MOVBreg ...)
+(SignExt8to64 ...) => (MOVBreg ...)
+(SignExt16to32 ...) => (MOVHreg ...)
+(SignExt16to64 ...) => (MOVHreg ...)
+(SignExt32to64 ...) => (MOVWreg ...)
+
+(ZeroExt8to16 ...) => (MOVBUreg ...)
+(ZeroExt8to32 ...) => (MOVBUreg ...)
+(ZeroExt8to64 ...) => (MOVBUreg ...)
+(ZeroExt16to32 ...) => (MOVHUreg ...)
+(ZeroExt16to64 ...) => (MOVHUreg ...)
+(ZeroExt32to64 ...) => (MOVWUreg ...)
+
+(Cvt32to32F ...) => (FCVTSW ...)
+(Cvt32to64F ...) => (FCVTDW ...)
+(Cvt64to32F ...) => (FCVTSL ...)
+(Cvt64to64F ...) => (FCVTDL ...)
+
+(Cvt32Fto32 ...) => (FCVTWS ...)
+(Cvt32Fto64 ...) => (FCVTLS ...)
+(Cvt64Fto32 ...) => (FCVTWD ...)
+(Cvt64Fto64 ...) => (FCVTLD ...)
+
+(Cvt32Fto64F ...) => (FCVTDS ...)
+(Cvt64Fto32F ...) => (FCVTSD ...)
+
+(CvtBoolToUint8 ...) => (Copy ...)
+
+(Round32F ...) => (Copy ...)
+(Round64F ...) => (Copy ...)
+
+// From genericOps.go:
+// "0 if arg0 == 0, -1 if arg0 > 0, undef if arg0<0"
+//
+// Like other arches, we compute ~((x-1) >> 63), with arithmetic right shift.
+// For positive x, bit 63 of x-1 is always 0, so the result is -1.
+// For zero x, bit 63 of x-1 is 1, so the result is 0.
+//
+(Slicemask <t> x) => (NOT (SRAI <t> [63] (ADDI <t> [-1] x)))
+
+// Truncations
+// We ignore the unused high parts of registers, so truncates are just copies.
+(Trunc16to8 ...) => (Copy ...)
+(Trunc32to8 ...) => (Copy ...)
+(Trunc32to16 ...) => (Copy ...)
+(Trunc64to8 ...) => (Copy ...)
+(Trunc64to16 ...) => (Copy ...)
+(Trunc64to32 ...) => (Copy ...)
+
+// Shifts
+
+// SLL only considers the bottom 6 bits of y. If y > 64, the result should
+// always be 0.
+//
+// Breaking down the operation:
+//
+// (SLL x y) generates x << (y & 63).
+//
+// If y < 64, this is the value we want. Otherwise, we want zero.
+//
+// So, we AND with -1 * uint64(y < 64), which is 0xfffff... if y < 64 and 0 otherwise.
+(Lsh8x8 <t> x y) => (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+(Lsh8x16 <t> x y) => (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Lsh8x32 <t> x y) => (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Lsh8x64 <t> x y) => (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] y)))
+(Lsh16x8 <t> x y) => (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+(Lsh16x16 <t> x y) => (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Lsh16x32 <t> x y) => (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Lsh16x64 <t> x y) => (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] y)))
+(Lsh32x8 <t> x y) => (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+(Lsh32x16 <t> x y) => (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Lsh32x32 <t> x y) => (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Lsh32x64 <t> x y) => (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] y)))
+(Lsh64x8 <t> x y) => (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+(Lsh64x16 <t> x y) => (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Lsh64x32 <t> x y) => (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Lsh64x64 <t> x y) => (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] y)))
+
+// SRL only considers the bottom 6 bits of y. If y > 64, the result should
+// always be 0. See Lsh above for a detailed description.
+(Rsh8Ux8 <t> x y) => (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+(Rsh8Ux16 <t> x y) => (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Rsh8Ux32 <t> x y) => (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Rsh8Ux64 <t> x y) => (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] y)))
+(Rsh16Ux8 <t> x y) => (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+(Rsh16Ux16 <t> x y) => (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Rsh16Ux32 <t> x y) => (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Rsh16Ux64 <t> x y) => (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] y)))
+(Rsh32Ux8 <t> x y) => (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+(Rsh32Ux16 <t> x y) => (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Rsh32Ux32 <t> x y) => (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Rsh32Ux64 <t> x y) => (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] y)))
+(Rsh64Ux8 <t> x y) => (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+(Rsh64Ux16 <t> x y) => (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Rsh64Ux32 <t> x y) => (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Rsh64Ux64 <t> x y) => (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] y)))
+
+// SRA only considers the bottom 6 bits of y. If y > 64, the result should
+// be either 0 or -1 based on the sign bit.
+//
+// We implement this by performing the max shift (-1) if y >= 64.
+//
+// We OR (uint64(y < 64) - 1) into y before passing it to SRA. This leaves
+// us with -1 (0xffff...) if y >= 64.
+//
+// We don't need to sign-extend the OR result, as it will be at minimum 8 bits,
+// more than the 6 bits SRA cares about.
+(Rsh8x8 <t> x y) => (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
+(Rsh8x16 <t> x y) => (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
+(Rsh8x32 <t> x y) => (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
+(Rsh8x64 <t> x y) => (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
+(Rsh16x8 <t> x y) => (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
+(Rsh16x16 <t> x y) => (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
+(Rsh16x32 <t> x y) => (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
+(Rsh16x64 <t> x y) => (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
+(Rsh32x8 <t> x y) => (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
+(Rsh32x16 <t> x y) => (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
+(Rsh32x32 <t> x y) => (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
+(Rsh32x64 <t> x y) => (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
+(Rsh64x8 <t> x y) => (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
+(Rsh64x16 <t> x y) => (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
+(Rsh64x32 <t> x y) => (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
+(Rsh64x64 <t> x y) => (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
+
+// rotates
+(RotateLeft8 <t> x (MOVBconst [c])) => (Or8 (Lsh8x64 <t> x (MOVBconst [c&7])) (Rsh8Ux64 <t> x (MOVBconst [-c&7])))
+(RotateLeft16 <t> x (MOVHconst [c])) => (Or16 (Lsh16x64 <t> x (MOVHconst [c&15])) (Rsh16Ux64 <t> x (MOVHconst [-c&15])))
+(RotateLeft32 <t> x (MOVWconst [c])) => (Or32 (Lsh32x64 <t> x (MOVWconst [c&31])) (Rsh32Ux64 <t> x (MOVWconst [-c&31])))
+(RotateLeft64 <t> x (MOVDconst [c])) => (Or64 (Lsh64x64 <t> x (MOVDconst [c&63])) (Rsh64Ux64 <t> x (MOVDconst [-c&63])))
+
+(Less64 ...) => (SLT ...)
+(Less32 x y) => (SLT (SignExt32to64 x) (SignExt32to64 y))
+(Less16 x y) => (SLT (SignExt16to64 x) (SignExt16to64 y))
+(Less8 x y) => (SLT (SignExt8to64 x) (SignExt8to64 y))
+(Less64U ...) => (SLTU ...)
+(Less32U x y) => (SLTU (ZeroExt32to64 x) (ZeroExt32to64 y))
+(Less16U x y) => (SLTU (ZeroExt16to64 x) (ZeroExt16to64 y))
+(Less8U x y) => (SLTU (ZeroExt8to64 x) (ZeroExt8to64 y))
+(Less64F ...) => (FLTD ...)
+(Less32F ...) => (FLTS ...)
+
+// Convert x <= y to !(y > x).
+(Leq64 x y) => (Not (Less64 y x))
+(Leq32 x y) => (Not (Less32 y x))
+(Leq16 x y) => (Not (Less16 y x))
+(Leq8 x y) => (Not (Less8 y x))
+(Leq64U x y) => (Not (Less64U y x))
+(Leq32U x y) => (Not (Less32U y x))
+(Leq16U x y) => (Not (Less16U y x))
+(Leq8U x y) => (Not (Less8U y x))
+(Leq64F ...) => (FLED ...)
+(Leq32F ...) => (FLES ...)
+
+(EqPtr x y) => (SEQZ (SUB <x.Type> x y))
+(Eq64 x y) => (SEQZ (SUB <x.Type> x y))
+(Eq32 x y) => (SEQZ (SUBW <x.Type> x y))
+(Eq16 x y) => (SEQZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
+(Eq8 x y) => (SEQZ (SUB <x.Type> (ZeroExt8to64 x) (ZeroExt8to64 y)))
+(Eq64F ...) => (FEQD ...)
+(Eq32F ...) => (FEQS ...)
+
+(NeqPtr x y) => (SNEZ (SUB <x.Type> x y))
+(Neq64 x y) => (SNEZ (SUB <x.Type> x y))
+(Neq32 x y) => (SNEZ (SUBW <x.Type> x y))
+(Neq16 x y) => (SNEZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
+(Neq8 x y) => (SNEZ (SUB <x.Type> (ZeroExt8to64 x) (ZeroExt8to64 y)))
+(Neq64F ...) => (FNED ...)
+(Neq32F ...) => (FNES ...)
+
+// Loads
+(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
+(Load <t> ptr mem) && ( is8BitInt(t) && isSigned(t)) => (MOVBload ptr mem)
+(Load <t> ptr mem) && ( is8BitInt(t) && !isSigned(t)) => (MOVBUload ptr mem)
+(Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) => (MOVHload ptr mem)
+(Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) => (MOVHUload ptr mem)
+(Load <t> ptr mem) && (is32BitInt(t) && isSigned(t)) => (MOVWload ptr mem)
+(Load <t> ptr mem) && (is32BitInt(t) && !isSigned(t)) => (MOVWUload ptr mem)
+(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) => (MOVDload ptr mem)
+(Load <t> ptr mem) && is32BitFloat(t) => (FMOVWload ptr mem)
+(Load <t> ptr mem) && is64BitFloat(t) => (FMOVDload ptr mem)
+
+// Stores
+(Store {t} ptr val mem) && t.Size() == 1 => (MOVBstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 2 => (MOVHstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && !is32BitFloat(val.Type) => (MOVWstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 && !is64BitFloat(val.Type) => (MOVDstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && is32BitFloat(val.Type) => (FMOVWstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 && is64BitFloat(val.Type) => (FMOVDstore ptr val mem)
+
+// We need to fold MOVaddr into the LD/MOVDstore ops so that the live variable analysis
+// knows what variables are being read/written by the ops.
+(MOVBUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVBload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVHUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVHload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVHload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVWUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVWload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVDload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+
+(MOVBstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVHstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVWstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVDstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVBstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVHstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVWstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+(MOVDstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) =>
+ (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+
+(MOVBUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
+ (MOVBUload [off1+int32(off2)] {sym} base mem)
+(MOVBload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
+ (MOVBload [off1+int32(off2)] {sym} base mem)
+(MOVHUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
+ (MOVHUload [off1+int32(off2)] {sym} base mem)
+(MOVHload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
+ (MOVHload [off1+int32(off2)] {sym} base mem)
+(MOVWUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
+ (MOVWUload [off1+int32(off2)] {sym} base mem)
+(MOVWload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
+ (MOVWload [off1+int32(off2)] {sym} base mem)
+(MOVDload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
+ (MOVDload [off1+int32(off2)] {sym} base mem)
+
+(MOVBstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) =>
+ (MOVBstore [off1+int32(off2)] {sym} base val mem)
+(MOVHstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) =>
+ (MOVHstore [off1+int32(off2)] {sym} base val mem)
+(MOVWstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) =>
+ (MOVWstore [off1+int32(off2)] {sym} base val mem)
+(MOVDstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) =>
+ (MOVDstore [off1+int32(off2)] {sym} base val mem)
+(MOVBstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVBstorezero [off1+int32(off2)] {sym} ptr mem)
+(MOVHstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVHstorezero [off1+int32(off2)] {sym} ptr mem)
+(MOVWstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVWstorezero [off1+int32(off2)] {sym} ptr mem)
+(MOVDstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVDstorezero [off1+int32(off2)] {sym} ptr mem)
+
+// Similarly, fold ADDI into MOVaddr to avoid confusing live variable analysis
+// with OffPtr -> ADDI.
+(ADDI [c] (MOVaddr [d] {s} x)) && is32Bit(c+int64(d)) => (MOVaddr [int32(c)+d] {s} x)
+
+// Small zeroing
+(Zero [0] _ mem) => mem
+(Zero [1] ptr mem) => (MOVBstore ptr (MOVBconst [0]) mem)
+(Zero [2] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore ptr (MOVHconst [0]) mem)
+(Zero [2] ptr mem) =>
+ (MOVBstore [1] ptr (MOVBconst [0])
+ (MOVBstore ptr (MOVBconst [0]) mem))
+(Zero [4] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore ptr (MOVWconst [0]) mem)
+(Zero [4] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [2] ptr (MOVHconst [0])
+ (MOVHstore ptr (MOVHconst [0]) mem))
+(Zero [4] ptr mem) =>
+ (MOVBstore [3] ptr (MOVBconst [0])
+ (MOVBstore [2] ptr (MOVBconst [0])
+ (MOVBstore [1] ptr (MOVBconst [0])
+ (MOVBstore ptr (MOVBconst [0]) mem))))
+(Zero [8] {t} ptr mem) && t.Alignment()%8 == 0 =>
+ (MOVDstore ptr (MOVDconst [0]) mem)
+(Zero [8] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [4] ptr (MOVWconst [0])
+ (MOVWstore ptr (MOVWconst [0]) mem))
+(Zero [8] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [6] ptr (MOVHconst [0])
+ (MOVHstore [4] ptr (MOVHconst [0])
+ (MOVHstore [2] ptr (MOVHconst [0])
+ (MOVHstore ptr (MOVHconst [0]) mem))))
+
+(Zero [3] ptr mem) =>
+ (MOVBstore [2] ptr (MOVBconst [0])
+ (MOVBstore [1] ptr (MOVBconst [0])
+ (MOVBstore ptr (MOVBconst [0]) mem)))
+(Zero [6] {t} ptr mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [4] ptr (MOVHconst [0])
+ (MOVHstore [2] ptr (MOVHconst [0])
+ (MOVHstore ptr (MOVHconst [0]) mem)))
+(Zero [12] {t} ptr mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [8] ptr (MOVWconst [0])
+ (MOVWstore [4] ptr (MOVWconst [0])
+ (MOVWstore ptr (MOVWconst [0]) mem)))
+(Zero [16] {t} ptr mem) && t.Alignment()%8 == 0 =>
+ (MOVDstore [8] ptr (MOVDconst [0])
+ (MOVDstore ptr (MOVDconst [0]) mem))
+(Zero [24] {t} ptr mem) && t.Alignment()%8 == 0 =>
+ (MOVDstore [16] ptr (MOVDconst [0])
+ (MOVDstore [8] ptr (MOVDconst [0])
+ (MOVDstore ptr (MOVDconst [0]) mem)))
+(Zero [32] {t} ptr mem) && t.Alignment()%8 == 0 =>
+ (MOVDstore [24] ptr (MOVDconst [0])
+ (MOVDstore [16] ptr (MOVDconst [0])
+ (MOVDstore [8] ptr (MOVDconst [0])
+ (MOVDstore ptr (MOVDconst [0]) mem))))
+
+// Medium 8-aligned zeroing uses a Duff's device
+// 8 and 128 are magic constants, see runtime/mkduff.go
+(Zero [s] {t} ptr mem)
+ && s%8 == 0 && s <= 8*128
+ && t.Alignment()%8 == 0 && !config.noDuffDevice =>
+ (DUFFZERO [8 * (128 - s/8)] ptr mem)
+
+// Generic zeroing uses a loop
+(Zero [s] {t} ptr mem) =>
+ (LoweredZero [t.Alignment()]
+ ptr
+ (ADD <ptr.Type> ptr (MOVDconst [s-moveSize(t.Alignment(), config)]))
+ mem)
+
+(Convert ...) => (MOVconvert ...)
+
+// Checks
+(IsNonNil p) => (NeqPtr (MOVDconst [0]) p)
+(IsInBounds ...) => (Less64U ...)
+(IsSliceInBounds ...) => (Leq64U ...)
+
+// Trivial lowering
+(NilCheck ...) => (LoweredNilCheck ...)
+(GetClosurePtr ...) => (LoweredGetClosurePtr ...)
+(GetCallerSP ...) => (LoweredGetCallerSP ...)
+(GetCallerPC ...) => (LoweredGetCallerPC ...)
+
+// Write barrier.
+(WB ...) => (LoweredWB ...)
+
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
+
+// Small moves
+(Move [0] _ _ mem) => mem
+(Move [1] dst src mem) => (MOVBstore dst (MOVBload src mem) mem)
+(Move [2] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore dst (MOVHload src mem) mem)
+(Move [2] dst src mem) =>
+ (MOVBstore [1] dst (MOVBload [1] src mem)
+ (MOVBstore dst (MOVBload src mem) mem))
+(Move [4] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore dst (MOVWload src mem) mem)
+(Move [4] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [2] dst (MOVHload [2] src mem)
+ (MOVHstore dst (MOVHload src mem) mem))
+(Move [4] dst src mem) =>
+ (MOVBstore [3] dst (MOVBload [3] src mem)
+ (MOVBstore [2] dst (MOVBload [2] src mem)
+ (MOVBstore [1] dst (MOVBload [1] src mem)
+ (MOVBstore dst (MOVBload src mem) mem))))
+(Move [8] {t} dst src mem) && t.Alignment()%8 == 0 =>
+ (MOVDstore dst (MOVDload src mem) mem)
+(Move [8] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [4] dst (MOVWload [4] src mem)
+ (MOVWstore dst (MOVWload src mem) mem))
+(Move [8] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [6] dst (MOVHload [6] src mem)
+ (MOVHstore [4] dst (MOVHload [4] src mem)
+ (MOVHstore [2] dst (MOVHload [2] src mem)
+ (MOVHstore dst (MOVHload src mem) mem))))
+
+(Move [3] dst src mem) =>
+ (MOVBstore [2] dst (MOVBload [2] src mem)
+ (MOVBstore [1] dst (MOVBload [1] src mem)
+ (MOVBstore dst (MOVBload src mem) mem)))
+(Move [6] {t} dst src mem) && t.Alignment()%2 == 0 =>
+ (MOVHstore [4] dst (MOVHload [4] src mem)
+ (MOVHstore [2] dst (MOVHload [2] src mem)
+ (MOVHstore dst (MOVHload src mem) mem)))
+(Move [12] {t} dst src mem) && t.Alignment()%4 == 0 =>
+ (MOVWstore [8] dst (MOVWload [8] src mem)
+ (MOVWstore [4] dst (MOVWload [4] src mem)
+ (MOVWstore dst (MOVWload src mem) mem)))
+(Move [16] {t} dst src mem) && t.Alignment()%8 == 0 =>
+ (MOVDstore [8] dst (MOVDload [8] src mem)
+ (MOVDstore dst (MOVDload src mem) mem))
+(Move [24] {t} dst src mem) && t.Alignment()%8 == 0 =>
+ (MOVDstore [16] dst (MOVDload [16] src mem)
+ (MOVDstore [8] dst (MOVDload [8] src mem)
+ (MOVDstore dst (MOVDload src mem) mem)))
+(Move [32] {t} dst src mem) && t.Alignment()%8 == 0 =>
+ (MOVDstore [24] dst (MOVDload [24] src mem)
+ (MOVDstore [16] dst (MOVDload [16] src mem)
+ (MOVDstore [8] dst (MOVDload [8] src mem)
+ (MOVDstore dst (MOVDload src mem) mem))))
+
+// Medium 8-aligned move uses a Duff's device
+// 16 and 128 are magic constants, see runtime/mkduff.go
+(Move [s] {t} dst src mem)
+ && s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0
+ && !config.noDuffDevice && logLargeCopy(v, s) =>
+ (DUFFCOPY [16 * (128 - s/8)] dst src mem)
+
+// Generic move uses a loop
+(Move [s] {t} dst src mem) && (s <= 16 || logLargeCopy(v, s)) =>
+ (LoweredMove [t.Alignment()]
+ dst
+ src
+ (ADDI <src.Type> [s-moveSize(t.Alignment(), config)] src)
+ mem)
+
+// Boolean ops; 0=false, 1=true
+(AndB ...) => (AND ...)
+(OrB ...) => (OR ...)
+(EqB x y) => (SEQZ (XOR <typ.Bool> x y))
+(NeqB ...) => (XOR ...)
+(Not ...) => (SEQZ ...)
+
+// Lowering pointer arithmetic
+// TODO: Special handling for SP offsets, like ARM
+(OffPtr [off] ptr:(SP)) && is32Bit(off) => (MOVaddr [int32(off)] ptr)
+(OffPtr [off] ptr) && is32Bit(off) => (ADDI [off] ptr)
+(OffPtr [off] ptr) => (ADD (MOVDconst [off]) ptr)
+
+// TODO(jsing): Check if we actually need MOV{B,H,W}const as most platforms
+// use a single MOVDconst op.
+(Const8 ...) => (MOVBconst ...)
+(Const16 ...) => (MOVHconst ...)
+(Const32 ...) => (MOVWconst ...)
+(Const64 ...) => (MOVDconst ...)
+(Const32F [val]) => (FMVSX (MOVWconst [int32(math.Float32bits(val))]))
+(Const64F [val]) => (FMVDX (MOVDconst [int64(math.Float64bits(val))]))
+(ConstNil) => (MOVDconst [0])
+(ConstBool [val]) => (MOVBconst [int8(b2i(val))])
+
+// Convert 64 bit immediate to two 32 bit immediates, combine with add and shift.
+// The lower 32 bit immediate will be treated as signed,
+// so if it is negative, adjust for the borrow by incrementing the top half.
+// We don't have to worry about overflow from the increment,
+// because if the top half is all 1s, and int32(c) is negative,
+// then the overall constant fits in an int32.
+(MOVDconst <t> [c]) && !is32Bit(c) && int32(c) < 0 => (ADD (SLLI <t> [32] (MOVDconst [c>>32+1])) (MOVDconst [int64(int32(c))]))
+(MOVDconst <t> [c]) && !is32Bit(c) && int32(c) >= 0 => (ADD (SLLI <t> [32] (MOVDconst [c>>32+0])) (MOVDconst [int64(int32(c))]))
+
+(Addr {sym} base) => (MOVaddr {sym} [0] base)
+(LocalAddr {sym} base _) => (MOVaddr {sym} base)
+
+// Calls
+(StaticCall ...) => (CALLstatic ...)
+(ClosureCall ...) => (CALLclosure ...)
+(InterCall ...) => (CALLinter ...)
+
+// Atomic Intrinsics
+(AtomicLoad8 ...) => (LoweredAtomicLoad8 ...)
+(AtomicLoad32 ...) => (LoweredAtomicLoad32 ...)
+(AtomicLoad64 ...) => (LoweredAtomicLoad64 ...)
+(AtomicLoadPtr ...) => (LoweredAtomicLoad64 ...)
+
+(AtomicStore8 ...) => (LoweredAtomicStore8 ...)
+(AtomicStore32 ...) => (LoweredAtomicStore32 ...)
+(AtomicStore64 ...) => (LoweredAtomicStore64 ...)
+(AtomicStorePtrNoWB ...) => (LoweredAtomicStore64 ...)
+
+(AtomicAdd32 ...) => (LoweredAtomicAdd32 ...)
+(AtomicAdd64 ...) => (LoweredAtomicAdd64 ...)
+
+(AtomicCompareAndSwap32 ...) => (LoweredAtomicCas32 ...)
+(AtomicCompareAndSwap64 ...) => (LoweredAtomicCas64 ...)
+
+(AtomicExchange32 ...) => (LoweredAtomicExchange32 ...)
+(AtomicExchange64 ...) => (LoweredAtomicExchange64 ...)
+
+// Conditional branches
+(If cond yes no) => (BNEZ cond yes no)
+
+// Optimizations
+
+// Absorb SEQZ/SNEZ into branch.
+(BEQZ (SEQZ x) yes no) => (BNEZ x yes no)
+(BEQZ (SNEZ x) yes no) => (BEQZ x yes no)
+(BNEZ (SEQZ x) yes no) => (BEQZ x yes no)
+(BNEZ (SNEZ x) yes no) => (BNEZ x yes no)
+
+// Convert BEQZ/BNEZ into more optimal branch conditions.
+(BEQZ (SUB x y) yes no) => (BEQ x y yes no)
+(BNEZ (SUB x y) yes no) => (BNE x y yes no)
+(BEQZ (SLT x y) yes no) => (BGE x y yes no)
+(BNEZ (SLT x y) yes no) => (BLT x y yes no)
+(BEQZ (SLTU x y) yes no) => (BGEU x y yes no)
+(BNEZ (SLTU x y) yes no) => (BLTU x y yes no)
+
+// Convert branch with zero to BEQZ/BNEZ.
+(BEQ (MOVDconst [0]) cond yes no) => (BEQZ cond yes no)
+(BEQ cond (MOVDconst [0]) yes no) => (BEQZ cond yes no)
+(BNE (MOVDconst [0]) cond yes no) => (BNEZ cond yes no)
+(BNE cond (MOVDconst [0]) yes no) => (BNEZ cond yes no)
+
+// Store zero
+(MOVBstore [off] {sym} ptr (MOVBconst [0]) mem) => (MOVBstorezero [off] {sym} ptr mem)
+(MOVHstore [off] {sym} ptr (MOVHconst [0]) mem) => (MOVHstorezero [off] {sym} ptr mem)
+(MOVWstore [off] {sym} ptr (MOVWconst [0]) mem) => (MOVWstorezero [off] {sym} ptr mem)
+(MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVDstorezero [off] {sym} ptr mem)
+
+// Avoid sign/zero extension for consts.
+(MOVBreg (MOVBconst [c])) => (MOVDconst [int64(c)])
+(MOVHreg (MOVBconst [c])) => (MOVDconst [int64(c)])
+(MOVHreg (MOVHconst [c])) => (MOVDconst [int64(c)])
+(MOVWreg (MOVBconst [c])) => (MOVDconst [int64(c)])
+(MOVWreg (MOVHconst [c])) => (MOVDconst [int64(c)])
+(MOVWreg (MOVWconst [c])) => (MOVDconst [int64(c)])
+(MOVBUreg (MOVBconst [c])) => (MOVDconst [int64(uint8(c))])
+(MOVHUreg (MOVBconst [c])) => (MOVDconst [int64(uint16(c))])
+(MOVHUreg (MOVHconst [c])) => (MOVDconst [int64(uint16(c))])
+(MOVWUreg (MOVBconst [c])) => (MOVDconst [int64(uint32(c))])
+(MOVWUreg (MOVHconst [c])) => (MOVDconst [int64(uint32(c))])
+(MOVWUreg (MOVWconst [c])) => (MOVDconst [int64(uint32(c))])
+
+// Avoid sign/zero extension after properly typed load.
+(MOVBreg x:(MOVBload _ _)) => (MOVDreg x)
+(MOVHreg x:(MOVBload _ _)) => (MOVDreg x)
+(MOVHreg x:(MOVBUload _ _)) => (MOVDreg x)
+(MOVHreg x:(MOVHload _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVBload _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVBUload _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVHload _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVHUload _ _)) => (MOVDreg x)
+(MOVWreg x:(MOVWload _ _)) => (MOVDreg x)
+(MOVBUreg x:(MOVBUload _ _)) => (MOVDreg x)
+(MOVHUreg x:(MOVBUload _ _)) => (MOVDreg x)
+(MOVHUreg x:(MOVHUload _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVBUload _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVHUload _ _)) => (MOVDreg x)
+(MOVWUreg x:(MOVWUload _ _)) => (MOVDreg x)
+
+// Fold double extensions.
+(MOVBreg x:(MOVBreg _)) => (MOVDreg x)
+(MOVHreg x:(MOVBreg _)) => (MOVDreg x)
+(MOVHreg x:(MOVBUreg _)) => (MOVDreg x)
+(MOVHreg x:(MOVHreg _)) => (MOVDreg x)
+(MOVWreg x:(MOVBreg _)) => (MOVDreg x)
+(MOVWreg x:(MOVBUreg _)) => (MOVDreg x)
+(MOVWreg x:(MOVHreg _)) => (MOVDreg x)
+(MOVWreg x:(MOVWreg _)) => (MOVDreg x)
+(MOVBUreg x:(MOVBUreg _)) => (MOVDreg x)
+(MOVHUreg x:(MOVBUreg _)) => (MOVDreg x)
+(MOVHUreg x:(MOVHUreg _)) => (MOVDreg x)
+(MOVWUreg x:(MOVBUreg _)) => (MOVDreg x)
+(MOVWUreg x:(MOVHUreg _)) => (MOVDreg x)
+(MOVWUreg x:(MOVWUreg _)) => (MOVDreg x)
+
+// Do not extend before store.
+(MOVBstore [off] {sym} ptr (MOVBreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVHreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVWreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVBUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVHUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVWreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOVWreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
+
+// Replace extend after load with alternate load where possible.
+(MOVBreg <t> x:(MOVBUload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBload <t> [off] {sym} ptr mem)
+(MOVHreg <t> x:(MOVHUload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVHload <t> [off] {sym} ptr mem)
+(MOVWreg <t> x:(MOVWUload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWload <t> [off] {sym} ptr mem)
+(MOVBUreg <t> x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVBUload <t> [off] {sym} ptr mem)
+(MOVHUreg <t> x:(MOVHload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVHUload <t> [off] {sym} ptr mem)
+(MOVWUreg <t> x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWUload <t> [off] {sym} ptr mem)
+
+// If a register move has only 1 use, just use the same register without emitting instruction
+// MOVnop does not emit an instruction, only for ensuring the type.
+(MOVDreg x) && x.Uses == 1 => (MOVDnop x)
+
+// Fold constant into immediate instructions where possible.
+(ADD (MOVBconst [val]) x) => (ADDI [int64(val)] x)
+(ADD (MOVHconst [val]) x) => (ADDI [int64(val)] x)
+(ADD (MOVWconst [val]) x) => (ADDI [int64(val)] x)
+(ADD (MOVDconst [val]) x) && is32Bit(val) => (ADDI [val] x)
+
+(AND (MOVBconst [val]) x) => (ANDI [int64(val)] x)
+(AND (MOVHconst [val]) x) => (ANDI [int64(val)] x)
+(AND (MOVWconst [val]) x) => (ANDI [int64(val)] x)
+(AND (MOVDconst [val]) x) && is32Bit(val) => (ANDI [val] x)
+
+(OR (MOVBconst [val]) x) => (ORI [int64(val)] x)
+(OR (MOVHconst [val]) x) => (ORI [int64(val)] x)
+(OR (MOVWconst [val]) x) => (ORI [int64(val)] x)
+(OR (MOVDconst [val]) x) && is32Bit(val) => (ORI [val] x)
+
+(XOR (MOVBconst [val]) x) => (XORI [int64(val)] x)
+(XOR (MOVHconst [val]) x) => (XORI [int64(val)] x)
+(XOR (MOVWconst [val]) x) => (XORI [int64(val)] x)
+(XOR (MOVDconst [val]) x) && is32Bit(val) => (XORI [val] x)
+
+(SLL x (MOVBconst [val])) => (SLLI [int64(val&63)] x)
+(SLL x (MOVHconst [val])) => (SLLI [int64(val&63)] x)
+(SLL x (MOVWconst [val])) => (SLLI [int64(val&63)] x)
+(SLL x (MOVDconst [val])) => (SLLI [int64(val&63)] x)
+
+(SRL x (MOVBconst [val])) => (SRLI [int64(val&63)] x)
+(SRL x (MOVHconst [val])) => (SRLI [int64(val&63)] x)
+(SRL x (MOVWconst [val])) => (SRLI [int64(val&63)] x)
+(SRL x (MOVDconst [val])) => (SRLI [int64(val&63)] x)
+
+(SRA x (MOVBconst [val])) => (SRAI [int64(val&63)] x)
+(SRA x (MOVHconst [val])) => (SRAI [int64(val&63)] x)
+(SRA x (MOVWconst [val])) => (SRAI [int64(val&63)] x)
+(SRA x (MOVDconst [val])) => (SRAI [int64(val&63)] x)
+
+// Convert subtraction of a const into ADDI with negative immediate, where possible.
+(SUB x (MOVBconst [val])) => (ADDI [-int64(val)] x)
+(SUB x (MOVHconst [val])) => (ADDI [-int64(val)] x)
+(SUB x (MOVWconst [val])) && is32Bit(-int64(val)) => (ADDI [-int64(val)] x)
+(SUB x (MOVDconst [val])) && is32Bit(-val) => (ADDI [-val] x)
+
+// Subtraction of zero.
+(SUB x (MOVBconst [0])) => x
+(SUB x (MOVHconst [0])) => x
+(SUB x (MOVWconst [0])) => x
+(SUB x (MOVDconst [0])) => x
+
+// Subtraction of zero with sign extension.
+(SUBW x (MOVWconst [0])) => (ADDIW [0] x)
+
+// Subtraction from zero.
+(SUB (MOVBconst [0]) x) => (NEG x)
+(SUB (MOVHconst [0]) x) => (NEG x)
+(SUB (MOVWconst [0]) x) => (NEG x)
+(SUB (MOVDconst [0]) x) => (NEG x)
+
+// Subtraction from zero with sign extension.
+(SUBW (MOVDconst [0]) x) => (NEGW x)
+
+// Addition of zero.
+(ADDI [0] x) => x
diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go
new file mode 100644
index 0000000..f643192
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go
@@ -0,0 +1,464 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "fmt"
+)
+
+// Notes:
+// - Boolean types occupy the entire register. 0=false, 1=true.
+
+// Suffixes encode the bit width of various instructions:
+//
+// D (double word) = 64 bit int
+// W (word) = 32 bit int
+// H (half word) = 16 bit int
+// B (byte) = 8 bit int
+// S (single) = 32 bit float
+// D (double) = 64 bit float
+// L = 64 bit int, used when the opcode starts with F
+
+const (
+ riscv64REG_G = 27
+ riscv64REG_CTXT = 20
+ riscv64REG_LR = 1
+ riscv64REG_SP = 2
+ riscv64REG_TP = 4
+ riscv64REG_TMP = 31
+ riscv64REG_ZERO = 0
+)
+
+func riscv64RegName(r int) string {
+ switch {
+ case r == riscv64REG_G:
+ return "g"
+ case r == riscv64REG_SP:
+ return "SP"
+ case 0 <= r && r <= 31:
+ return fmt.Sprintf("X%d", r)
+ case 32 <= r && r <= 63:
+ return fmt.Sprintf("F%d", r-32)
+ default:
+ panic(fmt.Sprintf("unknown register %d", r))
+ }
+}
+
+func init() {
+ var regNamesRISCV64 []string
+ var gpMask, fpMask, gpgMask, gpspMask, gpspsbMask, gpspsbgMask regMask
+ regNamed := make(map[string]regMask)
+
+ // Build the list of register names, creating an appropriately indexed
+ // regMask for the gp and fp registers as we go.
+ //
+ // If name is specified, use it rather than the riscv reg number.
+ addreg := func(r int, name string) regMask {
+ mask := regMask(1) << uint(len(regNamesRISCV64))
+ if name == "" {
+ name = riscv64RegName(r)
+ }
+ regNamesRISCV64 = append(regNamesRISCV64, name)
+ regNamed[name] = mask
+ return mask
+ }
+
+ // General purpose registers.
+ for r := 0; r <= 31; r++ {
+ if r == riscv64REG_LR {
+ // LR is not used by regalloc, so we skip it to leave
+ // room for pseudo-register SB.
+ continue
+ }
+
+ mask := addreg(r, "")
+
+ // Add general purpose registers to gpMask.
+ switch r {
+ // ZERO, TP and TMP are not in any gp mask.
+ case riscv64REG_ZERO, riscv64REG_TP, riscv64REG_TMP:
+ case riscv64REG_G:
+ gpgMask |= mask
+ gpspsbgMask |= mask
+ case riscv64REG_SP:
+ gpspMask |= mask
+ gpspsbMask |= mask
+ gpspsbgMask |= mask
+ default:
+ gpMask |= mask
+ gpgMask |= mask
+ gpspMask |= mask
+ gpspsbMask |= mask
+ gpspsbgMask |= mask
+ }
+ }
+
+ // Floating pointer registers.
+ for r := 32; r <= 63; r++ {
+ mask := addreg(r, "")
+ fpMask |= mask
+ }
+
+ // Pseudo-register: SB
+ mask := addreg(-1, "SB")
+ gpspsbMask |= mask
+ gpspsbgMask |= mask
+
+ if len(regNamesRISCV64) > 64 {
+ // regMask is only 64 bits.
+ panic("Too many RISCV64 registers")
+ }
+
+ regCtxt := regNamed["X20"]
+ callerSave := gpMask | fpMask | regNamed["g"]
+
+ var (
+ gpstore = regInfo{inputs: []regMask{gpspsbMask, gpspMask, 0}} // SB in first input so we can load from a global, but not in second to avoid using SB as a temporary register
+ gpstore0 = regInfo{inputs: []regMask{gpspsbMask}}
+ gp01 = regInfo{outputs: []regMask{gpMask}}
+ gp11 = regInfo{inputs: []regMask{gpMask}, outputs: []regMask{gpMask}}
+ gp21 = regInfo{inputs: []regMask{gpMask, gpMask}, outputs: []regMask{gpMask}}
+ gpload = regInfo{inputs: []regMask{gpspsbMask, 0}, outputs: []regMask{gpMask}}
+ gp11sb = regInfo{inputs: []regMask{gpspsbMask}, outputs: []regMask{gpMask}}
+ gpxchg = regInfo{inputs: []regMask{gpspsbgMask, gpgMask}, outputs: []regMask{gpMask}}
+ gpcas = regInfo{inputs: []regMask{gpspsbgMask, gpgMask, gpgMask}, outputs: []regMask{gpMask}}
+
+ fp11 = regInfo{inputs: []regMask{fpMask}, outputs: []regMask{fpMask}}
+ fp21 = regInfo{inputs: []regMask{fpMask, fpMask}, outputs: []regMask{fpMask}}
+ gpfp = regInfo{inputs: []regMask{gpMask}, outputs: []regMask{fpMask}}
+ fpgp = regInfo{inputs: []regMask{fpMask}, outputs: []regMask{gpMask}}
+ fpstore = regInfo{inputs: []regMask{gpspsbMask, fpMask, 0}}
+ fpload = regInfo{inputs: []regMask{gpspsbMask, 0}, outputs: []regMask{fpMask}}
+ fp2gp = regInfo{inputs: []regMask{fpMask, fpMask}, outputs: []regMask{gpMask}}
+
+ call = regInfo{clobbers: callerSave}
+ callClosure = regInfo{inputs: []regMask{gpspMask, regCtxt, 0}, clobbers: callerSave}
+ callInter = regInfo{inputs: []regMask{gpMask}, clobbers: callerSave}
+ )
+
+ RISCV64ops := []opData{
+ {name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1
+ {name: "ADDI", argLength: 1, reg: gp11sb, asm: "ADDI", aux: "Int64"}, // arg0 + auxint
+ {name: "ADDIW", argLength: 1, reg: gp11, asm: "ADDIW", aux: "Int64"}, // 32 low bits of arg0 + auxint, sign extended to 64 bits
+ {name: "NEG", argLength: 1, reg: gp11, asm: "NEG"}, // -arg0
+ {name: "NEGW", argLength: 1, reg: gp11, asm: "NEGW"}, // -arg0 of 32 bits, sign extended to 64 bits
+ {name: "SUB", argLength: 2, reg: gp21, asm: "SUB"}, // arg0 - arg1
+ {name: "SUBW", argLength: 2, reg: gp21, asm: "SUBW"}, // 32 low bits of arg 0 - 32 low bits of arg 1, sign extended to 64 bits
+
+ // M extension. H means high (i.e., it returns the top bits of
+ // the result). U means unsigned. W means word (i.e., 32-bit).
+ {name: "MUL", argLength: 2, reg: gp21, asm: "MUL", commutative: true, typ: "Int64"}, // arg0 * arg1
+ {name: "MULW", argLength: 2, reg: gp21, asm: "MULW", commutative: true, typ: "Int32"},
+ {name: "MULH", argLength: 2, reg: gp21, asm: "MULH", commutative: true, typ: "Int64"},
+ {name: "MULHU", argLength: 2, reg: gp21, asm: "MULHU", commutative: true, typ: "UInt64"},
+ {name: "DIV", argLength: 2, reg: gp21, asm: "DIV", typ: "Int64"}, // arg0 / arg1
+ {name: "DIVU", argLength: 2, reg: gp21, asm: "DIVU", typ: "UInt64"},
+ {name: "DIVW", argLength: 2, reg: gp21, asm: "DIVW", typ: "Int32"},
+ {name: "DIVUW", argLength: 2, reg: gp21, asm: "DIVUW", typ: "UInt32"},
+ {name: "REM", argLength: 2, reg: gp21, asm: "REM", typ: "Int64"}, // arg0 % arg1
+ {name: "REMU", argLength: 2, reg: gp21, asm: "REMU", typ: "UInt64"},
+ {name: "REMW", argLength: 2, reg: gp21, asm: "REMW", typ: "Int32"},
+ {name: "REMUW", argLength: 2, reg: gp21, asm: "REMUW", typ: "UInt32"},
+
+ {name: "MOVaddr", argLength: 1, reg: gp11sb, asm: "MOV", aux: "SymOff", rematerializeable: true, symEffect: "RdWr"}, // arg0 + auxint + offset encoded in aux
+ // auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
+
+ {name: "MOVBconst", reg: gp01, asm: "MOV", typ: "UInt8", aux: "Int8", rematerializeable: true}, // 8 low bits of auxint
+ {name: "MOVHconst", reg: gp01, asm: "MOV", typ: "UInt16", aux: "Int16", rematerializeable: true}, // 16 low bits of auxint
+ {name: "MOVWconst", reg: gp01, asm: "MOV", typ: "UInt32", aux: "Int32", rematerializeable: true}, // 32 low bits of auxint
+ {name: "MOVDconst", reg: gp01, asm: "MOV", typ: "UInt64", aux: "Int64", rematerializeable: true}, // auxint
+
+ // Loads: load <size> bits from arg0+auxint+aux and extend to 64 bits; arg1=mem
+ {name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVB", aux: "SymOff", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"}, // 8 bits, sign extend
+ {name: "MOVHload", argLength: 2, reg: gpload, asm: "MOVH", aux: "SymOff", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // 16 bits, sign extend
+ {name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVW", aux: "SymOff", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"}, // 32 bits, sign extend
+ {name: "MOVDload", argLength: 2, reg: gpload, asm: "MOV", aux: "SymOff", typ: "Int64", faultOnNilArg0: true, symEffect: "Read"}, // 64 bits
+ {name: "MOVBUload", argLength: 2, reg: gpload, asm: "MOVBU", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // 8 bits, zero extend
+ {name: "MOVHUload", argLength: 2, reg: gpload, asm: "MOVHU", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // 16 bits, zero extend
+ {name: "MOVWUload", argLength: 2, reg: gpload, asm: "MOVWU", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // 32 bits, zero extend
+
+ // Stores: store <size> lowest bits in arg1 to arg0+auxint+aux; arg2=mem
+ {name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 8 bits
+ {name: "MOVHstore", argLength: 3, reg: gpstore, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 16 bits
+ {name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 32 bits
+ {name: "MOVDstore", argLength: 3, reg: gpstore, asm: "MOV", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 64 bits
+
+ // Stores: store <size> of zero in arg0+auxint+aux; arg1=mem
+ {name: "MOVBstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 8 bits
+ {name: "MOVHstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 16 bits
+ {name: "MOVWstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 32 bits
+ {name: "MOVDstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOV", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 64 bits
+
+ // Conversions
+ {name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB"}, // move from arg0, sign-extended from byte
+ {name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVH"}, // move from arg0, sign-extended from half
+ {name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"}, // move from arg0, sign-extended from word
+ {name: "MOVDreg", argLength: 1, reg: gp11, asm: "MOV"}, // move from arg0
+ {name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // move from arg0, unsign-extended from byte
+ {name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // move from arg0, unsign-extended from half
+ {name: "MOVWUreg", argLength: 1, reg: gp11, asm: "MOVWU"}, // move from arg0, unsign-extended from word
+
+ {name: "MOVDnop", argLength: 1, reg: regInfo{inputs: []regMask{gpMask}, outputs: []regMask{gpMask}}, resultInArg0: true}, // nop, return arg0 in same register
+
+ // Shift ops
+ {name: "SLL", argLength: 2, reg: gp21, asm: "SLL"}, // arg0 << (aux1 & 63)
+ {name: "SRA", argLength: 2, reg: gp21, asm: "SRA"}, // arg0 >> (aux1 & 63), signed
+ {name: "SRL", argLength: 2, reg: gp21, asm: "SRL"}, // arg0 >> (aux1 & 63), unsigned
+ {name: "SLLI", argLength: 1, reg: gp11, asm: "SLLI", aux: "Int64"}, // arg0 << auxint, shift amount 0-63
+ {name: "SRAI", argLength: 1, reg: gp11, asm: "SRAI", aux: "Int64"}, // arg0 >> auxint, signed, shift amount 0-63
+ {name: "SRLI", argLength: 1, reg: gp11, asm: "SRLI", aux: "Int64"}, // arg0 >> auxint, unsigned, shift amount 0-63
+
+ // Bitwise ops
+ {name: "XOR", argLength: 2, reg: gp21, asm: "XOR", commutative: true}, // arg0 ^ arg1
+ {name: "XORI", argLength: 1, reg: gp11, asm: "XORI", aux: "Int64"}, // arg0 ^ auxint
+ {name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true}, // arg0 | arg1
+ {name: "ORI", argLength: 1, reg: gp11, asm: "ORI", aux: "Int64"}, // arg0 | auxint
+ {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0 & arg1
+ {name: "ANDI", argLength: 1, reg: gp11, asm: "ANDI", aux: "Int64"}, // arg0 & auxint
+ {name: "NOT", argLength: 1, reg: gp11, asm: "NOT"}, // ^arg0
+
+ // Generate boolean values
+ {name: "SEQZ", argLength: 1, reg: gp11, asm: "SEQZ"}, // arg0 == 0, result is 0 or 1
+ {name: "SNEZ", argLength: 1, reg: gp11, asm: "SNEZ"}, // arg0 != 0, result is 0 or 1
+ {name: "SLT", argLength: 2, reg: gp21, asm: "SLT"}, // arg0 < arg1, result is 0 or 1
+ {name: "SLTI", argLength: 1, reg: gp11, asm: "SLTI", aux: "Int64"}, // arg0 < auxint, result is 0 or 1
+ {name: "SLTU", argLength: 2, reg: gp21, asm: "SLTU"}, // arg0 < arg1, unsigned, result is 0 or 1
+ {name: "SLTIU", argLength: 1, reg: gp11, asm: "SLTIU", aux: "Int64"}, // arg0 < auxint, unsigned, result is 0 or 1
+
+ // MOVconvert converts between pointers and integers.
+ // We have a special op for this so as to not confuse GC
+ // (particularly stack maps). It takes a memory arg so it
+ // gets correctly ordered with respect to GC safepoints.
+ {name: "MOVconvert", argLength: 2, reg: gp11, asm: "MOV"}, // arg0, but converted to int/ptr as appropriate; arg1=mem
+
+ // Calls
+ {name: "CALLstatic", argLength: 1, reg: call, aux: "CallOff", call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
+ {name: "CALLclosure", argLength: 3, reg: callClosure, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
+ {name: "CALLinter", argLength: 2, reg: callInter, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
+
+ // duffzero
+ // arg0 = address of memory to zero (in X10, changed as side effect)
+ // arg1 = mem
+ // auxint = offset into duffzero code to start executing
+ // X1 (link register) changed because of function call
+ // returns mem
+ {
+ name: "DUFFZERO",
+ aux: "Int64",
+ argLength: 2,
+ reg: regInfo{
+ inputs: []regMask{regNamed["X10"]},
+ clobbers: regNamed["X1"] | regNamed["X10"],
+ },
+ typ: "Mem",
+ faultOnNilArg0: true,
+ },
+
+ // duffcopy
+ // arg0 = address of dst memory (in X11, changed as side effect)
+ // arg1 = address of src memory (in X10, changed as side effect)
+ // arg2 = mem
+ // auxint = offset into duffcopy code to start executing
+ // X1 (link register) changed because of function call
+ // returns mem
+ {
+ name: "DUFFCOPY",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{regNamed["X11"], regNamed["X10"]},
+ clobbers: regNamed["X1"] | regNamed["X10"] | regNamed["X11"],
+ },
+ typ: "Mem",
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // Generic moves and zeros
+
+ // general unaligned zeroing
+ // arg0 = address of memory to zero (in X5, changed as side effect)
+ // arg1 = address of the last element to zero (inclusive)
+ // arg2 = mem
+ // auxint = element size
+ // returns mem
+ // mov ZERO, (X5)
+ // ADD $sz, X5
+ // BGEU Rarg1, X5, -2(PC)
+ {
+ name: "LoweredZero",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{regNamed["X5"], gpMask},
+ clobbers: regNamed["X5"],
+ },
+ typ: "Mem",
+ faultOnNilArg0: true,
+ },
+
+ // general unaligned move
+ // arg0 = address of dst memory (in X5, changed as side effect)
+ // arg1 = address of src memory (in X6, changed as side effect)
+ // arg2 = address of the last element of src (can't be X7 as we clobber it before using arg2)
+ // arg3 = mem
+ // auxint = alignment
+ // clobbers X7 as a tmp register.
+ // returns mem
+ // mov (X6), X7
+ // mov X7, (X5)
+ // ADD $sz, X5
+ // ADD $sz, X6
+ // BGEU Rarg2, X5, -4(PC)
+ {
+ name: "LoweredMove",
+ aux: "Int64",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{regNamed["X5"], regNamed["X6"], gpMask &^ regNamed["X7"]},
+ clobbers: regNamed["X5"] | regNamed["X6"] | regNamed["X7"],
+ },
+ typ: "Mem",
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // Atomic loads.
+ // load from arg0. arg1=mem.
+ // returns <value,memory> so they can be properly ordered with other loads.
+ {name: "LoweredAtomicLoad8", argLength: 2, reg: gpload, faultOnNilArg0: true},
+ {name: "LoweredAtomicLoad32", argLength: 2, reg: gpload, faultOnNilArg0: true},
+ {name: "LoweredAtomicLoad64", argLength: 2, reg: gpload, faultOnNilArg0: true},
+
+ // Atomic stores.
+ // store arg1 to arg0. arg2=mem. returns memory.
+ {name: "LoweredAtomicStore8", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicStore64", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
+
+ // Atomic exchange.
+ // store arg1 to *arg0. arg2=mem. returns <old content of *arg0, memory>.
+ {name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+ {name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+
+ // Atomic add.
+ // *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>.
+ {name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // Atomic compare and swap.
+ // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory.
+ // if *arg0 == arg1 {
+ // *arg0 = arg2
+ // return (true, memory)
+ // } else {
+ // return (false, memory)
+ // }
+ // MOV $0, Rout
+ // LR (Rarg0), Rtmp
+ // BNE Rtmp, Rarg1, 3(PC)
+ // SC Rarg2, (Rarg0), Rtmp
+ // BNE Rtmp, ZERO, -3(PC)
+ // MOV $1, Rout
+ {name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+ {name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
+
+ // Lowering pass-throughs
+ {name: "LoweredNilCheck", argLength: 2, faultOnNilArg0: true, nilCheck: true, reg: regInfo{inputs: []regMask{gpspMask}}}, // arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
+ {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{regCtxt}}}, // scheduler ensures only at beginning of entry block
+
+ // LoweredGetCallerSP returns the SP of the caller of the current function.
+ {name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
+
+ // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+ // I.e., if f calls g "calls" getcallerpc,
+ // the result should be the PC within f that g will return to.
+ // See runtime/stubs.go for a more detailed discussion.
+ {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
+
+ // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+ // It saves all GP registers if necessary,
+ // but clobbers RA (LR) because it's a call
+ // and T6 (REG_TMP).
+ {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{regNamed["X5"], regNamed["X6"]}, clobbers: (callerSave &^ (gpMask | regNamed["g"])) | regNamed["X1"]}, clobberFlags: true, aux: "Sym", symEffect: "None"},
+
+ // There are three of these functions so that they can have three different register inputs.
+ // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
+ // default registers to match so we don't need to copy registers around unnecessarily.
+ {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{regNamed["X7"], regNamed["X28"]}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{regNamed["X6"], regNamed["X7"]}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+ {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{regNamed["X5"], regNamed["X6"]}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
+
+ // F extension.
+ {name: "FADDS", argLength: 2, reg: fp21, asm: "FADDS", commutative: true, typ: "Float32"}, // arg0 + arg1
+ {name: "FSUBS", argLength: 2, reg: fp21, asm: "FSUBS", commutative: false, typ: "Float32"}, // arg0 - arg1
+ {name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true, typ: "Float32"}, // arg0 * arg1
+ {name: "FDIVS", argLength: 2, reg: fp21, asm: "FDIVS", commutative: false, typ: "Float32"}, // arg0 / arg1
+ {name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS", typ: "Float32"}, // sqrt(arg0)
+ {name: "FNEGS", argLength: 1, reg: fp11, asm: "FNEGS", typ: "Float32"}, // -arg0
+ {name: "FMVSX", argLength: 1, reg: gpfp, asm: "FMVSX", typ: "Float32"}, // reinterpret arg0 as float
+ {name: "FCVTSW", argLength: 1, reg: gpfp, asm: "FCVTSW", typ: "Float32"}, // float32(low 32 bits of arg0)
+ {name: "FCVTSL", argLength: 1, reg: gpfp, asm: "FCVTSL", typ: "Float32"}, // float32(arg0)
+ {name: "FCVTWS", argLength: 1, reg: fpgp, asm: "FCVTWS", typ: "Int32"}, // int32(arg0)
+ {name: "FCVTLS", argLength: 1, reg: fpgp, asm: "FCVTLS", typ: "Int64"}, // int64(arg0)
+ {name: "FMOVWload", argLength: 2, reg: fpload, asm: "MOVF", aux: "SymOff", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"}, // load float32 from arg0+auxint+aux
+ {name: "FMOVWstore", argLength: 3, reg: fpstore, asm: "MOVF", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store float32 to arg0+auxint+aux
+ {name: "FEQS", argLength: 2, reg: fp2gp, asm: "FEQS", commutative: true}, // arg0 == arg1
+ {name: "FNES", argLength: 2, reg: fp2gp, asm: "FNES", commutative: true}, // arg0 != arg1
+ {name: "FLTS", argLength: 2, reg: fp2gp, asm: "FLTS"}, // arg0 < arg1
+ {name: "FLES", argLength: 2, reg: fp2gp, asm: "FLES"}, // arg0 <= arg1
+
+ // D extension.
+ {name: "FADDD", argLength: 2, reg: fp21, asm: "FADDD", commutative: true, typ: "Float64"}, // arg0 + arg1
+ {name: "FSUBD", argLength: 2, reg: fp21, asm: "FSUBD", commutative: false, typ: "Float64"}, // arg0 - arg1
+ {name: "FMULD", argLength: 2, reg: fp21, asm: "FMULD", commutative: true, typ: "Float64"}, // arg0 * arg1
+ {name: "FDIVD", argLength: 2, reg: fp21, asm: "FDIVD", commutative: false, typ: "Float64"}, // arg0 / arg1
+ {name: "FSQRTD", argLength: 1, reg: fp11, asm: "FSQRTD", typ: "Float64"}, // sqrt(arg0)
+ {name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD", typ: "Float64"}, // -arg0
+ {name: "FMVDX", argLength: 1, reg: gpfp, asm: "FMVDX", typ: "Float64"}, // reinterpret arg0 as float
+ {name: "FCVTDW", argLength: 1, reg: gpfp, asm: "FCVTDW", typ: "Float64"}, // float64(low 32 bits of arg0)
+ {name: "FCVTDL", argLength: 1, reg: gpfp, asm: "FCVTDL", typ: "Float64"}, // float64(arg0)
+ {name: "FCVTWD", argLength: 1, reg: fpgp, asm: "FCVTWD", typ: "Int32"}, // int32(arg0)
+ {name: "FCVTLD", argLength: 1, reg: fpgp, asm: "FCVTLD", typ: "Int64"}, // int64(arg0)
+ {name: "FCVTDS", argLength: 1, reg: fp11, asm: "FCVTDS", typ: "Float64"}, // float64(arg0)
+ {name: "FCVTSD", argLength: 1, reg: fp11, asm: "FCVTSD", typ: "Float32"}, // float32(arg0)
+ {name: "FMOVDload", argLength: 2, reg: fpload, asm: "MOVD", aux: "SymOff", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"}, // load float64 from arg0+auxint+aux
+ {name: "FMOVDstore", argLength: 3, reg: fpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store float6 to arg0+auxint+aux
+ {name: "FEQD", argLength: 2, reg: fp2gp, asm: "FEQD", commutative: true}, // arg0 == arg1
+ {name: "FNED", argLength: 2, reg: fp2gp, asm: "FNED", commutative: true}, // arg0 != arg1
+ {name: "FLTD", argLength: 2, reg: fp2gp, asm: "FLTD"}, // arg0 < arg1
+ {name: "FLED", argLength: 2, reg: fp2gp, asm: "FLED"}, // arg0 <= arg1
+ }
+
+ RISCV64blocks := []blockData{
+ {name: "BEQ", controls: 2},
+ {name: "BNE", controls: 2},
+ {name: "BLT", controls: 2},
+ {name: "BGE", controls: 2},
+ {name: "BLTU", controls: 2},
+ {name: "BGEU", controls: 2},
+
+ {name: "BEQZ", controls: 1},
+ {name: "BNEZ", controls: 1},
+ {name: "BLEZ", controls: 1},
+ {name: "BGEZ", controls: 1},
+ {name: "BLTZ", controls: 1},
+ {name: "BGTZ", controls: 1},
+ }
+
+ archs = append(archs, arch{
+ name: "RISCV64",
+ pkg: "cmd/internal/obj/riscv",
+ genfile: "../../riscv64/ssa.go",
+ ops: RISCV64ops,
+ blocks: RISCV64blocks,
+ regnames: regNamesRISCV64,
+ gpregmask: gpMask,
+ fpregmask: fpMask,
+ framepointerreg: -1, // not used
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/S390X.rules b/src/cmd/compile/internal/ssa/gen/S390X.rules
new file mode 100644
index 0000000..384f2e8
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/S390X.rules
@@ -0,0 +1,1695 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Lowering arithmetic
+(Add(64|Ptr) ...) => (ADD ...)
+(Add(32|16|8) ...) => (ADDW ...)
+(Add32F x y) => (Select0 (FADDS x y))
+(Add64F x y) => (Select0 (FADD x y))
+
+(Sub(64|Ptr) ...) => (SUB ...)
+(Sub(32|16|8) ...) => (SUBW ...)
+(Sub32F x y) => (Select0 (FSUBS x y))
+(Sub64F x y) => (Select0 (FSUB x y))
+
+(Mul64 ...) => (MULLD ...)
+(Mul(32|16|8) ...) => (MULLW ...)
+(Mul32F ...) => (FMULS ...)
+(Mul64F ...) => (FMUL ...)
+(Mul64uhilo ...) => (MLGR ...)
+
+(Div32F ...) => (FDIVS ...)
+(Div64F ...) => (FDIV ...)
+
+(Div64 x y) => (DIVD x y)
+(Div64u ...) => (DIVDU ...)
+// DIVW/DIVWU has a 64-bit dividend and a 32-bit divisor,
+// so a sign/zero extension of the dividend is required.
+(Div32 x y) => (DIVW (MOVWreg x) y)
+(Div32u x y) => (DIVWU (MOVWZreg x) y)
+(Div16 x y) => (DIVW (MOVHreg x) (MOVHreg y))
+(Div16u x y) => (DIVWU (MOVHZreg x) (MOVHZreg y))
+(Div8 x y) => (DIVW (MOVBreg x) (MOVBreg y))
+(Div8u x y) => (DIVWU (MOVBZreg x) (MOVBZreg y))
+
+(Hmul(64|64u) ...) => (MULH(D|DU) ...)
+(Hmul32 x y) => (SRDconst [32] (MULLD (MOVWreg x) (MOVWreg y)))
+(Hmul32u x y) => (SRDconst [32] (MULLD (MOVWZreg x) (MOVWZreg y)))
+
+(Mod64 x y) => (MODD x y)
+(Mod64u ...) => (MODDU ...)
+// MODW/MODWU has a 64-bit dividend and a 32-bit divisor,
+// so a sign/zero extension of the dividend is required.
+(Mod32 x y) => (MODW (MOVWreg x) y)
+(Mod32u x y) => (MODWU (MOVWZreg x) y)
+(Mod16 x y) => (MODW (MOVHreg x) (MOVHreg y))
+(Mod16u x y) => (MODWU (MOVHZreg x) (MOVHZreg y))
+(Mod8 x y) => (MODW (MOVBreg x) (MOVBreg y))
+(Mod8u x y) => (MODWU (MOVBZreg x) (MOVBZreg y))
+
+// (x + y) / 2 with x>=y -> (x - y) / 2 + y
+(Avg64u <t> x y) => (ADD (SRDconst <t> (SUB <t> x y) [1]) y)
+
+(And64 ...) => (AND ...)
+(And(32|16|8) ...) => (ANDW ...)
+
+(Or64 ...) => (OR ...)
+(Or(32|16|8) ...) => (ORW ...)
+
+(Xor64 ...) => (XOR ...)
+(Xor(32|16|8) ...) => (XORW ...)
+
+(Neg64 ...) => (NEG ...)
+(Neg(32|16|8) ...) => (NEGW ...)
+(Neg32F ...) => (FNEGS ...)
+(Neg64F ...) => (FNEG ...)
+
+(Com64 ...) => (NOT ...)
+(Com(32|16|8) ...) => (NOTW ...)
+(NOT x) => (XOR (MOVDconst [-1]) x)
+(NOTW x) => (XORWconst [-1] x)
+
+// Lowering boolean ops
+(AndB ...) => (ANDW ...)
+(OrB ...) => (ORW ...)
+(Not x) => (XORWconst [1] x)
+
+// Lowering pointer arithmetic
+(OffPtr [off] ptr:(SP)) => (MOVDaddr [int32(off)] ptr)
+(OffPtr [off] ptr) && is32Bit(off) => (ADDconst [int32(off)] ptr)
+(OffPtr [off] ptr) => (ADD (MOVDconst [off]) ptr)
+
+// TODO: optimize these cases?
+(Ctz64NonZero ...) => (Ctz64 ...)
+(Ctz32NonZero ...) => (Ctz32 ...)
+
+// Ctz(x) = 64 - findLeftmostOne((x-1)&^x)
+(Ctz64 <t> x) => (SUB (MOVDconst [64]) (FLOGR (AND <t> (SUBconst <t> [1] x) (NOT <t> x))))
+(Ctz32 <t> x) => (SUB (MOVDconst [64]) (FLOGR (MOVWZreg (ANDW <t> (SUBWconst <t> [1] x) (NOTW <t> x)))))
+
+(BitLen64 x) => (SUB (MOVDconst [64]) (FLOGR x))
+
+// POPCNT treats the input register as a vector of 8 bytes, producing
+// a population count for each individual byte. For inputs larger than
+// a single byte we therefore need to sum the individual bytes produced
+// by the POPCNT instruction. For example, the following instruction
+// sequence could be used to calculate the population count of a 4-byte
+// value:
+//
+// MOVD $0x12345678, R1 // R1=0x12345678 <-- input
+// POPCNT R1, R2 // R2=0x02030404
+// SRW $16, R2, R3 // R3=0x00000203
+// ADDW R2, R3, R4 // R4=0x02030607
+// SRW $8, R4, R5 // R5=0x00020306
+// ADDW R4, R5, R6 // R6=0x0205090d
+// MOVBZ R6, R7 // R7=0x0000000d <-- result is 13
+//
+(PopCount8 x) => (POPCNT (MOVBZreg x))
+(PopCount16 x) => (MOVBZreg (SumBytes2 (POPCNT <typ.UInt16> x)))
+(PopCount32 x) => (MOVBZreg (SumBytes4 (POPCNT <typ.UInt32> x)))
+(PopCount64 x) => (MOVBZreg (SumBytes8 (POPCNT <typ.UInt64> x)))
+
+// SumBytes{2,4,8} pseudo operations sum the values of the rightmost
+// 2, 4 or 8 bytes respectively. The result is a single byte however
+// other bytes might contain junk so a zero extension is required if
+// the desired output type is larger than 1 byte.
+(SumBytes2 x) => (ADDW (SRWconst <typ.UInt8> x [8]) x)
+(SumBytes4 x) => (SumBytes2 (ADDW <typ.UInt16> (SRWconst <typ.UInt16> x [16]) x))
+(SumBytes8 x) => (SumBytes4 (ADDW <typ.UInt32> (SRDconst <typ.UInt32> x [32]) x))
+
+(Bswap64 ...) => (MOVDBR ...)
+(Bswap32 ...) => (MOVWBR ...)
+
+// add with carry
+(Select0 (Add64carry x y c))
+ => (Select0 <typ.UInt64> (ADDE x y (Select1 <types.TypeFlags> (ADDCconst c [-1]))))
+(Select1 (Add64carry x y c))
+ => (Select0 <typ.UInt64> (ADDE (MOVDconst [0]) (MOVDconst [0]) (Select1 <types.TypeFlags> (ADDE x y (Select1 <types.TypeFlags> (ADDCconst c [-1]))))))
+
+// subtract with borrow
+(Select0 (Sub64borrow x y c))
+ => (Select0 <typ.UInt64> (SUBE x y (Select1 <types.TypeFlags> (SUBC (MOVDconst [0]) c))))
+(Select1 (Sub64borrow x y c))
+ => (NEG (Select0 <typ.UInt64> (SUBE (MOVDconst [0]) (MOVDconst [0]) (Select1 <types.TypeFlags> (SUBE x y (Select1 <types.TypeFlags> (SUBC (MOVDconst [0]) c)))))))
+
+// math package intrinsics
+(Sqrt ...) => (FSQRT ...)
+(Floor x) => (FIDBR [7] x)
+(Ceil x) => (FIDBR [6] x)
+(Trunc x) => (FIDBR [5] x)
+(RoundToEven x) => (FIDBR [4] x)
+(Round x) => (FIDBR [1] x)
+(FMA x y z) => (FMADD z x y)
+
+// Atomic loads and stores.
+// The SYNC instruction (fast-BCR-serialization) prevents store-load
+// reordering. Other sequences of memory operations (load-load,
+// store-store and load-store) are already guaranteed not to be reordered.
+(AtomicLoad(8|32|Acq32|64|Ptr) ptr mem) => (MOV(BZ|WZ|WZ|D|D)atomicload ptr mem)
+(AtomicStore(8|32|64|PtrNoWB) ptr val mem) => (SYNC (MOV(B|W|D|D)atomicstore ptr val mem))
+
+// Store-release doesn't require store-load ordering.
+(AtomicStoreRel32 ptr val mem) => (MOVWatomicstore ptr val mem)
+
+// Atomic adds.
+(AtomicAdd32 ptr val mem) => (AddTupleFirst32 val (LAA ptr val mem))
+(AtomicAdd64 ptr val mem) => (AddTupleFirst64 val (LAAG ptr val mem))
+(Select0 <t> (AddTupleFirst32 val tuple)) => (ADDW val (Select0 <t> tuple))
+(Select1 (AddTupleFirst32 _ tuple)) => (Select1 tuple)
+(Select0 <t> (AddTupleFirst64 val tuple)) => (ADD val (Select0 <t> tuple))
+(Select1 (AddTupleFirst64 _ tuple)) => (Select1 tuple)
+
+// Atomic exchanges.
+(AtomicExchange32 ptr val mem) => (LoweredAtomicExchange32 ptr val mem)
+(AtomicExchange64 ptr val mem) => (LoweredAtomicExchange64 ptr val mem)
+
+// Atomic compare and swap.
+(AtomicCompareAndSwap32 ptr old new_ mem) => (LoweredAtomicCas32 ptr old new_ mem)
+(AtomicCompareAndSwap64 ptr old new_ mem) => (LoweredAtomicCas64 ptr old new_ mem)
+
+// Atomic and: *(*uint8)(ptr) &= val
+//
+// Round pointer down to nearest word boundary and pad value with ones before
+// applying atomic AND operation to target word.
+//
+// *(*uint32)(ptr &^ 3) &= rotateleft(uint32(val) | 0xffffff00, ((3 << 3) ^ ((ptr & 3) << 3))
+//
+(AtomicAnd8 ptr val mem)
+ => (LANfloor
+ ptr
+ (RLL <typ.UInt32>
+ (ORWconst <typ.UInt32> val [-1<<8])
+ (RXSBG <typ.UInt32> {s390x.NewRotateParams(59, 60, 3)} (MOVDconst [3<<3]) ptr))
+ mem)
+
+// Atomic or: *(*uint8)(ptr) |= val
+//
+// Round pointer down to nearest word boundary and pad value with zeros before
+// applying atomic OR operation to target word.
+//
+// *(*uint32)(ptr &^ 3) |= uint32(val) << ((3 << 3) ^ ((ptr & 3) << 3))
+//
+(AtomicOr8 ptr val mem)
+ => (LAOfloor
+ ptr
+ (SLW <typ.UInt32>
+ (MOVBZreg <typ.UInt32> val)
+ (RXSBG <typ.UInt32> {s390x.NewRotateParams(59, 60, 3)} (MOVDconst [3<<3]) ptr))
+ mem)
+
+(AtomicAnd32 ...) => (LAN ...)
+(AtomicOr32 ...) => (LAO ...)
+
+// Lowering extension
+// Note: we always extend to 64 bits even though some ops don't need that many result bits.
+(SignExt8to(16|32|64) ...) => (MOVBreg ...)
+(SignExt16to(32|64) ...) => (MOVHreg ...)
+(SignExt32to64 ...) => (MOVWreg ...)
+
+(ZeroExt8to(16|32|64) ...) => (MOVBZreg ...)
+(ZeroExt16to(32|64) ...) => (MOVHZreg ...)
+(ZeroExt32to64 ...) => (MOVWZreg ...)
+
+(Slicemask <t> x) => (SRADconst (NEG <t> x) [63])
+
+// Lowering truncation
+// Because we ignore high parts of registers, truncates are just copies.
+(Trunc(16|32|64)to8 ...) => (Copy ...)
+(Trunc(32|64)to16 ...) => (Copy ...)
+(Trunc64to32 ...) => (Copy ...)
+
+// Lowering float <-> int
+(Cvt32to32F ...) => (CEFBRA ...)
+(Cvt32to64F ...) => (CDFBRA ...)
+(Cvt64to32F ...) => (CEGBRA ...)
+(Cvt64to64F ...) => (CDGBRA ...)
+
+(Cvt32Fto32 ...) => (CFEBRA ...)
+(Cvt32Fto64 ...) => (CGEBRA ...)
+(Cvt64Fto32 ...) => (CFDBRA ...)
+(Cvt64Fto64 ...) => (CGDBRA ...)
+
+// Lowering float <-> uint
+(Cvt32Uto32F ...) => (CELFBR ...)
+(Cvt32Uto64F ...) => (CDLFBR ...)
+(Cvt64Uto32F ...) => (CELGBR ...)
+(Cvt64Uto64F ...) => (CDLGBR ...)
+
+(Cvt32Fto32U ...) => (CLFEBR ...)
+(Cvt32Fto64U ...) => (CLGEBR ...)
+(Cvt64Fto32U ...) => (CLFDBR ...)
+(Cvt64Fto64U ...) => (CLGDBR ...)
+
+// Lowering float32 <-> float64
+(Cvt32Fto64F ...) => (LDEBR ...)
+(Cvt64Fto32F ...) => (LEDBR ...)
+
+(CvtBoolToUint8 ...) => (Copy ...)
+
+(Round(32|64)F ...) => (LoweredRound(32|64)F ...)
+
+// Lowering shifts
+
+// Lower bounded shifts first. No need to check shift value.
+(Lsh64x(64|32|16|8) x y) && shiftIsBounded(v) => (SLD x y)
+(Lsh32x(64|32|16|8) x y) && shiftIsBounded(v) => (SLW x y)
+(Lsh16x(64|32|16|8) x y) && shiftIsBounded(v) => (SLW x y)
+(Lsh8x(64|32|16|8) x y) && shiftIsBounded(v) => (SLW x y)
+(Rsh64Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SRD x y)
+(Rsh32Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SRW x y)
+(Rsh16Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SRW (MOVHZreg x) y)
+(Rsh8Ux(64|32|16|8) x y) && shiftIsBounded(v) => (SRW (MOVBZreg x) y)
+(Rsh64x(64|32|16|8) x y) && shiftIsBounded(v) => (SRAD x y)
+(Rsh32x(64|32|16|8) x y) && shiftIsBounded(v) => (SRAW x y)
+(Rsh16x(64|32|16|8) x y) && shiftIsBounded(v) => (SRAW (MOVHreg x) y)
+(Rsh8x(64|32|16|8) x y) && shiftIsBounded(v) => (SRAW (MOVBreg x) y)
+
+// Unsigned shifts need to return 0 if shift amount is >= width of shifted value.
+// result = shift >= 64 ? 0 : arg << shift
+(Lsh(64|32|16|8)x64 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
+(Lsh(64|32|16|8)x32 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
+(Lsh(64|32|16|8)x16 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+(Lsh(64|32|16|8)x8 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+
+(Rsh(64|32)Ux64 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
+(Rsh(64|32)Ux32 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
+(Rsh(64|32)Ux16 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+(Rsh(64|32)Ux8 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+
+(Rsh(16|8)Ux64 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPUconst y [64]))
+(Rsh(16|8)Ux32 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPWUconst y [64]))
+(Rsh(16|8)Ux16 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+(Rsh(16|8)Ux8 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+
+// 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 63 (all ones) if the shift value is more than 63.
+// result = arg >> (shift >= 64 ? 63 : shift)
+(Rsh(64|32)x64 x y) => (SRA(D|W) x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPUconst y [64])))
+(Rsh(64|32)x32 x y) => (SRA(D|W) x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst y [64])))
+(Rsh(64|32)x16 x y) => (SRA(D|W) x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVHZreg y) [64])))
+(Rsh(64|32)x8 x y) => (SRA(D|W) x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVBZreg y) [64])))
+
+(Rsh(16|8)x64 x y) => (SRAW (MOV(H|B)reg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPUconst y [64])))
+(Rsh(16|8)x32 x y) => (SRAW (MOV(H|B)reg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst y [64])))
+(Rsh(16|8)x16 x y) => (SRAW (MOV(H|B)reg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVHZreg y) [64])))
+(Rsh(16|8)x8 x y) => (SRAW (MOV(H|B)reg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVBZreg y) [64])))
+
+// Lowering rotates
+(RotateLeft8 <t> x (MOVDconst [c])) => (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
+(RotateLeft16 <t> x (MOVDconst [c])) => (Or16 (Lsh16x64 <t> x (MOVDconst [c&15])) (Rsh16Ux64 <t> x (MOVDconst [-c&15])))
+(RotateLeft32 ...) => (RLL ...)
+(RotateLeft64 ...) => (RLLG ...)
+
+// Lowering comparisons
+(Less64 x y) => (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
+(Less32 x y) => (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
+(Less(16|8) x y) => (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B)reg x) (MOV(H|B)reg y)))
+(Less64U x y) => (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
+(Less32U x y) => (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
+(Less(16|8)U x y) => (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOV(H|B)Zreg x) (MOV(H|B)Zreg y)))
+(Less64F x y) => (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
+(Less32F x y) => (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
+
+(Leq64 x y) => (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
+(Leq32 x y) => (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
+(Leq(16|8) x y) => (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B)reg x) (MOV(H|B)reg y)))
+(Leq64U x y) => (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
+(Leq32U x y) => (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
+(Leq(16|8)U x y) => (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOV(H|B)Zreg x) (MOV(H|B)Zreg y)))
+(Leq64F x y) => (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
+(Leq32F x y) => (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
+
+(Eq(64|Ptr) x y) => (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
+(Eq32 x y) => (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
+(Eq(16|8|B) x y) => (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B|B)reg x) (MOV(H|B|B)reg y)))
+(Eq64F x y) => (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
+(Eq32F x y) => (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
+
+(Neq(64|Ptr) x y) => (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
+(Neq32 x y) => (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
+(Neq(16|8|B) x y) => (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B|B)reg x) (MOV(H|B|B)reg y)))
+(Neq64F x y) => (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
+(Neq32F x y) => (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
+
+// Lowering loads
+(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) => (MOVDload ptr mem)
+(Load <t> ptr mem) && is32BitInt(t) && isSigned(t) => (MOVWload ptr mem)
+(Load <t> ptr mem) && is32BitInt(t) && !isSigned(t) => (MOVWZload ptr mem)
+(Load <t> ptr mem) && is16BitInt(t) && isSigned(t) => (MOVHload ptr mem)
+(Load <t> ptr mem) && is16BitInt(t) && !isSigned(t) => (MOVHZload ptr mem)
+(Load <t> ptr mem) && is8BitInt(t) && isSigned(t) => (MOVBload ptr mem)
+(Load <t> ptr mem) && (t.IsBoolean() || (is8BitInt(t) && !isSigned(t))) => (MOVBZload ptr mem)
+(Load <t> ptr mem) && is32BitFloat(t) => (FMOVSload ptr mem)
+(Load <t> ptr mem) && is64BitFloat(t) => (FMOVDload ptr mem)
+
+// Lowering stores
+// These more-specific FP versions of Store pattern should come first.
+(Store {t} ptr val mem) && t.Size() == 8 && is64BitFloat(val.Type) => (FMOVDstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 && is32BitFloat(val.Type) => (FMOVSstore ptr val mem)
+
+(Store {t} ptr val mem) && t.Size() == 8 => (MOVDstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 => (MOVWstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 2 => (MOVHstore ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 1 => (MOVBstore ptr val mem)
+
+// Lowering moves
+
+// Load and store for small copies.
+(Move [0] _ _ mem) => mem
+(Move [1] dst src mem) => (MOVBstore dst (MOVBZload src mem) mem)
+(Move [2] dst src mem) => (MOVHstore dst (MOVHZload src mem) mem)
+(Move [4] dst src mem) => (MOVWstore dst (MOVWZload src mem) mem)
+(Move [8] dst src mem) => (MOVDstore dst (MOVDload src mem) mem)
+(Move [16] dst src mem) =>
+ (MOVDstore [8] dst (MOVDload [8] src mem)
+ (MOVDstore dst (MOVDload src mem) mem))
+(Move [24] dst src mem) =>
+ (MOVDstore [16] dst (MOVDload [16] src mem)
+ (MOVDstore [8] dst (MOVDload [8] src mem)
+ (MOVDstore dst (MOVDload src mem) mem)))
+(Move [3] dst src mem) =>
+ (MOVBstore [2] dst (MOVBZload [2] src mem)
+ (MOVHstore dst (MOVHZload src mem) mem))
+(Move [5] dst src mem) =>
+ (MOVBstore [4] dst (MOVBZload [4] src mem)
+ (MOVWstore dst (MOVWZload src mem) mem))
+(Move [6] dst src mem) =>
+ (MOVHstore [4] dst (MOVHZload [4] src mem)
+ (MOVWstore dst (MOVWZload src mem) mem))
+(Move [7] dst src mem) =>
+ (MOVBstore [6] dst (MOVBZload [6] src mem)
+ (MOVHstore [4] dst (MOVHZload [4] src mem)
+ (MOVWstore dst (MOVWZload src mem) mem)))
+
+// MVC for other moves. Use up to 4 instructions (sizes up to 1024 bytes).
+(Move [s] dst src mem) && s > 0 && s <= 256 && logLargeCopy(v, s) =>
+ (MVC [makeValAndOff32(int32(s), 0)] dst src mem)
+(Move [s] dst src mem) && s > 256 && s <= 512 && logLargeCopy(v, s) =>
+ (MVC [makeValAndOff32(int32(s)-256, 256)] dst src (MVC [makeValAndOff32(256, 0)] dst src mem))
+(Move [s] dst src mem) && s > 512 && s <= 768 && logLargeCopy(v, s) =>
+ (MVC [makeValAndOff32(int32(s)-512, 512)] dst src (MVC [makeValAndOff32(256, 256)] dst src (MVC [makeValAndOff32(256, 0)] dst src mem)))
+(Move [s] dst src mem) && s > 768 && s <= 1024 && logLargeCopy(v, s) =>
+ (MVC [makeValAndOff32(int32(s)-768, 768)] dst src (MVC [makeValAndOff32(256, 512)] dst src (MVC [makeValAndOff32(256, 256)] dst src (MVC [makeValAndOff32(256, 0)] dst src mem))))
+
+// Move more than 1024 bytes using a loop.
+(Move [s] dst src mem) && s > 1024 && logLargeCopy(v, s) =>
+ (LoweredMove [s%256] dst src (ADD <src.Type> src (MOVDconst [(s/256)*256])) mem)
+
+// Lowering Zero instructions
+(Zero [0] _ mem) => mem
+(Zero [1] destptr mem) => (MOVBstoreconst [0] destptr mem)
+(Zero [2] destptr mem) => (MOVHstoreconst [0] destptr mem)
+(Zero [4] destptr mem) => (MOVWstoreconst [0] destptr mem)
+(Zero [8] destptr mem) => (MOVDstoreconst [0] destptr mem)
+(Zero [3] destptr mem) =>
+ (MOVBstoreconst [makeValAndOff32(0,2)] destptr
+ (MOVHstoreconst [0] destptr mem))
+(Zero [5] destptr mem) =>
+ (MOVBstoreconst [makeValAndOff32(0,4)] destptr
+ (MOVWstoreconst [0] destptr mem))
+(Zero [6] destptr mem) =>
+ (MOVHstoreconst [makeValAndOff32(0,4)] destptr
+ (MOVWstoreconst [0] destptr mem))
+(Zero [7] destptr mem) =>
+ (MOVWstoreconst [makeValAndOff32(0,3)] destptr
+ (MOVWstoreconst [0] destptr mem))
+
+(Zero [s] destptr mem) && s > 0 && s <= 1024 =>
+ (CLEAR [makeValAndOff32(int32(s), 0)] destptr mem)
+
+// Zero more than 1024 bytes using a loop.
+(Zero [s] destptr mem) && s > 1024 =>
+ (LoweredZero [s%256] destptr (ADDconst <destptr.Type> destptr [(int32(s)/256)*256]) mem)
+
+// Lowering constants
+(Const(64|32|16|8) [val]) => (MOVDconst [int64(val)])
+(Const(32|64)F ...) => (FMOV(S|D)const ...)
+(ConstNil) => (MOVDconst [0])
+(ConstBool [b]) => (MOVDconst [b2i(b)])
+
+// Lowering calls
+(StaticCall ...) => (CALLstatic ...)
+(ClosureCall ...) => (CALLclosure ...)
+(InterCall ...) => (CALLinter ...)
+
+// Miscellaneous
+(IsNonNil p) => (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPconst p [0]))
+(IsInBounds idx len) => (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPU idx len))
+(IsSliceInBounds idx len) => (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPU idx len))
+(NilCheck ...) => (LoweredNilCheck ...)
+(GetG ...) => (LoweredGetG ...)
+(GetClosurePtr ...) => (LoweredGetClosurePtr ...)
+(GetCallerSP ...) => (LoweredGetCallerSP ...)
+(GetCallerPC ...) => (LoweredGetCallerPC ...)
+(Addr {sym} base) => (MOVDaddr {sym} base)
+(LocalAddr {sym} base _) => (MOVDaddr {sym} base)
+(ITab (Load ptr mem)) => (MOVDload ptr mem)
+
+// block rewrites
+(If cond yes no) => (CLIJ {s390x.LessOrGreater} (MOVBZreg <typ.Bool> cond) [0] yes no)
+
+// Write barrier.
+(WB ...) => (LoweredWB ...)
+
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
+(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
+
+// ***************************
+// Above: lowering rules
+// Below: optimizations
+// ***************************
+// TODO: Should the optimizations be a separate pass?
+
+// Note: when removing unnecessary sign/zero extensions.
+//
+// After a value is spilled it is restored using a sign- or zero-extension
+// to register-width as appropriate for its type. For example, a uint8 will
+// be restored using a MOVBZ (llgc) instruction which will zero extend the
+// 8-bit value to 64-bits.
+//
+// This is a hazard when folding sign- and zero-extensions since we need to
+// ensure not only that the value in the argument register is correctly
+// extended but also that it will still be correctly extended if it is
+// spilled and restored.
+//
+// In general this means we need type checks when the RHS of a rule is an
+// OpCopy (i.e. "(... x:(...) ...) -> x").
+
+// Merge double extensions.
+(MOV(H|HZ)reg e:(MOV(B|BZ)reg x)) && clobberIfDead(e) => (MOV(B|BZ)reg x)
+(MOV(W|WZ)reg e:(MOV(B|BZ)reg x)) && clobberIfDead(e) => (MOV(B|BZ)reg x)
+(MOV(W|WZ)reg e:(MOV(H|HZ)reg x)) && clobberIfDead(e) => (MOV(H|HZ)reg x)
+
+// Bypass redundant sign extensions.
+(MOV(B|BZ)reg e:(MOVBreg x)) && clobberIfDead(e) => (MOV(B|BZ)reg x)
+(MOV(B|BZ)reg e:(MOVHreg x)) && clobberIfDead(e) => (MOV(B|BZ)reg x)
+(MOV(B|BZ)reg e:(MOVWreg x)) && clobberIfDead(e) => (MOV(B|BZ)reg x)
+(MOV(H|HZ)reg e:(MOVHreg x)) && clobberIfDead(e) => (MOV(H|HZ)reg x)
+(MOV(H|HZ)reg e:(MOVWreg x)) && clobberIfDead(e) => (MOV(H|HZ)reg x)
+(MOV(W|WZ)reg e:(MOVWreg x)) && clobberIfDead(e) => (MOV(W|WZ)reg x)
+
+// Bypass redundant zero extensions.
+(MOV(B|BZ)reg e:(MOVBZreg x)) && clobberIfDead(e) => (MOV(B|BZ)reg x)
+(MOV(B|BZ)reg e:(MOVHZreg x)) && clobberIfDead(e) => (MOV(B|BZ)reg x)
+(MOV(B|BZ)reg e:(MOVWZreg x)) && clobberIfDead(e) => (MOV(B|BZ)reg x)
+(MOV(H|HZ)reg e:(MOVHZreg x)) && clobberIfDead(e) => (MOV(H|HZ)reg x)
+(MOV(H|HZ)reg e:(MOVWZreg x)) && clobberIfDead(e) => (MOV(H|HZ)reg x)
+(MOV(W|WZ)reg e:(MOVWZreg x)) && clobberIfDead(e) => (MOV(W|WZ)reg x)
+
+// Remove zero extensions after zero extending load.
+// Note: take care that if x is spilled it is restored correctly.
+(MOV(B|H|W)Zreg x:(MOVBZload _ _)) && (!x.Type.IsSigned() || x.Type.Size() > 1) => x
+(MOV(H|W)Zreg x:(MOVHZload _ _)) && (!x.Type.IsSigned() || x.Type.Size() > 2) => x
+(MOVWZreg x:(MOVWZload _ _)) && (!x.Type.IsSigned() || x.Type.Size() > 4) => x
+
+// Remove sign extensions after sign extending load.
+// Note: take care that if x is spilled it is restored correctly.
+(MOV(B|H|W)reg x:(MOVBload _ _)) && (x.Type.IsSigned() || x.Type.Size() == 8) => x
+(MOV(H|W)reg x:(MOVHload _ _)) && (x.Type.IsSigned() || x.Type.Size() == 8) => x
+(MOVWreg x:(MOVWload _ _)) && (x.Type.IsSigned() || x.Type.Size() == 8) => x
+
+// Remove sign extensions after zero extending load.
+// These type checks are probably unnecessary but do them anyway just in case.
+(MOV(H|W)reg x:(MOVBZload _ _)) && (!x.Type.IsSigned() || x.Type.Size() > 1) => x
+(MOVWreg x:(MOVHZload _ _)) && (!x.Type.IsSigned() || x.Type.Size() > 2) => x
+
+// Fold sign and zero extensions into 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.
+//
+// Make sure we don't combine these ops if the load has another use.
+// This prevents a single load from being split into multiple loads
+// which then might return different values. See test/atomicload.go.
+(MOV(B|H|W)Zreg <t> x:(MOV(B|H|W)load [o] {s} p mem))
+ && x.Uses == 1
+ && clobber(x)
+ => @x.Block (MOV(B|H|W)Zload <t> [o] {s} p mem)
+(MOV(B|H|W)reg <t> x:(MOV(B|H|W)Zload [o] {s} p mem))
+ && x.Uses == 1
+ && clobber(x)
+ => @x.Block (MOV(B|H|W)load <t> [o] {s} p mem)
+
+// Remove zero extensions after argument load.
+(MOVBZreg x:(Arg <t>)) && !t.IsSigned() && t.Size() == 1 => x
+(MOVHZreg x:(Arg <t>)) && !t.IsSigned() && t.Size() <= 2 => x
+(MOVWZreg x:(Arg <t>)) && !t.IsSigned() && t.Size() <= 4 => x
+
+// Remove sign extensions after argument load.
+(MOVBreg x:(Arg <t>)) && t.IsSigned() && t.Size() == 1 => x
+(MOVHreg x:(Arg <t>)) && t.IsSigned() && t.Size() <= 2 => x
+(MOVWreg x:(Arg <t>)) && t.IsSigned() && t.Size() <= 4 => x
+
+// Fold zero extensions into constants.
+(MOVBZreg (MOVDconst [c])) => (MOVDconst [int64( uint8(c))])
+(MOVHZreg (MOVDconst [c])) => (MOVDconst [int64(uint16(c))])
+(MOVWZreg (MOVDconst [c])) => (MOVDconst [int64(uint32(c))])
+
+// Fold sign extensions into constants.
+(MOVBreg (MOVDconst [c])) => (MOVDconst [int64( int8(c))])
+(MOVHreg (MOVDconst [c])) => (MOVDconst [int64(int16(c))])
+(MOVWreg (MOVDconst [c])) => (MOVDconst [int64(int32(c))])
+
+// Remove zero extension of conditional move.
+// Note: only for MOVBZreg for now since it is added as part of 'if' statement lowering.
+(MOVBZreg x:(LOCGR (MOVDconst [c]) (MOVDconst [d]) _))
+ && int64(uint8(c)) == c
+ && int64(uint8(d)) == d
+ && (!x.Type.IsSigned() || x.Type.Size() > 1)
+ => x
+
+// Fold boolean tests into blocks.
+// Note: this must match If statement lowering.
+(CLIJ {s390x.LessOrGreater} (LOCGR {d} (MOVDconst [0]) (MOVDconst [x]) cmp) [0] yes no)
+ && int32(x) != 0
+ => (BRC {d} cmp yes no)
+
+// Canonicalize BRC condition code mask by removing impossible conditions.
+// Integer comparisons cannot generate the unordered condition.
+(BRC {c} x:((CMP|CMPW|CMPU|CMPWU) _ _) yes no) && c&s390x.Unordered != 0 => (BRC {c&^s390x.Unordered} x yes no)
+(BRC {c} x:((CMP|CMPW|CMPU|CMPWU)const _) yes no) && c&s390x.Unordered != 0 => (BRC {c&^s390x.Unordered} x yes no)
+
+// Compare-and-branch.
+// Note: bit 3 (unordered) must not be set so we mask out s390x.Unordered.
+(BRC {c} (CMP x y) yes no) => (CGRJ {c&^s390x.Unordered} x y yes no)
+(BRC {c} (CMPW x y) yes no) => (CRJ {c&^s390x.Unordered} x y yes no)
+(BRC {c} (CMPU x y) yes no) => (CLGRJ {c&^s390x.Unordered} x y yes no)
+(BRC {c} (CMPWU x y) yes no) => (CLRJ {c&^s390x.Unordered} x y yes no)
+
+// Compare-and-branch (immediate).
+// Note: bit 3 (unordered) must not be set so we mask out s390x.Unordered.
+(BRC {c} (CMPconst x [y]) yes no) && y == int32( int8(y)) => (CGIJ {c&^s390x.Unordered} x [ int8(y)] yes no)
+(BRC {c} (CMPWconst x [y]) yes no) && y == int32( int8(y)) => (CIJ {c&^s390x.Unordered} x [ int8(y)] yes no)
+(BRC {c} (CMPUconst x [y]) yes no) && y == int32(uint8(y)) => (CLGIJ {c&^s390x.Unordered} x [uint8(y)] yes no)
+(BRC {c} (CMPWUconst x [y]) yes no) && y == int32(uint8(y)) => (CLIJ {c&^s390x.Unordered} x [uint8(y)] yes no)
+
+// Absorb immediate into compare-and-branch.
+(C(R|GR)J {c} x (MOVDconst [y]) yes no) && is8Bit(y) => (C(I|GI)J {c} x [ int8(y)] yes no)
+(CL(R|GR)J {c} x (MOVDconst [y]) yes no) && isU8Bit(y) => (CL(I|GI)J {c} x [uint8(y)] yes no)
+(C(R|GR)J {c} (MOVDconst [x]) y yes no) && is8Bit(x) => (C(I|GI)J {c.ReverseComparison()} y [ int8(x)] yes no)
+(CL(R|GR)J {c} (MOVDconst [x]) y yes no) && isU8Bit(x) => (CL(I|GI)J {c.ReverseComparison()} y [uint8(x)] yes no)
+
+// Prefer comparison with immediate to compare-and-branch.
+(CGRJ {c} x (MOVDconst [y]) yes no) && !is8Bit(y) && is32Bit(y) => (BRC {c} (CMPconst x [int32(y)]) yes no)
+(CRJ {c} x (MOVDconst [y]) yes no) && !is8Bit(y) && is32Bit(y) => (BRC {c} (CMPWconst x [int32(y)]) yes no)
+(CLGRJ {c} x (MOVDconst [y]) yes no) && !isU8Bit(y) && isU32Bit(y) => (BRC {c} (CMPUconst x [int32(y)]) yes no)
+(CLRJ {c} x (MOVDconst [y]) yes no) && !isU8Bit(y) && isU32Bit(y) => (BRC {c} (CMPWUconst x [int32(y)]) yes no)
+(CGRJ {c} (MOVDconst [x]) y yes no) && !is8Bit(x) && is32Bit(x) => (BRC {c.ReverseComparison()} (CMPconst y [int32(x)]) yes no)
+(CRJ {c} (MOVDconst [x]) y yes no) && !is8Bit(x) && is32Bit(x) => (BRC {c.ReverseComparison()} (CMPWconst y [int32(x)]) yes no)
+(CLGRJ {c} (MOVDconst [x]) y yes no) && !isU8Bit(x) && isU32Bit(x) => (BRC {c.ReverseComparison()} (CMPUconst y [int32(x)]) yes no)
+(CLRJ {c} (MOVDconst [x]) y yes no) && !isU8Bit(x) && isU32Bit(x) => (BRC {c.ReverseComparison()} (CMPWUconst y [int32(x)]) yes no)
+
+// Absorb sign/zero extensions into 32-bit compare-and-branch.
+(CIJ {c} (MOV(W|WZ)reg x) [y] yes no) => (CIJ {c} x [y] yes no)
+(CLIJ {c} (MOV(W|WZ)reg x) [y] yes no) => (CLIJ {c} x [y] yes no)
+
+// Bring out-of-range signed immediates into range by varying branch condition.
+(BRC {s390x.Less} (CMPconst x [ 128]) yes no) => (CGIJ {s390x.LessOrEqual} x [ 127] yes no)
+(BRC {s390x.Less} (CMPWconst x [ 128]) yes no) => (CIJ {s390x.LessOrEqual} x [ 127] yes no)
+(BRC {s390x.LessOrEqual} (CMPconst x [-129]) yes no) => (CGIJ {s390x.Less} x [-128] yes no)
+(BRC {s390x.LessOrEqual} (CMPWconst x [-129]) yes no) => (CIJ {s390x.Less} x [-128] yes no)
+(BRC {s390x.Greater} (CMPconst x [-129]) yes no) => (CGIJ {s390x.GreaterOrEqual} x [-128] yes no)
+(BRC {s390x.Greater} (CMPWconst x [-129]) yes no) => (CIJ {s390x.GreaterOrEqual} x [-128] yes no)
+(BRC {s390x.GreaterOrEqual} (CMPconst x [ 128]) yes no) => (CGIJ {s390x.Greater} x [ 127] yes no)
+(BRC {s390x.GreaterOrEqual} (CMPWconst x [ 128]) yes no) => (CIJ {s390x.Greater} x [ 127] yes no)
+
+// Bring out-of-range unsigned immediates into range by varying branch condition.
+(BRC {s390x.Less} (CMP(WU|U)const x [256]) yes no) => (C(L|LG)IJ {s390x.LessOrEqual} x [255] yes no)
+(BRC {s390x.GreaterOrEqual} (CMP(WU|U)const x [256]) yes no) => (C(L|LG)IJ {s390x.Greater} x [255] yes no)
+
+// Bring out-of-range immediates into range by switching signedness (only == and !=).
+(BRC {c} (CMPconst x [y]) yes no) && y == int32(uint8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater) => (CLGIJ {c} x [uint8(y)] yes no)
+(BRC {c} (CMPWconst x [y]) yes no) && y == int32(uint8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater) => (CLIJ {c} x [uint8(y)] yes no)
+(BRC {c} (CMPUconst x [y]) yes no) && y == int32( int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater) => (CGIJ {c} x [ int8(y)] yes no)
+(BRC {c} (CMPWUconst x [y]) yes no) && y == int32( int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater) => (CIJ {c} x [ int8(y)] yes no)
+
+// Fold constants into instructions.
+(ADD x (MOVDconst [c])) && is32Bit(c) => (ADDconst [int32(c)] x)
+(ADDW x (MOVDconst [c])) => (ADDWconst [int32(c)] x)
+
+(SUB x (MOVDconst [c])) && is32Bit(c) => (SUBconst x [int32(c)])
+(SUB (MOVDconst [c]) x) && is32Bit(c) => (NEG (SUBconst <v.Type> x [int32(c)]))
+(SUBW x (MOVDconst [c])) => (SUBWconst x [int32(c)])
+(SUBW (MOVDconst [c]) x) => (NEGW (SUBWconst <v.Type> x [int32(c)]))
+
+(MULLD x (MOVDconst [c])) && is32Bit(c) => (MULLDconst [int32(c)] x)
+(MULLW x (MOVDconst [c])) => (MULLWconst [int32(c)] x)
+
+// NILF instructions leave the high 32 bits unchanged which is
+// equivalent to the leftmost 32 bits being set.
+// TODO(mundaym): modify the assembler to accept 64-bit values
+// and use isU32Bit(^c).
+(AND x (MOVDconst [c]))
+ && s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c)) != nil
+ => (RISBGZ x {*s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c))})
+(AND x (MOVDconst [c]))
+ && is32Bit(c)
+ && c < 0
+ => (ANDconst [c] x)
+(AND x (MOVDconst [c]))
+ && is32Bit(c)
+ && c >= 0
+ => (MOVWZreg (ANDWconst <typ.UInt32> [int32(c)] x))
+
+(ANDW x (MOVDconst [c])) => (ANDWconst [int32(c)] x)
+
+((AND|ANDW)const [c] ((AND|ANDW)const [d] x)) => ((AND|ANDW)const [c&d] x)
+
+((OR|XOR) x (MOVDconst [c])) && isU32Bit(c) => ((OR|XOR)const [c] x)
+((OR|XOR)W x (MOVDconst [c])) => ((OR|XOR)Wconst [int32(c)] x)
+
+// Constant shifts.
+(S(LD|RD|RAD) x (MOVDconst [c])) => (S(LD|RD|RAD)const x [uint8(c&63)])
+(S(LW|RW|RAW) x (MOVDconst [c])) && c&32 == 0 => (S(LW|RW|RAW)const x [uint8(c&31)])
+(S(LW|RW) _ (MOVDconst [c])) && c&32 != 0 => (MOVDconst [0])
+(SRAW x (MOVDconst [c])) && c&32 != 0 => (SRAWconst x [31])
+
+// Shifts only use the rightmost 6 bits of the shift value.
+(S(LD|RD|RAD|LW|RW|RAW) x (RISBGZ y {r}))
+ && r.Amount == 0
+ && r.OutMask()&63 == 63
+ => (S(LD|RD|RAD|LW|RW|RAW) x y)
+(S(LD|RD|RAD|LW|RW|RAW) x (AND (MOVDconst [c]) y))
+ => (S(LD|RD|RAD|LW|RW|RAW) x (ANDWconst <typ.UInt32> [int32(c&63)] y))
+(S(LD|RD|RAD|LW|RW|RAW) x (ANDWconst [c] y)) && c&63 == 63
+ => (S(LD|RD|RAD|LW|RW|RAW) x y)
+(SLD x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SLD x y)
+(SRD x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SRD x y)
+(SRAD x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SRAD x y)
+(SLW x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SLW x y)
+(SRW x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SRW x y)
+(SRAW x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SRAW x y)
+
+// Match rotate by constant.
+(RLLG x (MOVDconst [c])) => (RISBGZ x {s390x.NewRotateParams(0, 63, uint8(c&63))})
+(RLL x (MOVDconst [c])) => (RLLconst x [uint8(c&31)])
+
+// Match rotate by constant pattern.
+((ADD|OR|XOR) (SLDconst x [c]) (SRDconst x [64-c])) => (RISBGZ x {s390x.NewRotateParams(0, 63, c)})
+((ADD|OR|XOR)W (SLWconst x [c]) (SRWconst x [32-c])) => (RLLconst x [c])
+
+// Signed 64-bit comparison with immediate.
+(CMP x (MOVDconst [c])) && is32Bit(c) => (CMPconst x [int32(c)])
+(CMP (MOVDconst [c]) x) && is32Bit(c) => (InvertFlags (CMPconst x [int32(c)]))
+
+// Unsigned 64-bit comparison with immediate.
+(CMPU x (MOVDconst [c])) && isU32Bit(c) => (CMPUconst x [int32(c)])
+(CMPU (MOVDconst [c]) x) && isU32Bit(c) => (InvertFlags (CMPUconst x [int32(c)]))
+
+// Signed and unsigned 32-bit comparison with immediate.
+(CMP(W|WU) x (MOVDconst [c])) => (CMP(W|WU)const x [int32(c)])
+(CMP(W|WU) (MOVDconst [c]) x) => (InvertFlags (CMP(W|WU)const x [int32(c)]))
+
+// Match (x >> c) << d to 'rotate then insert selected bits [into zero]'.
+(SLDconst (SRDconst x [c]) [d]) => (RISBGZ x {s390x.NewRotateParams(uint8(max8(0, int8(c-d))), 63-d, uint8(int8(d-c)&63))})
+
+// Match (x << c) >> d to 'rotate then insert selected bits [into zero]'.
+(SRDconst (SLDconst x [c]) [d]) => (RISBGZ x {s390x.NewRotateParams(d, uint8(min8(63, int8(63-c+d))), uint8(int8(c-d)&63))})
+
+// Absorb input zero extension into 'rotate then insert selected bits [into zero]'.
+(RISBGZ (MOVWZreg x) {r}) && r.InMerge(0xffffffff) != nil => (RISBGZ x {*r.InMerge(0xffffffff)})
+(RISBGZ (MOVHZreg x) {r}) && r.InMerge(0x0000ffff) != nil => (RISBGZ x {*r.InMerge(0x0000ffff)})
+(RISBGZ (MOVBZreg x) {r}) && r.InMerge(0x000000ff) != nil => (RISBGZ x {*r.InMerge(0x000000ff)})
+
+// Absorb 'rotate then insert selected bits [into zero]' into zero extension.
+(MOVWZreg (RISBGZ x {r})) && r.OutMerge(0xffffffff) != nil => (RISBGZ x {*r.OutMerge(0xffffffff)})
+(MOVHZreg (RISBGZ x {r})) && r.OutMerge(0x0000ffff) != nil => (RISBGZ x {*r.OutMerge(0x0000ffff)})
+(MOVBZreg (RISBGZ x {r})) && r.OutMerge(0x000000ff) != nil => (RISBGZ x {*r.OutMerge(0x000000ff)})
+
+// Absorb shift into 'rotate then insert selected bits [into zero]'.
+//
+// Any unsigned shift can be represented as a rotate and mask operation:
+//
+// x << c => RotateLeft64(x, c) & (^uint64(0) << c)
+// x >> c => RotateLeft64(x, -c) & (^uint64(0) >> c)
+//
+// Therefore when a shift is used as the input to a rotate then insert
+// selected bits instruction we can merge the two together. We just have
+// to be careful that the resultant mask is representable (non-zero and
+// contiguous). For example, assuming that x is variable and c, y and m
+// are constants, a shift followed by a rotate then insert selected bits
+// could be represented as:
+//
+// RotateLeft64(RotateLeft64(x, c) & (^uint64(0) << c), y) & m
+//
+// We can split the rotation by y into two, one rotate for x and one for
+// the mask:
+//
+// RotateLeft64(RotateLeft64(x, c), y) & (RotateLeft64(^uint64(0) << c, y)) & m
+//
+// The rotations of x by c followed by y can then be combined:
+//
+// RotateLeft64(x, c+y) & (RotateLeft64(^uint64(0) << c, y)) & m
+// ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// rotate mask
+//
+// To perform this optimization we therefore just need to check that it
+// is valid to merge the shift mask (^(uint64(0)<<c)) into the selected
+// bits mask (i.e. that the resultant mask is non-zero and contiguous).
+//
+(RISBGZ (SLDconst x [c]) {r}) && r.InMerge(^uint64(0)<<c) != nil => (RISBGZ x {(*r.InMerge(^uint64(0)<<c)).RotateLeft(c)})
+(RISBGZ (SRDconst x [c]) {r}) && r.InMerge(^uint64(0)>>c) != nil => (RISBGZ x {(*r.InMerge(^uint64(0)>>c)).RotateLeft(-c)})
+
+// Absorb 'rotate then insert selected bits [into zero]' into left shift.
+(SLDconst (RISBGZ x {r}) [c])
+ && s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask()) != nil
+ => (RISBGZ x {(*s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask())).RotateLeft(r.Amount)})
+
+// Absorb 'rotate then insert selected bits [into zero]' into right shift.
+(SRDconst (RISBGZ x {r}) [c])
+ && s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask()) != nil
+ => (RISBGZ x {(*s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask())).RotateLeft(r.Amount)})
+
+// Merge 'rotate then insert selected bits [into zero]' instructions together.
+(RISBGZ (RISBGZ x {y}) {z})
+ && z.InMerge(y.OutMask()) != nil
+ => (RISBGZ x {(*z.InMerge(y.OutMask())).RotateLeft(y.Amount)})
+
+// Convert RISBGZ into 64-bit shift (helps CSE).
+(RISBGZ x {r}) && r.End == 63 && r.Start == -r.Amount&63 => (SRDconst x [-r.Amount&63])
+(RISBGZ x {r}) && r.Start == 0 && r.End == 63-r.Amount => (SLDconst x [r.Amount])
+
+// Optimize single bit isolation when it is known to be equivalent to
+// the most significant bit due to mask produced by arithmetic shift.
+// Simply isolate the most significant bit itself and place it in the
+// correct position.
+//
+// Example: (int64(x) >> 63) & 0x8 -> RISBGZ $60, $60, $4, Rsrc, Rdst
+(RISBGZ (SRADconst x [c]) {r})
+ && r.Start == r.End // single bit selected
+ && (r.Start+r.Amount)&63 <= c // equivalent to most significant bit of x
+ => (RISBGZ x {s390x.NewRotateParams(r.Start, r.Start, -r.Start&63)})
+
+// Canonicalize the order of arguments to comparisons - helps with CSE.
+((CMP|CMPW|CMPU|CMPWU) x y) && x.ID > y.ID => (InvertFlags ((CMP|CMPW|CMPU|CMPWU) y x))
+
+// Use sign/zero extend instead of RISBGZ.
+(RISBGZ x {r}) && r == s390x.NewRotateParams(56, 63, 0) => (MOVBZreg x)
+(RISBGZ x {r}) && r == s390x.NewRotateParams(48, 63, 0) => (MOVHZreg x)
+(RISBGZ x {r}) && r == s390x.NewRotateParams(32, 63, 0) => (MOVWZreg x)
+
+// Use sign/zero extend instead of ANDW.
+(ANDWconst [0x00ff] x) => (MOVBZreg x)
+(ANDWconst [0xffff] x) => (MOVHZreg x)
+
+// Strength reduce multiplication to the sum (or difference) of two powers of two.
+//
+// Examples:
+// 5x -> 4x + 1x
+// 10x -> 8x + 2x
+// 120x -> 128x - 8x
+// -120x -> 8x - 128x
+//
+// We know that the rightmost bit of any positive value, once isolated, must either
+// be a power of 2 (because it is a single bit) or 0 (if the original value is 0).
+// In all of these rules we use a rightmost bit calculation to determine one operand
+// for the addition or subtraction. We then just need to calculate if the other
+// operand is a valid power of 2 before we can match the rule.
+//
+// Notes:
+// - the generic rules have already matched single powers of two so we ignore them here
+// - isPowerOfTwo32 asserts that its argument is greater than 0
+// - c&(c-1) = clear rightmost bit
+// - c&^(c-1) = isolate rightmost bit
+
+// c = 2ˣ + 2ʸ => c - 2ˣ = 2ʸ
+(MULL(D|W)const <t> x [c]) && isPowerOfTwo32(c&(c-1))
+ => ((ADD|ADDW) (SL(D|W)const <t> x [uint8(log32(c&(c-1)))])
+ (SL(D|W)const <t> x [uint8(log32(c&^(c-1)))]))
+
+// c = 2ʸ - 2ˣ => c + 2ˣ = 2ʸ
+(MULL(D|W)const <t> x [c]) && isPowerOfTwo32(c+(c&^(c-1)))
+ => ((SUB|SUBW) (SL(D|W)const <t> x [uint8(log32(c+(c&^(c-1))))])
+ (SL(D|W)const <t> x [uint8(log32(c&^(c-1)))]))
+
+// c = 2ˣ - 2ʸ => -c + 2ˣ = 2ʸ
+(MULL(D|W)const <t> x [c]) && isPowerOfTwo32(-c+(-c&^(-c-1)))
+ => ((SUB|SUBW) (SL(D|W)const <t> x [uint8(log32(-c&^(-c-1)))])
+ (SL(D|W)const <t> x [uint8(log32(-c+(-c&^(-c-1))))]))
+
+// Fold ADD into MOVDaddr. Odd offsets from SB shouldn't be folded (LARL can't handle them).
+(ADDconst [c] (MOVDaddr [d] {s} x:(SB))) && ((c+d)&1 == 0) && is32Bit(int64(c)+int64(d)) => (MOVDaddr [c+d] {s} x)
+(ADDconst [c] (MOVDaddr [d] {s} x)) && x.Op != OpSB && is20Bit(int64(c)+int64(d)) => (MOVDaddr [c+d] {s} x)
+(ADD idx (MOVDaddr [c] {s} ptr)) && ptr.Op != OpSB => (MOVDaddridx [c] {s} ptr idx)
+
+// fold ADDconst into MOVDaddrx
+(ADDconst [c] (MOVDaddridx [d] {s} x y)) && is20Bit(int64(c)+int64(d)) => (MOVDaddridx [c+d] {s} x y)
+(MOVDaddridx [c] {s} (ADDconst [d] x) y) && is20Bit(int64(c)+int64(d)) => (MOVDaddridx [c+d] {s} x y)
+(MOVDaddridx [c] {s} x (ADDconst [d] y)) && is20Bit(int64(c)+int64(d)) => (MOVDaddridx [c+d] {s} x y)
+
+// reverse ordering of compare instruction
+(LOCGR {c} x y (InvertFlags cmp)) => (LOCGR {c.ReverseComparison()} x y cmp)
+
+// replace load from same location as preceding store with copy
+(MOVDload [off] {sym} ptr1 (MOVDstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => x
+(MOVWload [off] {sym} ptr1 (MOVWstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (MOVWreg x)
+(MOVHload [off] {sym} ptr1 (MOVHstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (MOVHreg x)
+(MOVBload [off] {sym} ptr1 (MOVBstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (MOVBreg x)
+(MOVWZload [off] {sym} ptr1 (MOVWstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (MOVWZreg x)
+(MOVHZload [off] {sym} ptr1 (MOVHstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (MOVHZreg x)
+(MOVBZload [off] {sym} ptr1 (MOVBstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (MOVBZreg x)
+(MOVDload [off] {sym} ptr1 (FMOVDstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (LGDR x)
+(FMOVDload [off] {sym} ptr1 (MOVDstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (LDGR x)
+(FMOVDload [off] {sym} ptr1 (FMOVDstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => x
+(FMOVSload [off] {sym} ptr1 (FMOVSstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => x
+
+// prefer FPR <-> GPR moves over combined load ops
+(MULLDload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _)) && isSamePtr(ptr1, ptr2) => (MULLD x (LGDR <t> y))
+(ADDload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _)) && isSamePtr(ptr1, ptr2) => (ADD x (LGDR <t> y))
+(SUBload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _)) && isSamePtr(ptr1, ptr2) => (SUB x (LGDR <t> y))
+(ORload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _)) && isSamePtr(ptr1, ptr2) => (OR x (LGDR <t> y))
+(ANDload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _)) && isSamePtr(ptr1, ptr2) => (AND x (LGDR <t> y))
+(XORload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _)) && isSamePtr(ptr1, ptr2) => (XOR x (LGDR <t> y))
+
+// detect attempts to set/clear the sign bit
+// may need to be reworked when NIHH/OIHH are added
+(RISBGZ (LGDR <t> x) {r}) && r == s390x.NewRotateParams(1, 63, 0) => (LGDR <t> (LPDFR <x.Type> x))
+(LDGR <t> (RISBGZ x {r})) && r == s390x.NewRotateParams(1, 63, 0) => (LPDFR (LDGR <t> x))
+(OR (MOVDconst [-1<<63]) (LGDR <t> x)) => (LGDR <t> (LNDFR <x.Type> x))
+(LDGR <t> (OR (MOVDconst [-1<<63]) x)) => (LNDFR (LDGR <t> x))
+
+// detect attempts to set the sign bit with load
+(LDGR <t> x:(ORload <t1> [off] {sym} (MOVDconst [-1<<63]) ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (LNDFR <t> (LDGR <t> (MOVDload <t1> [off] {sym} ptr mem)))
+
+// detect copysign
+(OR (RISBGZ (LGDR x) {r}) (LGDR (LPDFR <t> y)))
+ && r == s390x.NewRotateParams(0, 0, 0)
+ => (LGDR (CPSDR <t> y x))
+(OR (RISBGZ (LGDR x) {r}) (MOVDconst [c]))
+ && c >= 0
+ && r == s390x.NewRotateParams(0, 0, 0)
+ => (LGDR (CPSDR <x.Type> (FMOVDconst <x.Type> [math.Float64frombits(uint64(c))]) x))
+(CPSDR y (FMOVDconst [c])) && !math.Signbit(c) => (LPDFR y)
+(CPSDR y (FMOVDconst [c])) && math.Signbit(c) => (LNDFR y)
+
+// absorb negations into set/clear sign bit
+(FNEG (LPDFR x)) => (LNDFR x)
+(FNEG (LNDFR x)) => (LPDFR x)
+(FNEGS (LPDFR x)) => (LNDFR x)
+(FNEGS (LNDFR x)) => (LPDFR x)
+
+// no need to convert float32 to float64 to set/clear sign bit
+(LEDBR (LPDFR (LDEBR x))) => (LPDFR x)
+(LEDBR (LNDFR (LDEBR x))) => (LNDFR x)
+
+// remove unnecessary FPR <-> GPR moves
+(LDGR (LGDR x)) => x
+(LGDR (LDGR x)) => x
+
+// Don't extend before storing
+(MOVWstore [off] {sym} ptr (MOVWreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVBreg x) mem) => (MOVBstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOVWZreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
+(MOVHstore [off] {sym} ptr (MOVHZreg x) mem) => (MOVHstore [off] {sym} ptr x mem)
+(MOVBstore [off] {sym} ptr (MOVBZreg 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 ADDconst get eliminated, we still have to compute the ADDconst and we now
+// have potentially two live values (ptr and (ADDconst [off] ptr)) instead of one.
+// Nevertheless, let's do it!
+(MOVDload [off1] {sym} (ADDconst [off2] ptr) mem) && is20Bit(int64(off1)+int64(off2)) => (MOVDload [off1+off2] {sym} ptr mem)
+(MOVWload [off1] {sym} (ADDconst [off2] ptr) mem) && is20Bit(int64(off1)+int64(off2)) => (MOVWload [off1+off2] {sym} ptr mem)
+(MOVHload [off1] {sym} (ADDconst [off2] ptr) mem) && is20Bit(int64(off1)+int64(off2)) => (MOVHload [off1+off2] {sym} ptr mem)
+(MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) && is20Bit(int64(off1)+int64(off2)) => (MOVBload [off1+off2] {sym} ptr mem)
+(MOVWZload [off1] {sym} (ADDconst [off2] ptr) mem) && is20Bit(int64(off1)+int64(off2)) => (MOVWZload [off1+off2] {sym} ptr mem)
+(MOVHZload [off1] {sym} (ADDconst [off2] ptr) mem) && is20Bit(int64(off1)+int64(off2)) => (MOVHZload [off1+off2] {sym} ptr mem)
+(MOVBZload [off1] {sym} (ADDconst [off2] ptr) mem) && is20Bit(int64(off1)+int64(off2)) => (MOVBZload [off1+off2] {sym} ptr mem)
+(FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem) && is20Bit(int64(off1)+int64(off2)) => (FMOVSload [off1+off2] {sym} ptr mem)
+(FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem) && is20Bit(int64(off1)+int64(off2)) => (FMOVDload [off1+off2] {sym} ptr mem)
+
+(MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is20Bit(int64(off1)+int64(off2)) => (MOVDstore [off1+off2] {sym} ptr val mem)
+(MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is20Bit(int64(off1)+int64(off2)) => (MOVWstore [off1+off2] {sym} ptr val mem)
+(MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is20Bit(int64(off1)+int64(off2)) => (MOVHstore [off1+off2] {sym} ptr val mem)
+(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is20Bit(int64(off1)+int64(off2)) => (MOVBstore [off1+off2] {sym} ptr val mem)
+(FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is20Bit(int64(off1)+int64(off2)) => (FMOVSstore [off1+off2] {sym} ptr val mem)
+(FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is20Bit(int64(off1)+int64(off2)) => (FMOVDstore [off1+off2] {sym} ptr val mem)
+
+(ADDload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (ADDload [off1+off2] {sym} x ptr mem)
+(ADDWload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (ADDWload [off1+off2] {sym} x ptr mem)
+(MULLDload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (MULLDload [off1+off2] {sym} x ptr mem)
+(MULLWload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (MULLWload [off1+off2] {sym} x ptr mem)
+(SUBload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (SUBload [off1+off2] {sym} x ptr mem)
+(SUBWload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (SUBWload [off1+off2] {sym} x ptr mem)
+
+(ANDload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (ANDload [off1+off2] {sym} x ptr mem)
+(ANDWload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (ANDWload [off1+off2] {sym} x ptr mem)
+(ORload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (ORload [off1+off2] {sym} x ptr mem)
+(ORWload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (ORWload [off1+off2] {sym} x ptr mem)
+(XORload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (XORload [off1+off2] {sym} x ptr mem)
+(XORWload [off1] {sym} x (ADDconst [off2] ptr) mem) && ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2)) => (XORWload [off1+off2] {sym} x ptr mem)
+
+// Fold constants into stores.
+(MOVDstore [off] {sym} ptr (MOVDconst [c]) mem) && is16Bit(c) && isU12Bit(int64(off)) && ptr.Op != OpSB =>
+ (MOVDstoreconst [makeValAndOff32(int32(c),off)] {sym} ptr mem)
+(MOVWstore [off] {sym} ptr (MOVDconst [c]) mem) && is16Bit(c) && isU12Bit(int64(off)) && ptr.Op != OpSB =>
+ (MOVWstoreconst [makeValAndOff32(int32(c),off)] {sym} ptr mem)
+(MOVHstore [off] {sym} ptr (MOVDconst [c]) mem) && isU12Bit(int64(off)) && ptr.Op != OpSB =>
+ (MOVHstoreconst [makeValAndOff32(int32(int16(c)),off)] {sym} ptr mem)
+(MOVBstore [off] {sym} ptr (MOVDconst [c]) mem) && is20Bit(int64(off)) && ptr.Op != OpSB =>
+ (MOVBstoreconst [makeValAndOff32(int32(int8(c)),off)] {sym} ptr mem)
+
+// Fold address offsets into constant stores.
+(MOVDstoreconst [sc] {s} (ADDconst [off] ptr) mem) && isU12Bit(sc.Off()+int64(off)) =>
+ (MOVDstoreconst [sc.addOffset32(off)] {s} ptr mem)
+(MOVWstoreconst [sc] {s} (ADDconst [off] ptr) mem) && isU12Bit(sc.Off()+int64(off)) =>
+ (MOVWstoreconst [sc.addOffset32(off)] {s} ptr mem)
+(MOVHstoreconst [sc] {s} (ADDconst [off] ptr) mem) && isU12Bit(sc.Off()+int64(off)) =>
+ (MOVHstoreconst [sc.addOffset32(off)] {s} ptr mem)
+(MOVBstoreconst [sc] {s} (ADDconst [off] ptr) mem) && is20Bit(sc.Off()+int64(off)) =>
+ (MOVBstoreconst [sc.addOffset32(off)] {s} ptr mem)
+
+// Merge address calculations into loads and stores.
+// Offsets from SB must not be merged into unaligned memory accesses because
+// loads/stores using PC-relative addressing directly must be aligned to the
+// size of the target.
+(MOVDload [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%8 == 0 && (off1+off2)%8 == 0)) =>
+ (MOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVWZload [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%4 == 0 && (off1+off2)%4 == 0)) =>
+ (MOVWZload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVHZload [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%2 == 0 && (off1+off2)%2 == 0)) =>
+ (MOVHZload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVBZload [off1] {sym1} (MOVDaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVBZload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+
+(MOVWload [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%4 == 0 && (off1+off2)%4 == 0)) =>
+ (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVHload [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%2 == 0 && (off1+off2)%2 == 0)) =>
+ (MOVHload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+(MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+
+(MOVDstore [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%8 == 0 && (off1+off2)%8 == 0)) =>
+ (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVWstore [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%4 == 0 && (off1+off2)%4 == 0)) =>
+ (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVHstore [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%2 == 0 && (off1+off2)%2 == 0)) =>
+ (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) =>
+ (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+
+(ADDload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (ADDload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+(ADDWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (ADDWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+(MULLDload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (MULLDload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+(MULLWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (MULLWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+(SUBload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (SUBload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+(SUBWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (SUBWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+
+(ANDload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (ANDload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+(ANDWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (ANDWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+(ORload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (ORload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+(ORWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (ORWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+(XORload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (XORload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+(XORWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem) && ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2) => (XORWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+
+// Cannot store constant to SB directly (no 'move relative long immediate' instructions).
+(MOVDstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off) =>
+ (MOVDstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+(MOVWstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off) =>
+ (MOVWstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+(MOVHstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off) =>
+ (MOVHstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+(MOVBstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off) =>
+ (MOVBstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+
+// MOVDaddr into MOVDaddridx
+(MOVDaddridx [off1] {sym1} (MOVDaddr [off2] {sym2} x) y) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB =>
+ (MOVDaddridx [off1+off2] {mergeSym(sym1,sym2)} x y)
+(MOVDaddridx [off1] {sym1} x (MOVDaddr [off2] {sym2} y)) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && y.Op != OpSB =>
+ (MOVDaddridx [off1+off2] {mergeSym(sym1,sym2)} x y)
+
+// Absorb InvertFlags into branches.
+(BRC {c} (InvertFlags cmp) yes no) => (BRC {c.ReverseComparison()} cmp yes no)
+
+// Constant comparisons.
+(CMPconst (MOVDconst [x]) [y]) && x==int64(y) => (FlagEQ)
+(CMPconst (MOVDconst [x]) [y]) && x<int64(y) => (FlagLT)
+(CMPconst (MOVDconst [x]) [y]) && x>int64(y) => (FlagGT)
+(CMPUconst (MOVDconst [x]) [y]) && uint64(x)==uint64(y) => (FlagEQ)
+(CMPUconst (MOVDconst [x]) [y]) && uint64(x)<uint64(y) => (FlagLT)
+(CMPUconst (MOVDconst [x]) [y]) && uint64(x)>uint64(y) => (FlagGT)
+
+(CMPWconst (MOVDconst [x]) [y]) && int32(x)==int32(y) => (FlagEQ)
+(CMPWconst (MOVDconst [x]) [y]) && int32(x)<int32(y) => (FlagLT)
+(CMPWconst (MOVDconst [x]) [y]) && int32(x)>int32(y) => (FlagGT)
+(CMPWUconst (MOVDconst [x]) [y]) && uint32(x)==uint32(y) => (FlagEQ)
+(CMPWUconst (MOVDconst [x]) [y]) && uint32(x)<uint32(y) => (FlagLT)
+(CMPWUconst (MOVDconst [x]) [y]) && uint32(x)>uint32(y) => (FlagGT)
+
+(CMP(W|WU)const (MOVBZreg _) [c]) && 0xff < c => (FlagLT)
+(CMP(W|WU)const (MOVHZreg _) [c]) && 0xffff < c => (FlagLT)
+
+(CMPconst (SRDconst _ [c]) [n]) && c > 0 && n < 0 => (FlagGT)
+(CMPWconst (SRWconst _ [c]) [n]) && c > 0 && n < 0 => (FlagGT)
+
+(CMPUconst (SRDconst _ [c]) [n]) && c > 0 && c < 64 && (1<<uint(64-c)) <= uint64(n) => (FlagLT)
+(CMPWUconst (SRWconst _ [c]) [n]) && c > 0 && c < 32 && (1<<uint(32-c)) <= uint32(n) => (FlagLT)
+
+(CMPWconst (ANDWconst _ [m]) [n]) && int32(m) >= 0 && int32(m) < int32(n) => (FlagLT)
+(CMPWUconst (ANDWconst _ [m]) [n]) && uint32(m) < uint32(n) => (FlagLT)
+
+(CMPconst (RISBGZ x {r}) [c]) && c > 0 && r.OutMask() < uint64(c) => (FlagLT)
+(CMPUconst (RISBGZ x {r}) [c]) && r.OutMask() < uint64(uint32(c)) => (FlagLT)
+
+// Constant compare-and-branch with immediate.
+(CGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Equal != 0 && int64(x) == int64(y) => (First yes no)
+(CGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Less != 0 && int64(x) < int64(y) => (First yes no)
+(CGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Greater != 0 && int64(x) > int64(y) => (First yes no)
+(CIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Equal != 0 && int32(x) == int32(y) => (First yes no)
+(CIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Less != 0 && int32(x) < int32(y) => (First yes no)
+(CIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Greater != 0 && int32(x) > int32(y) => (First yes no)
+(CLGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Equal != 0 && uint64(x) == uint64(y) => (First yes no)
+(CLGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Less != 0 && uint64(x) < uint64(y) => (First yes no)
+(CLGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Greater != 0 && uint64(x) > uint64(y) => (First yes no)
+(CLIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Equal != 0 && uint32(x) == uint32(y) => (First yes no)
+(CLIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Less != 0 && uint32(x) < uint32(y) => (First yes no)
+(CLIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Greater != 0 && uint32(x) > uint32(y) => (First yes no)
+(CGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Equal == 0 && int64(x) == int64(y) => (First no yes)
+(CGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Less == 0 && int64(x) < int64(y) => (First no yes)
+(CGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Greater == 0 && int64(x) > int64(y) => (First no yes)
+(CIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Equal == 0 && int32(x) == int32(y) => (First no yes)
+(CIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Less == 0 && int32(x) < int32(y) => (First no yes)
+(CIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Greater == 0 && int32(x) > int32(y) => (First no yes)
+(CLGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Equal == 0 && uint64(x) == uint64(y) => (First no yes)
+(CLGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Less == 0 && uint64(x) < uint64(y) => (First no yes)
+(CLGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Greater == 0 && uint64(x) > uint64(y) => (First no yes)
+(CLIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Equal == 0 && uint32(x) == uint32(y) => (First no yes)
+(CLIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Less == 0 && uint32(x) < uint32(y) => (First no yes)
+(CLIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Greater == 0 && uint32(x) > uint32(y) => (First no yes)
+
+// Constant compare-and-branch with immediate when unsigned comparison with zero.
+(C(L|LG)IJ {s390x.GreaterOrEqual} _ [0] yes no) => (First yes no)
+(C(L|LG)IJ {s390x.Less} _ [0] yes no) => (First no yes)
+
+// Constant compare-and-branch when operands match.
+(C(GR|R|LGR|LR)J {c} x y yes no) && x == y && c&s390x.Equal != 0 => (First yes no)
+(C(GR|R|LGR|LR)J {c} x y yes no) && x == y && c&s390x.Equal == 0 => (First no yes)
+
+// Convert 64-bit comparisons to 32-bit comparisons and signed comparisons
+// to unsigned comparisons.
+// Helps simplify constant comparison detection.
+(CM(P|PU)const (MOV(W|WZ)reg x) [c]) => (CMP(W|WU)const x [c])
+(CM(P|P|PU|PU)const x:(MOV(H|HZ|H|HZ)reg _) [c]) => (CMP(W|W|WU|WU)const x [c])
+(CM(P|P|PU|PU)const x:(MOV(B|BZ|B|BZ)reg _) [c]) => (CMP(W|W|WU|WU)const x [c])
+(CMPconst (MOV(WZ|W)reg x:(ANDWconst [m] _)) [c]) && int32(m) >= 0 && c >= 0 => (CMPWUconst x [c])
+(CMPUconst (MOV(WZ|W)reg x:(ANDWconst [m] _)) [c]) && int32(m) >= 0 => (CMPWUconst x [c])
+(CMPconst x:(SRDconst _ [c]) [n]) && c > 0 && n >= 0 => (CMPUconst x [n])
+(CMPWconst x:(SRWconst _ [c]) [n]) && c > 0 && n >= 0 => (CMPWUconst x [n])
+
+// Absorb sign and zero extensions into 32-bit comparisons.
+(CMP(W|W|WU|WU) x (MOV(W|WZ|W|WZ)reg y)) => (CMP(W|W|WU|WU) x y)
+(CMP(W|W|WU|WU) (MOV(W|WZ|W|WZ)reg x) y) => (CMP(W|W|WU|WU) x y)
+(CMP(W|W|WU|WU)const (MOV(W|WZ|W|WZ)reg x) [c]) => (CMP(W|W|WU|WU)const x [c])
+
+// Absorb flag constants into branches.
+(BRC {c} (FlagEQ) yes no) && c&s390x.Equal != 0 => (First yes no)
+(BRC {c} (FlagLT) yes no) && c&s390x.Less != 0 => (First yes no)
+(BRC {c} (FlagGT) yes no) && c&s390x.Greater != 0 => (First yes no)
+(BRC {c} (FlagOV) yes no) && c&s390x.Unordered != 0 => (First yes no)
+
+(BRC {c} (FlagEQ) yes no) && c&s390x.Equal == 0 => (First no yes)
+(BRC {c} (FlagLT) yes no) && c&s390x.Less == 0 => (First no yes)
+(BRC {c} (FlagGT) yes no) && c&s390x.Greater == 0 => (First no yes)
+(BRC {c} (FlagOV) yes no) && c&s390x.Unordered == 0 => (First no yes)
+
+// Absorb flag constants into SETxx ops.
+(LOCGR {c} _ x (FlagEQ)) && c&s390x.Equal != 0 => x
+(LOCGR {c} _ x (FlagLT)) && c&s390x.Less != 0 => x
+(LOCGR {c} _ x (FlagGT)) && c&s390x.Greater != 0 => x
+(LOCGR {c} _ x (FlagOV)) && c&s390x.Unordered != 0 => x
+
+(LOCGR {c} x _ (FlagEQ)) && c&s390x.Equal == 0 => x
+(LOCGR {c} x _ (FlagLT)) && c&s390x.Less == 0 => x
+(LOCGR {c} x _ (FlagGT)) && c&s390x.Greater == 0 => x
+(LOCGR {c} x _ (FlagOV)) && c&s390x.Unordered == 0 => x
+
+// Remove redundant *const ops
+(ADDconst [0] x) => x
+(ADDWconst [c] x) && int32(c)==0 => x
+(SUBconst [0] x) => x
+(SUBWconst [c] x) && int32(c) == 0 => x
+(ANDconst [0] _) => (MOVDconst [0])
+(ANDWconst [c] _) && int32(c)==0 => (MOVDconst [0])
+(ANDconst [-1] x) => x
+(ANDWconst [c] x) && int32(c)==-1 => x
+(ORconst [0] x) => x
+(ORWconst [c] x) && int32(c)==0 => x
+(ORconst [-1] _) => (MOVDconst [-1])
+(ORWconst [c] _) && int32(c)==-1 => (MOVDconst [-1])
+(XORconst [0] x) => x
+(XORWconst [c] x) && int32(c)==0 => x
+
+// Shifts by zero (may be inserted during multiplication strength reduction).
+((SLD|SLW|SRD|SRW|SRAD|SRAW)const x [0]) => x
+
+// Convert constant subtracts to constant adds.
+(SUBconst [c] x) && c != -(1<<31) => (ADDconst [-c] x)
+(SUBWconst [c] x) => (ADDWconst [-int32(c)] x)
+
+// generic constant folding
+// TODO: more of this
+(ADDconst [c] (MOVDconst [d])) => (MOVDconst [int64(c)+d])
+(ADDWconst [c] (MOVDconst [d])) => (MOVDconst [int64(c)+d])
+(ADDconst [c] (ADDconst [d] x)) && is32Bit(int64(c)+int64(d)) => (ADDconst [c+d] x)
+(ADDWconst [c] (ADDWconst [d] x)) => (ADDWconst [int32(c+d)] x)
+(SUBconst (MOVDconst [d]) [c]) => (MOVDconst [d-int64(c)])
+(SUBconst (SUBconst x [d]) [c]) && is32Bit(-int64(c)-int64(d)) => (ADDconst [-c-d] x)
+(SRADconst [c] (MOVDconst [d])) => (MOVDconst [d>>uint64(c)])
+(SRAWconst [c] (MOVDconst [d])) => (MOVDconst [int64(int32(d))>>uint64(c)])
+(NEG (MOVDconst [c])) => (MOVDconst [-c])
+(NEGW (MOVDconst [c])) => (MOVDconst [int64(int32(-c))])
+(MULLDconst [c] (MOVDconst [d])) => (MOVDconst [int64(c)*d])
+(MULLWconst [c] (MOVDconst [d])) => (MOVDconst [int64(c*int32(d))])
+(AND (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c&d])
+(ANDconst [c] (MOVDconst [d])) => (MOVDconst [c&d])
+(ANDWconst [c] (MOVDconst [d])) => (MOVDconst [int64(c)&d])
+(OR (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c|d])
+(ORconst [c] (MOVDconst [d])) => (MOVDconst [c|d])
+(ORWconst [c] (MOVDconst [d])) => (MOVDconst [int64(c)|d])
+(XOR (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c^d])
+(XORconst [c] (MOVDconst [d])) => (MOVDconst [c^d])
+(XORWconst [c] (MOVDconst [d])) => (MOVDconst [int64(c)^d])
+(LoweredRound32F x:(FMOVSconst)) => x
+(LoweredRound64F x:(FMOVDconst)) => x
+
+// generic simplifications
+// TODO: more of this
+(ADD x (NEG y)) => (SUB x y)
+(ADDW x (NEGW y)) => (SUBW x y)
+(SUB x x) => (MOVDconst [0])
+(SUBW x x) => (MOVDconst [0])
+(AND x x) => x
+(ANDW x x) => x
+(OR x x) => x
+(ORW x x) => x
+(XOR x x) => (MOVDconst [0])
+(XORW x x) => (MOVDconst [0])
+(NEG (ADDconst [c] (NEG x))) && c != -(1<<31) => (ADDconst [-c] x)
+(MOVBZreg (ANDWconst [m] x)) => (MOVWZreg (ANDWconst <typ.UInt32> [int32( uint8(m))] x))
+(MOVHZreg (ANDWconst [m] x)) => (MOVWZreg (ANDWconst <typ.UInt32> [int32(uint16(m))] x))
+(MOVBreg (ANDWconst [m] x)) && int8(m) >= 0 => (MOVWZreg (ANDWconst <typ.UInt32> [int32( uint8(m))] x))
+(MOVHreg (ANDWconst [m] x)) && int16(m) >= 0 => (MOVWZreg (ANDWconst <typ.UInt32> [int32(uint16(m))] x))
+
+// carry flag generation
+// (only constant fold carry of zero)
+(Select1 (ADDCconst (MOVDconst [c]) [d]))
+ && uint64(c+int64(d)) >= uint64(c) && c+int64(d) == 0
+ => (FlagEQ)
+(Select1 (ADDCconst (MOVDconst [c]) [d]))
+ && uint64(c+int64(d)) >= uint64(c) && c+int64(d) != 0
+ => (FlagLT)
+
+// borrow flag generation
+// (only constant fold borrow of zero)
+(Select1 (SUBC (MOVDconst [c]) (MOVDconst [d])))
+ && uint64(d) <= uint64(c) && c-d == 0
+ => (FlagGT)
+(Select1 (SUBC (MOVDconst [c]) (MOVDconst [d])))
+ && uint64(d) <= uint64(c) && c-d != 0
+ => (FlagOV)
+
+// add with carry
+(ADDE x y (FlagEQ)) => (ADDC x y)
+(ADDE x y (FlagLT)) => (ADDC x y)
+(ADDC x (MOVDconst [c])) && is16Bit(c) => (ADDCconst x [int16(c)])
+(Select0 (ADDCconst (MOVDconst [c]) [d])) => (MOVDconst [c+int64(d)])
+
+// subtract with borrow
+(SUBE x y (FlagGT)) => (SUBC x y)
+(SUBE x y (FlagOV)) => (SUBC x y)
+(Select0 (SUBC (MOVDconst [c]) (MOVDconst [d]))) => (MOVDconst [c-d])
+
+// collapse carry chain
+(ADDE x y (Select1 (ADDCconst [-1] (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) c)))))
+ => (ADDE x y c)
+
+// collapse borrow chain
+(SUBE x y (Select1 (SUBC (MOVDconst [0]) (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) c))))))
+ => (SUBE x y c)
+
+// branch on carry
+(C(G|LG)IJ {s390x.Equal} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [0]) => (BRC {s390x.NoCarry} carry)
+(C(G|LG)IJ {s390x.Equal} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [1]) => (BRC {s390x.Carry} carry)
+(C(G|LG)IJ {s390x.LessOrGreater} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [0]) => (BRC {s390x.Carry} carry)
+(C(G|LG)IJ {s390x.LessOrGreater} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [1]) => (BRC {s390x.NoCarry} carry)
+(C(G|LG)IJ {s390x.Greater} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [0]) => (BRC {s390x.Carry} carry)
+
+// branch on borrow
+(C(G|LG)IJ {s390x.Equal} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [0]) => (BRC {s390x.NoBorrow} borrow)
+(C(G|LG)IJ {s390x.Equal} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [1]) => (BRC {s390x.Borrow} borrow)
+(C(G|LG)IJ {s390x.LessOrGreater} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [0]) => (BRC {s390x.Borrow} borrow)
+(C(G|LG)IJ {s390x.LessOrGreater} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [1]) => (BRC {s390x.NoBorrow} borrow)
+(C(G|LG)IJ {s390x.Greater} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [0]) => (BRC {s390x.Borrow} borrow)
+
+// fused multiply-add
+(Select0 (F(ADD|SUB) (FMUL y z) x)) => (FM(ADD|SUB) x y z)
+(Select0 (F(ADDS|SUBS) (FMULS y z) x)) => (FM(ADDS|SUBS) x y z)
+
+// Convert floating point comparisons against zero into 'load and test' instructions.
+(F(CMP|CMPS) x (FMOV(D|S)const [0.0])) => (LT(D|E)BR x)
+(F(CMP|CMPS) (FMOV(D|S)const [0.0]) x) => (InvertFlags (LT(D|E)BR <v.Type> x))
+
+// FSUB, FSUBS, FADD, FADDS now produce a condition code representing the
+// comparison of the result with 0.0. If a compare with zero instruction
+// (e.g. LTDBR) is following one of those instructions, we can use the
+// generated flag and remove the comparison instruction.
+// Note: when inserting Select1 ops we need to ensure they are in the
+// same block as their argument. We could also use @x.Block for this
+// but moving the flag generating value to a different block seems to
+// increase the likelihood that the flags value will have to be regenerated
+// by flagalloc which is not what we want.
+(LTDBR (Select0 x:(F(ADD|SUB) _ _))) && b == x.Block => (Select1 x)
+(LTEBR (Select0 x:(F(ADDS|SUBS) _ _))) && b == x.Block => (Select1 x)
+
+// Fold memory operations into operations.
+// Exclude global data (SB) because these instructions cannot handle relative addresses.
+// TODO(mundaym): indexed versions of these?
+((ADD|SUB|MULLD|AND|OR|XOR) <t> x g:(MOVDload [off] {sym} ptr mem))
+ && ptr.Op != OpSB
+ && is20Bit(int64(off))
+ && canMergeLoadClobber(v, g, x)
+ && clobber(g)
+ => ((ADD|SUB|MULLD|AND|OR|XOR)load <t> [off] {sym} x ptr mem)
+((ADD|SUB|MULL|AND|OR|XOR)W <t> x g:(MOVWload [off] {sym} ptr mem))
+ && ptr.Op != OpSB
+ && is20Bit(int64(off))
+ && canMergeLoadClobber(v, g, x)
+ && clobber(g)
+ => ((ADD|SUB|MULL|AND|OR|XOR)Wload <t> [off] {sym} x ptr mem)
+((ADD|SUB|MULL|AND|OR|XOR)W <t> x g:(MOVWZload [off] {sym} ptr mem))
+ && ptr.Op != OpSB
+ && is20Bit(int64(off))
+ && canMergeLoadClobber(v, g, x)
+ && clobber(g)
+ => ((ADD|SUB|MULL|AND|OR|XOR)Wload <t> [off] {sym} x ptr mem)
+
+// Combine constant stores into larger (unaligned) stores.
+// Avoid SB because constant stores to relative offsets are
+// emulated by the assembler and also can't handle unaligned offsets.
+(MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && a.Off() + 1 == c.Off()
+ && clobber(x)
+ => (MOVHstoreconst [makeValAndOff32(c.Val32()&0xff | a.Val32()<<8, a.Off32())] {s} p mem)
+(MOVHstoreconst [c] {s} p x:(MOVHstoreconst [a] {s} p mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && a.Off() + 2 == c.Off()
+ && clobber(x)
+ => (MOVWstore [a.Off32()] {s} p (MOVDconst [int64(c.Val32()&0xffff | a.Val32()<<16)]) mem)
+(MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && a.Off() + 4 == c.Off()
+ && clobber(x)
+ => (MOVDstore [a.Off32()] {s} p (MOVDconst [c.Val()&0xffffffff | a.Val()<<32]) mem)
+
+// Combine stores into larger (unaligned) stores.
+// It doesn't work on global data (based on SB) because stores with relative addressing
+// require that the memory operand be aligned.
+(MOVBstore [i] {s} p w x:(MOVBstore [i-1] {s} p (SRDconst [8] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstore [i-1] {s} p w mem)
+(MOVBstore [i] {s} p w0:(SRDconst [j] w) x:(MOVBstore [i-1] {s} p (SRDconst [j+8] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstore [i-1] {s} p w0 mem)
+(MOVBstore [i] {s} p w x:(MOVBstore [i-1] {s} p (SRWconst [8] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstore [i-1] {s} p w mem)
+(MOVBstore [i] {s} p w0:(SRWconst [j] w) x:(MOVBstore [i-1] {s} p (SRWconst [j+8] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHstore [i-1] {s} p w0 mem)
+(MOVHstore [i] {s} p w x:(MOVHstore [i-2] {s} p (SRDconst [16] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstore [i-2] {s} p w mem)
+(MOVHstore [i] {s} p w0:(SRDconst [j] w) x:(MOVHstore [i-2] {s} p (SRDconst [j+16] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstore [i-2] {s} p w0 mem)
+(MOVHstore [i] {s} p w x:(MOVHstore [i-2] {s} p (SRWconst [16] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstore [i-2] {s} p w mem)
+(MOVHstore [i] {s} p w0:(SRWconst [j] w) x:(MOVHstore [i-2] {s} p (SRWconst [j+16] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWstore [i-2] {s} p w0 mem)
+(MOVWstore [i] {s} p (SRDconst [32] w) x:(MOVWstore [i-4] {s} p w mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVDstore [i-4] {s} p w mem)
+(MOVWstore [i] {s} p w0:(SRDconst [j] w) x:(MOVWstore [i-4] {s} p (SRDconst [j+32] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVDstore [i-4] {s} p w0 mem)
+
+// Combine stores into larger (unaligned) stores with the bytes reversed (little endian).
+// Store-with-bytes-reversed instructions do not support relative memory addresses,
+// so these stores can't operate on global data (SB).
+(MOVBstore [i] {s} p (SRDconst [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHBRstore [i-1] {s} p w mem)
+(MOVBstore [i] {s} p (SRDconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SRDconst [j-8] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHBRstore [i-1] {s} p w0 mem)
+(MOVBstore [i] {s} p (SRWconst [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHBRstore [i-1] {s} p w mem)
+(MOVBstore [i] {s} p (SRWconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SRWconst [j-8] w) mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVHBRstore [i-1] {s} p w0 mem)
+(MOVHBRstore [i] {s} p (SRDconst [16] w) x:(MOVHBRstore [i-2] {s} p w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWBRstore [i-2] {s} p w mem)
+(MOVHBRstore [i] {s} p (SRDconst [j] w) x:(MOVHBRstore [i-2] {s} p w0:(SRDconst [j-16] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWBRstore [i-2] {s} p w0 mem)
+(MOVHBRstore [i] {s} p (SRWconst [16] w) x:(MOVHBRstore [i-2] {s} p w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWBRstore [i-2] {s} p w mem)
+(MOVHBRstore [i] {s} p (SRWconst [j] w) x:(MOVHBRstore [i-2] {s} p w0:(SRWconst [j-16] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVWBRstore [i-2] {s} p w0 mem)
+(MOVWBRstore [i] {s} p (SRDconst [32] w) x:(MOVWBRstore [i-4] {s} p w mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVDBRstore [i-4] {s} p w mem)
+(MOVWBRstore [i] {s} p (SRDconst [j] w) x:(MOVWBRstore [i-4] {s} p w0:(SRDconst [j-32] w) mem))
+ && x.Uses == 1
+ && clobber(x)
+ => (MOVDBRstore [i-4] {s} p w0 mem)
+
+// Combining byte loads into larger (unaligned) loads.
+
+// Big-endian loads
+
+(ORW x1:(MOVBZload [i1] {s} p mem)
+ sh:(SLWconst [8] x0:(MOVBZload [i0] {s} p mem)))
+ && i1 == i0+1
+ && p.Op != OpSB
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVHZload [i0] {s} p mem)
+
+(OR x1:(MOVBZload [i1] {s} p mem)
+ sh:(SLDconst [8] x0:(MOVBZload [i0] {s} p mem)))
+ && i1 == i0+1
+ && p.Op != OpSB
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVHZload [i0] {s} p mem)
+
+(ORW x1:(MOVHZload [i1] {s} p mem)
+ sh:(SLWconst [16] x0:(MOVHZload [i0] {s} p mem)))
+ && i1 == i0+2
+ && p.Op != OpSB
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVWZload [i0] {s} p mem)
+
+(OR x1:(MOVHZload [i1] {s} p mem)
+ sh:(SLDconst [16] x0:(MOVHZload [i0] {s} p mem)))
+ && i1 == i0+2
+ && p.Op != OpSB
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVWZload [i0] {s} p mem)
+
+(OR x1:(MOVWZload [i1] {s} p mem)
+ sh:(SLDconst [32] x0:(MOVWZload [i0] {s} p mem)))
+ && i1 == i0+4
+ && p.Op != OpSB
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVDload [i0] {s} p mem)
+
+(ORW
+ s0:(SLWconst [j0] x0:(MOVBZload [i0] {s} p mem))
+ or:(ORW
+ s1:(SLWconst [j1] x1:(MOVBZload [i1] {s} p mem))
+ y))
+ && i1 == i0+1
+ && j1 == j0-8
+ && j1 % 16 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (ORW <v.Type> (SLWconst <v.Type> [j1] (MOVHZload [i0] {s} p mem)) y)
+
+(OR
+ s0:(SLDconst [j0] x0:(MOVBZload [i0] {s} p mem))
+ or:(OR
+ s1:(SLDconst [j1] x1:(MOVBZload [i1] {s} p mem))
+ y))
+ && i1 == i0+1
+ && j1 == j0-8
+ && j1 % 16 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVHZload [i0] {s} p mem)) y)
+
+(OR
+ s0:(SLDconst [j0] x0:(MOVHZload [i0] {s} p mem))
+ or:(OR
+ s1:(SLDconst [j1] x1:(MOVHZload [i1] {s} p mem))
+ y))
+ && i1 == i0+2
+ && j1 == j0-16
+ && j1 % 32 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVWZload [i0] {s} p mem)) y)
+
+// Little-endian loads
+
+(ORW x0:(MOVBZload [i0] {s} p mem)
+ sh:(SLWconst [8] x1:(MOVBZload [i1] {s} p mem)))
+ && p.Op != OpSB
+ && i1 == i0+1
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVHZreg (MOVHBRload [i0] {s} p mem))
+
+(OR x0:(MOVBZload [i0] {s} p mem)
+ sh:(SLDconst [8] x1:(MOVBZload [i1] {s} p mem)))
+ && p.Op != OpSB
+ && i1 == i0+1
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, sh)
+ => @mergePoint(b,x0,x1) (MOVHZreg (MOVHBRload [i0] {s} p mem))
+
+(ORW r0:(MOVHZreg x0:(MOVHBRload [i0] {s} p mem))
+ sh:(SLWconst [16] r1:(MOVHZreg x1:(MOVHBRload [i1] {s} p mem))))
+ && i1 == i0+2
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && r0.Uses == 1
+ && r1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, r0, r1, sh)
+ => @mergePoint(b,x0,x1) (MOVWBRload [i0] {s} p mem)
+
+(OR r0:(MOVHZreg x0:(MOVHBRload [i0] {s} p mem))
+ sh:(SLDconst [16] r1:(MOVHZreg x1:(MOVHBRload [i1] {s} p mem))))
+ && i1 == i0+2
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && r0.Uses == 1
+ && r1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, r0, r1, sh)
+ => @mergePoint(b,x0,x1) (MOVWZreg (MOVWBRload [i0] {s} p mem))
+
+(OR r0:(MOVWZreg x0:(MOVWBRload [i0] {s} p mem))
+ sh:(SLDconst [32] r1:(MOVWZreg x1:(MOVWBRload [i1] {s} p mem))))
+ && i1 == i0+4
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && r0.Uses == 1
+ && r1.Uses == 1
+ && sh.Uses == 1
+ && mergePoint(b,x0,x1) != nil
+ && clobber(x0, x1, r0, r1, sh)
+ => @mergePoint(b,x0,x1) (MOVDBRload [i0] {s} p mem)
+
+(ORW
+ s1:(SLWconst [j1] x1:(MOVBZload [i1] {s} p mem))
+ or:(ORW
+ s0:(SLWconst [j0] x0:(MOVBZload [i0] {s} p mem))
+ y))
+ && p.Op != OpSB
+ && i1 == i0+1
+ && j1 == j0+8
+ && j0 % 16 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (ORW <v.Type> (SLWconst <v.Type> [j0] (MOVHZreg (MOVHBRload [i0] {s} p mem))) y)
+
+(OR
+ s1:(SLDconst [j1] x1:(MOVBZload [i1] {s} p mem))
+ or:(OR
+ s0:(SLDconst [j0] x0:(MOVBZload [i0] {s} p mem))
+ y))
+ && p.Op != OpSB
+ && i1 == i0+1
+ && j1 == j0+8
+ && j0 % 16 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVHZreg (MOVHBRload [i0] {s} p mem))) y)
+
+(OR
+ s1:(SLDconst [j1] r1:(MOVHZreg x1:(MOVHBRload [i1] {s} p mem)))
+ or:(OR
+ s0:(SLDconst [j0] r0:(MOVHZreg x0:(MOVHBRload [i0] {s} p mem)))
+ y))
+ && i1 == i0+2
+ && j1 == j0+16
+ && j0 % 32 == 0
+ && x0.Uses == 1
+ && x1.Uses == 1
+ && r0.Uses == 1
+ && r1.Uses == 1
+ && s0.Uses == 1
+ && s1.Uses == 1
+ && or.Uses == 1
+ && mergePoint(b,x0,x1,y) != nil
+ && clobber(x0, x1, r0, r1, s0, s1, or)
+ => @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVWZreg (MOVWBRload [i0] {s} p mem))) y)
+
+// Combine stores into store multiples.
+// 32-bit
+(MOVWstore [i] {s} p w1 x:(MOVWstore [i-4] {s} p w0 mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && is20Bit(int64(i)-4)
+ && clobber(x)
+ => (STM2 [i-4] {s} p w0 w1 mem)
+(MOVWstore [i] {s} p w2 x:(STM2 [i-8] {s} p w0 w1 mem))
+ && x.Uses == 1
+ && is20Bit(int64(i)-8)
+ && clobber(x)
+ => (STM3 [i-8] {s} p w0 w1 w2 mem)
+(MOVWstore [i] {s} p w3 x:(STM3 [i-12] {s} p w0 w1 w2 mem))
+ && x.Uses == 1
+ && is20Bit(int64(i)-12)
+ && clobber(x)
+ => (STM4 [i-12] {s} p w0 w1 w2 w3 mem)
+(STM2 [i] {s} p w2 w3 x:(STM2 [i-8] {s} p w0 w1 mem))
+ && x.Uses == 1
+ && is20Bit(int64(i)-8)
+ && clobber(x)
+ => (STM4 [i-8] {s} p w0 w1 w2 w3 mem)
+// 64-bit
+(MOVDstore [i] {s} p w1 x:(MOVDstore [i-8] {s} p w0 mem))
+ && p.Op != OpSB
+ && x.Uses == 1
+ && is20Bit(int64(i)-8)
+ && clobber(x)
+ => (STMG2 [i-8] {s} p w0 w1 mem)
+(MOVDstore [i] {s} p w2 x:(STMG2 [i-16] {s} p w0 w1 mem))
+ && x.Uses == 1
+ && is20Bit(int64(i)-16)
+ && clobber(x)
+ => (STMG3 [i-16] {s} p w0 w1 w2 mem)
+(MOVDstore [i] {s} p w3 x:(STMG3 [i-24] {s} p w0 w1 w2 mem))
+ && x.Uses == 1
+ && is20Bit(int64(i)-24)
+ && clobber(x)
+ => (STMG4 [i-24] {s} p w0 w1 w2 w3 mem)
+(STMG2 [i] {s} p w2 w3 x:(STMG2 [i-16] {s} p w0 w1 mem))
+ && x.Uses == 1
+ && is20Bit(int64(i)-16)
+ && clobber(x)
+ => (STMG4 [i-16] {s} p w0 w1 w2 w3 mem)
+
+// Convert 32-bit store multiples into 64-bit stores.
+(STM2 [i] {s} p (SRDconst [32] x) x mem) => (MOVDstore [i] {s} p x mem)
diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go
new file mode 100644
index 0000000..b24fd61
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go
@@ -0,0 +1,816 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import "strings"
+
+// Notes:
+// - Integer types live in the low portion of registers. Upper portions are junk.
+// - Boolean types use the low-order byte of a register. 0=false, 1=true.
+// Upper bytes are junk.
+// - When doing sub-register operations, we try to write the whole
+// destination register to avoid a partial-register write.
+// - Unused portions of AuxInt (or the Val portion of ValAndOff) are
+// filled by sign-extending the used portion. Users of AuxInt which interpret
+// AuxInt as unsigned (e.g. shifts) must be careful.
+// - The SB 'register' is implemented using instruction-relative addressing. This
+// places some limitations on when and how memory operands that are addressed
+// relative to SB can be used:
+//
+// 1. Pseudo-instructions do not always map to a single machine instruction when
+// using the SB 'register' to address data. This is because many machine
+// instructions do not have relative long (RL suffix) equivalents. For example,
+// ADDload, which is assembled as AG.
+//
+// 2. Loads and stores using relative addressing require the data be aligned
+// according to its size (8-bytes for double words, 4-bytes for words
+// and so on).
+//
+// We can always work around these by inserting LARL instructions (load address
+// relative long) in the assembler, but typically this results in worse code
+// generation because the address can't be re-used. Inserting instructions in the
+// assembler also means clobbering the temp register and it is a long-term goal
+// to prevent the compiler doing this so that it can be allocated as a normal
+// register.
+//
+// For more information about the z/Architecture, the instruction set and the
+// addressing modes it supports take a look at the z/Architecture Principles of
+// Operation: http://publibfp.boulder.ibm.com/epubs/pdf/dz9zr010.pdf
+//
+// Suffixes encode the bit width of pseudo-instructions.
+// D (double word) = 64 bit (frequently omitted)
+// W (word) = 32 bit
+// H (half word) = 16 bit
+// B (byte) = 8 bit
+// S (single prec.) = 32 bit (double precision is omitted)
+
+// copied from ../../s390x/reg.go
+var regNamesS390X = []string{
+ "R0",
+ "R1",
+ "R2",
+ "R3",
+ "R4",
+ "R5",
+ "R6",
+ "R7",
+ "R8",
+ "R9",
+ "R10",
+ "R11",
+ "R12",
+ "g", // R13
+ "R14",
+ "SP", // R15
+ "F0",
+ "F1",
+ "F2",
+ "F3",
+ "F4",
+ "F5",
+ "F6",
+ "F7",
+ "F8",
+ "F9",
+ "F10",
+ "F11",
+ "F12",
+ "F13",
+ "F14",
+ "F15",
+
+ // If you add registers, update asyncPreempt in runtime.
+
+ //pseudo-registers
+ "SB",
+}
+
+func init() {
+ // Make map from reg names to reg integers.
+ if len(regNamesS390X) > 64 {
+ panic("too many registers")
+ }
+ num := map[string]int{}
+ for i, name := range regNamesS390X {
+ num[name] = 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 (
+ sp = buildReg("SP")
+ sb = buildReg("SB")
+ r0 = buildReg("R0")
+ tmp = buildReg("R11") // R11 is used as a temporary in a small number of instructions.
+
+ // R10 is reserved by the assembler.
+ gp = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14")
+ gpg = gp | buildReg("g")
+ gpsp = gp | sp
+
+ // R0 is considered to contain the value 0 in address calculations.
+ ptr = gp &^ r0
+ ptrsp = ptr | sp
+ ptrspsb = ptrsp | sb
+
+ fp = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15")
+ callerSave = gp | fp | buildReg("g") // runtime.setg (and anything calling it) may clobber g
+ r1 = buildReg("R1")
+ r2 = buildReg("R2")
+ r3 = buildReg("R3")
+ )
+ // Common slices of register masks
+ var (
+ gponly = []regMask{gp}
+ fponly = []regMask{fp}
+ )
+
+ // Common regInfo
+ var (
+ gp01 = regInfo{inputs: []regMask{}, outputs: gponly}
+ gp11 = regInfo{inputs: []regMask{gp}, outputs: gponly}
+ gp11sp = regInfo{inputs: []regMask{gpsp}, outputs: gponly}
+ gp21 = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
+ gp21sp = regInfo{inputs: []regMask{gpsp, gp}, outputs: gponly}
+ gp21tmp = regInfo{inputs: []regMask{gp &^ tmp, gp &^ tmp}, outputs: []regMask{gp &^ tmp}, clobbers: tmp}
+
+ // R0 evaluates to 0 when used as the number of bits to shift
+ // so we need to exclude it from that operand.
+ sh21 = regInfo{inputs: []regMask{gp, ptr}, outputs: gponly}
+
+ addr = regInfo{inputs: []regMask{sp | sb}, outputs: gponly}
+ addridx = regInfo{inputs: []regMask{sp | sb, ptrsp}, outputs: gponly}
+
+ gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}}
+ gp1flags = regInfo{inputs: []regMask{gpsp}}
+ gp2flags1 = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
+ gp11flags = regInfo{inputs: []regMask{gp}, outputs: gponly}
+ gp21flags = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
+ gp2flags1flags = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
+
+ gpload = regInfo{inputs: []regMask{ptrspsb, 0}, outputs: gponly}
+ gploadidx = regInfo{inputs: []regMask{ptrspsb, ptrsp, 0}, outputs: gponly}
+ gpopload = regInfo{inputs: []regMask{gp, ptrsp, 0}, outputs: gponly}
+ gpstore = regInfo{inputs: []regMask{ptrspsb, gpsp, 0}}
+ gpstoreconst = regInfo{inputs: []regMask{ptrspsb, 0}}
+ gpstoreidx = regInfo{inputs: []regMask{ptrsp, ptrsp, gpsp, 0}}
+ gpstorebr = regInfo{inputs: []regMask{ptrsp, gpsp, 0}}
+ gpstorelaa = regInfo{inputs: []regMask{ptrspsb, gpsp, 0}, outputs: gponly}
+ gpstorelab = regInfo{inputs: []regMask{r1, gpsp, 0}, clobbers: r1}
+
+ gpmvc = regInfo{inputs: []regMask{ptrsp, ptrsp, 0}}
+
+ fp01 = regInfo{inputs: []regMask{}, outputs: fponly}
+ fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly}
+ fp31 = regInfo{inputs: []regMask{fp, fp, fp}, outputs: fponly}
+ fp21clobber = regInfo{inputs: []regMask{fp, fp}, outputs: fponly}
+ fpgp = regInfo{inputs: fponly, outputs: gponly}
+ gpfp = regInfo{inputs: gponly, outputs: fponly}
+ fp11 = regInfo{inputs: fponly, outputs: fponly}
+ fp1flags = regInfo{inputs: []regMask{fp}}
+ fp11clobber = regInfo{inputs: fponly, outputs: fponly}
+ fp2flags = regInfo{inputs: []regMask{fp, fp}}
+
+ fpload = regInfo{inputs: []regMask{ptrspsb, 0}, outputs: fponly}
+ fploadidx = regInfo{inputs: []regMask{ptrsp, ptrsp, 0}, outputs: fponly}
+
+ fpstore = regInfo{inputs: []regMask{ptrspsb, fp, 0}}
+ fpstoreidx = regInfo{inputs: []regMask{ptrsp, ptrsp, fp, 0}}
+
+ sync = regInfo{inputs: []regMask{0}}
+
+ // LoweredAtomicCas may overwrite arg1, so force it to R0 for now.
+ cas = regInfo{inputs: []regMask{ptrsp, r0, gpsp, 0}, outputs: []regMask{gp, 0}, clobbers: r0}
+
+ // LoweredAtomicExchange overwrites the output before executing
+ // CS{,G}, so the output register must not be the same as the
+ // input register. For now we just force the output register to
+ // R0.
+ exchange = regInfo{inputs: []regMask{ptrsp, gpsp &^ r0, 0}, outputs: []regMask{r0, 0}}
+ )
+
+ var S390Xops = []opData{
+ // fp ops
+ {name: "FADDS", argLength: 2, reg: fp21clobber, typ: "(Float32,Flags)", asm: "FADDS", commutative: true, resultInArg0: true}, // fp32 arg0 + arg1
+ {name: "FADD", argLength: 2, reg: fp21clobber, typ: "(Float64,Flags)", asm: "FADD", commutative: true, resultInArg0: true}, // fp64 arg0 + arg1
+ {name: "FSUBS", argLength: 2, reg: fp21clobber, typ: "(Float32,Flags)", asm: "FSUBS", resultInArg0: true}, // fp32 arg0 - arg1
+ {name: "FSUB", argLength: 2, reg: fp21clobber, typ: "(Float64,Flags)", asm: "FSUB", resultInArg0: true}, // fp64 arg0 - arg1
+ {name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true, resultInArg0: true}, // fp32 arg0 * arg1
+ {name: "FMUL", argLength: 2, reg: fp21, asm: "FMUL", commutative: true, resultInArg0: true}, // fp64 arg0 * arg1
+ {name: "FDIVS", argLength: 2, reg: fp21, asm: "FDIVS", resultInArg0: true}, // fp32 arg0 / arg1
+ {name: "FDIV", argLength: 2, reg: fp21, asm: "FDIV", resultInArg0: true}, // fp64 arg0 / arg1
+ {name: "FNEGS", argLength: 1, reg: fp11clobber, asm: "FNEGS", clobberFlags: true}, // fp32 -arg0
+ {name: "FNEG", argLength: 1, reg: fp11clobber, asm: "FNEG", clobberFlags: true}, // fp64 -arg0
+ {name: "FMADDS", argLength: 3, reg: fp31, asm: "FMADDS", resultInArg0: true}, // fp32 arg1 * arg2 + arg0
+ {name: "FMADD", argLength: 3, reg: fp31, asm: "FMADD", resultInArg0: true}, // fp64 arg1 * arg2 + arg0
+ {name: "FMSUBS", argLength: 3, reg: fp31, asm: "FMSUBS", resultInArg0: true}, // fp32 arg1 * arg2 - arg0
+ {name: "FMSUB", argLength: 3, reg: fp31, asm: "FMSUB", resultInArg0: true}, // fp64 arg1 * arg2 - arg0
+ {name: "LPDFR", argLength: 1, reg: fp11, asm: "LPDFR"}, // fp64/fp32 set sign bit
+ {name: "LNDFR", argLength: 1, reg: fp11, asm: "LNDFR"}, // fp64/fp32 clear sign bit
+ {name: "CPSDR", argLength: 2, reg: fp21, asm: "CPSDR"}, // fp64/fp32 copy arg1 sign bit to arg0
+
+ // Round to integer, float64 only.
+ //
+ // aux | rounding mode
+ // ----+-----------------------------------
+ // 1 | round to nearest, ties away from 0
+ // 4 | round to nearest, ties to even
+ // 5 | round toward 0
+ // 6 | round toward +∞
+ // 7 | round toward -∞
+ {name: "FIDBR", argLength: 1, reg: fp11, asm: "FIDBR", aux: "Int8"},
+
+ {name: "FMOVSload", argLength: 2, reg: fpload, asm: "FMOVS", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // fp32 load
+ {name: "FMOVDload", argLength: 2, reg: fpload, asm: "FMOVD", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // fp64 load
+ {name: "FMOVSconst", reg: fp01, asm: "FMOVS", aux: "Float32", rematerializeable: true}, // fp32 constant
+ {name: "FMOVDconst", reg: fp01, asm: "FMOVD", aux: "Float64", rematerializeable: true}, // fp64 constant
+ {name: "FMOVSloadidx", argLength: 3, reg: fploadidx, asm: "FMOVS", aux: "SymOff", symEffect: "Read"}, // fp32 load indexed by i
+ {name: "FMOVDloadidx", argLength: 3, reg: fploadidx, asm: "FMOVD", aux: "SymOff", symEffect: "Read"}, // fp64 load indexed by i
+
+ {name: "FMOVSstore", argLength: 3, reg: fpstore, asm: "FMOVS", aux: "SymOff", faultOnNilArg0: true, symEffect: "Write"}, // fp32 store
+ {name: "FMOVDstore", argLength: 3, reg: fpstore, asm: "FMOVD", aux: "SymOff", faultOnNilArg0: true, symEffect: "Write"}, // fp64 store
+ {name: "FMOVSstoreidx", argLength: 4, reg: fpstoreidx, asm: "FMOVS", aux: "SymOff", symEffect: "Write"}, // fp32 indexed by i store
+ {name: "FMOVDstoreidx", argLength: 4, reg: fpstoreidx, asm: "FMOVD", aux: "SymOff", symEffect: "Write"}, // fp64 indexed by i store
+
+ // binary ops
+ {name: "ADD", argLength: 2, reg: gp21sp, asm: "ADD", commutative: true, clobberFlags: true}, // arg0 + arg1
+ {name: "ADDW", argLength: 2, reg: gp21sp, asm: "ADDW", commutative: true, clobberFlags: true}, // arg0 + arg1
+ {name: "ADDconst", argLength: 1, reg: gp11sp, asm: "ADD", aux: "Int32", typ: "UInt64", clobberFlags: true}, // arg0 + auxint
+ {name: "ADDWconst", argLength: 1, reg: gp11sp, asm: "ADDW", aux: "Int32", clobberFlags: true}, // arg0 + auxint
+ {name: "ADDload", argLength: 3, reg: gpopload, asm: "ADD", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 + *arg1. arg2=mem
+ {name: "ADDWload", argLength: 3, reg: gpopload, asm: "ADDW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 + *arg1. arg2=mem
+
+ {name: "SUB", argLength: 2, reg: gp21, asm: "SUB", clobberFlags: true}, // arg0 - arg1
+ {name: "SUBW", argLength: 2, reg: gp21, asm: "SUBW", clobberFlags: true}, // arg0 - arg1
+ {name: "SUBconst", argLength: 1, reg: gp11, asm: "SUB", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 - auxint
+ {name: "SUBWconst", argLength: 1, reg: gp11, asm: "SUBW", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 - auxint
+ {name: "SUBload", argLength: 3, reg: gpopload, asm: "SUB", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 - *arg1. arg2=mem
+ {name: "SUBWload", argLength: 3, reg: gpopload, asm: "SUBW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 - *arg1. arg2=mem
+
+ {name: "MULLD", argLength: 2, reg: gp21, asm: "MULLD", typ: "Int64", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 * arg1
+ {name: "MULLW", argLength: 2, reg: gp21, asm: "MULLW", typ: "Int32", commutative: true, resultInArg0: true, clobberFlags: true}, // arg0 * arg1
+ {name: "MULLDconst", argLength: 1, reg: gp11, asm: "MULLD", aux: "Int32", typ: "Int64", resultInArg0: true, clobberFlags: true}, // arg0 * auxint
+ {name: "MULLWconst", argLength: 1, reg: gp11, asm: "MULLW", aux: "Int32", typ: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 * auxint
+ {name: "MULLDload", argLength: 3, reg: gpopload, asm: "MULLD", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 * *arg1. arg2=mem
+ {name: "MULLWload", argLength: 3, reg: gpopload, asm: "MULLW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 * *arg1. arg2=mem
+
+ {name: "MULHD", argLength: 2, reg: gp21tmp, asm: "MULHD", typ: "Int64", commutative: true, resultInArg0: true, clobberFlags: true}, // (arg0 * arg1) >> width
+ {name: "MULHDU", argLength: 2, reg: gp21tmp, asm: "MULHDU", typ: "Int64", commutative: true, resultInArg0: true, clobberFlags: true}, // (arg0 * arg1) >> width
+
+ {name: "DIVD", argLength: 2, reg: gp21tmp, asm: "DIVD", resultInArg0: true, clobberFlags: true}, // arg0 / arg1
+ {name: "DIVW", argLength: 2, reg: gp21tmp, asm: "DIVW", resultInArg0: true, clobberFlags: true}, // arg0 / arg1
+ {name: "DIVDU", argLength: 2, reg: gp21tmp, asm: "DIVDU", resultInArg0: true, clobberFlags: true}, // arg0 / arg1
+ {name: "DIVWU", argLength: 2, reg: gp21tmp, asm: "DIVWU", resultInArg0: true, clobberFlags: true}, // arg0 / arg1
+
+ {name: "MODD", argLength: 2, reg: gp21tmp, asm: "MODD", resultInArg0: true, clobberFlags: true}, // arg0 % arg1
+ {name: "MODW", argLength: 2, reg: gp21tmp, asm: "MODW", resultInArg0: true, clobberFlags: true}, // arg0 % arg1
+
+ {name: "MODDU", argLength: 2, reg: gp21tmp, asm: "MODDU", resultInArg0: true, clobberFlags: true}, // arg0 % arg1
+ {name: "MODWU", argLength: 2, reg: gp21tmp, asm: "MODWU", resultInArg0: true, clobberFlags: true}, // arg0 % arg1
+
+ {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true, clobberFlags: true}, // arg0 & arg1
+ {name: "ANDW", argLength: 2, reg: gp21, asm: "ANDW", commutative: true, clobberFlags: true}, // arg0 & arg1
+ {name: "ANDconst", argLength: 1, reg: gp11, asm: "AND", aux: "Int64", resultInArg0: true, clobberFlags: true}, // arg0 & auxint
+ {name: "ANDWconst", argLength: 1, reg: gp11, asm: "ANDW", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 & auxint
+ {name: "ANDload", argLength: 3, reg: gpopload, asm: "AND", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 & *arg1. arg2=mem
+ {name: "ANDWload", argLength: 3, reg: gpopload, asm: "ANDW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 & *arg1. arg2=mem
+
+ {name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true, clobberFlags: true}, // arg0 | arg1
+ {name: "ORW", argLength: 2, reg: gp21, asm: "ORW", commutative: true, clobberFlags: true}, // arg0 | arg1
+ {name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int64", resultInArg0: true, clobberFlags: true}, // arg0 | auxint
+ {name: "ORWconst", argLength: 1, reg: gp11, asm: "ORW", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 | auxint
+ {name: "ORload", argLength: 3, reg: gpopload, asm: "OR", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 | *arg1. arg2=mem
+ {name: "ORWload", argLength: 3, reg: gpopload, asm: "ORW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 | *arg1. arg2=mem
+
+ {name: "XOR", argLength: 2, reg: gp21, asm: "XOR", commutative: true, clobberFlags: true}, // arg0 ^ arg1
+ {name: "XORW", argLength: 2, reg: gp21, asm: "XORW", commutative: true, clobberFlags: true}, // arg0 ^ arg1
+ {name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64", resultInArg0: true, clobberFlags: true}, // arg0 ^ auxint
+ {name: "XORWconst", argLength: 1, reg: gp11, asm: "XORW", aux: "Int32", resultInArg0: true, clobberFlags: true}, // arg0 ^ auxint
+ {name: "XORload", argLength: 3, reg: gpopload, asm: "XOR", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 ^ *arg1. arg2=mem
+ {name: "XORWload", argLength: 3, reg: gpopload, asm: "XORW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 ^ *arg1. arg2=mem
+
+ // Arithmetic ops with carry/borrow chain.
+ //
+ // A carry is represented by a condition code of 2 or 3 (GT or OV).
+ // A borrow is represented by a condition code of 0 or 1 (EQ or LT).
+ {name: "ADDC", argLength: 2, reg: gp21flags, asm: "ADDC", typ: "(UInt64,Flags)", commutative: true}, // (arg0 + arg1, carry out)
+ {name: "ADDCconst", argLength: 1, reg: gp11flags, asm: "ADDC", typ: "(UInt64,Flags)", aux: "Int16"}, // (arg0 + auxint, carry out)
+ {name: "ADDE", argLength: 3, reg: gp2flags1flags, asm: "ADDE", typ: "(UInt64,Flags)", commutative: true, resultInArg0: true}, // (arg0 + arg1 + arg2 (carry in), carry out)
+ {name: "SUBC", argLength: 2, reg: gp21flags, asm: "SUBC", typ: "(UInt64,Flags)"}, // (arg0 - arg1, borrow out)
+ {name: "SUBE", argLength: 3, reg: gp2flags1flags, asm: "SUBE", typ: "(UInt64,Flags)", resultInArg0: true}, // (arg0 - arg1 - arg2 (borrow in), borrow out)
+
+ // Comparisons.
+ {name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1
+
+ {name: "CMPU", argLength: 2, reg: gp2flags, asm: "CMPU", typ: "Flags"}, // arg0 compare to arg1
+ {name: "CMPWU", argLength: 2, reg: gp2flags, asm: "CMPWU", typ: "Flags"}, // arg0 compare to arg1
+
+ {name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", typ: "Flags", aux: "Int32"}, // arg0 compare to auxint
+ {name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", typ: "Flags", aux: "Int32"}, // arg0 compare to auxint
+ {name: "CMPUconst", argLength: 1, reg: gp1flags, asm: "CMPU", typ: "Flags", aux: "Int32"}, // arg0 compare to auxint
+ {name: "CMPWUconst", argLength: 1, reg: gp1flags, asm: "CMPWU", typ: "Flags", aux: "Int32"}, // arg0 compare to auxint
+
+ {name: "FCMPS", argLength: 2, reg: fp2flags, asm: "CEBR", typ: "Flags"}, // arg0 compare to arg1, f32
+ {name: "FCMP", argLength: 2, reg: fp2flags, asm: "FCMPU", typ: "Flags"}, // arg0 compare to arg1, f64
+ {name: "LTDBR", argLength: 1, reg: fp1flags, asm: "LTDBR", typ: "Flags"}, // arg0 compare to 0, f64
+ {name: "LTEBR", argLength: 1, reg: fp1flags, asm: "LTEBR", typ: "Flags"}, // arg0 compare to 0, f32
+
+ {name: "SLD", argLength: 2, reg: sh21, asm: "SLD"}, // arg0 << arg1, shift amount is mod 64
+ {name: "SLW", argLength: 2, reg: sh21, asm: "SLW"}, // arg0 << arg1, shift amount is mod 64
+ {name: "SLDconst", argLength: 1, reg: gp11, asm: "SLD", aux: "UInt8"}, // arg0 << auxint, shift amount 0-63
+ {name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "UInt8"}, // arg0 << auxint, shift amount 0-31
+
+ {name: "SRD", argLength: 2, reg: sh21, asm: "SRD"}, // unsigned arg0 >> arg1, shift amount is mod 64
+ {name: "SRW", argLength: 2, reg: sh21, asm: "SRW"}, // unsigned uint32(arg0) >> arg1, shift amount is mod 64
+ {name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "UInt8"}, // unsigned arg0 >> auxint, shift amount 0-63
+ {name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "UInt8"}, // unsigned uint32(arg0) >> auxint, shift amount 0-31
+
+ // Arithmetic shifts clobber flags.
+ {name: "SRAD", argLength: 2, reg: sh21, asm: "SRAD", clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 64
+ {name: "SRAW", argLength: 2, reg: sh21, asm: "SRAW", clobberFlags: true}, // signed int32(arg0) >> arg1, shift amount is mod 64
+ {name: "SRADconst", argLength: 1, reg: gp11, asm: "SRAD", aux: "UInt8", clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-63
+ {name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "UInt8", clobberFlags: true}, // signed int32(arg0) >> auxint, shift amount 0-31
+
+ // Rotate instructions.
+ // Note: no RLLGconst - use RISBGZ instead.
+ {name: "RLLG", argLength: 2, reg: sh21, asm: "RLLG"}, // arg0 rotate left arg1, rotate amount 0-63
+ {name: "RLL", argLength: 2, reg: sh21, asm: "RLL"}, // arg0 rotate left arg1, rotate amount 0-31
+ {name: "RLLconst", argLength: 1, reg: gp11, asm: "RLL", aux: "UInt8"}, // arg0 rotate left auxint, rotate amount 0-31
+
+ // Rotate then (and|or|xor|insert) selected bits instructions.
+ //
+ // Aux is an s390x.RotateParams struct containing Start, End and rotation
+ // Amount fields.
+ //
+ // arg1 is rotated left by the rotation amount then the bits from the start
+ // bit to the end bit (inclusive) are combined with arg0 using the logical
+ // operation specified. Bit indices are specified from left to right - the
+ // MSB is 0 and the LSB is 63.
+ //
+ // Examples:
+ // | aux |
+ // | instruction | start | end | amount | arg0 | arg1 | result |
+ // +-------------+-------+-----+--------+-----------------------+-----------------------+-----------------------+
+ // | RXSBG (XOR) | 0 | 1 | 0 | 0xffff_ffff_ffff_ffff | 0xffff_ffff_ffff_ffff | 0x3fff_ffff_ffff_ffff |
+ // | RXSBG (XOR) | 62 | 63 | 0 | 0xffff_ffff_ffff_ffff | 0xffff_ffff_ffff_ffff | 0xffff_ffff_ffff_fffc |
+ // | RXSBG (XOR) | 0 | 47 | 16 | 0xffff_ffff_ffff_ffff | 0x0000_0000_0000_ffff | 0xffff_ffff_0000_ffff |
+ // +-------------+-------+-----+--------+-----------------------+-----------------------+-----------------------+
+ //
+ {name: "RXSBG", argLength: 2, reg: gp21, asm: "RXSBG", resultInArg0: true, aux: "S390XRotateParams", clobberFlags: true}, // rotate then xor selected bits
+ {name: "RISBGZ", argLength: 1, reg: gp11, asm: "RISBGZ", aux: "S390XRotateParams", clobberFlags: true}, // rotate then insert selected bits [into zero]
+
+ // unary ops
+ {name: "NEG", argLength: 1, reg: gp11, asm: "NEG", clobberFlags: true}, // -arg0
+ {name: "NEGW", argLength: 1, reg: gp11, asm: "NEGW", clobberFlags: true}, // -arg0
+
+ {name: "NOT", argLength: 1, reg: gp11, resultInArg0: true, clobberFlags: true}, // ^arg0
+ {name: "NOTW", argLength: 1, reg: gp11, resultInArg0: true, clobberFlags: true}, // ^arg0
+
+ {name: "FSQRT", argLength: 1, reg: fp11, asm: "FSQRT"}, // sqrt(arg0)
+
+ // Conditional register-register moves.
+ // The aux for these values is an s390x.CCMask value representing the condition code mask.
+ {name: "LOCGR", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "LOCGR", aux: "S390XCCMask"}, // load arg1 into arg0 if the condition code in arg2 matches a masked bit in aux.
+
+ {name: "MOVBreg", argLength: 1, reg: gp11sp, asm: "MOVB", typ: "Int64"}, // sign extend arg0 from int8 to int64
+ {name: "MOVBZreg", argLength: 1, reg: gp11sp, asm: "MOVBZ", typ: "UInt64"}, // zero extend arg0 from int8 to int64
+ {name: "MOVHreg", argLength: 1, reg: gp11sp, asm: "MOVH", typ: "Int64"}, // sign extend arg0 from int16 to int64
+ {name: "MOVHZreg", argLength: 1, reg: gp11sp, asm: "MOVHZ", typ: "UInt64"}, // zero extend arg0 from int16 to int64
+ {name: "MOVWreg", argLength: 1, reg: gp11sp, asm: "MOVW", typ: "Int64"}, // sign extend arg0 from int32 to int64
+ {name: "MOVWZreg", argLength: 1, reg: gp11sp, asm: "MOVWZ", typ: "UInt64"}, // zero extend arg0 from int32 to int64
+
+ {name: "MOVDconst", reg: gp01, asm: "MOVD", typ: "UInt64", aux: "Int64", rematerializeable: true}, // auxint
+
+ {name: "LDGR", argLength: 1, reg: gpfp, asm: "LDGR"}, // move int64 to float64 (no conversion)
+ {name: "LGDR", argLength: 1, reg: fpgp, asm: "LGDR"}, // move float64 to int64 (no conversion)
+
+ {name: "CFDBRA", argLength: 1, reg: fpgp, asm: "CFDBRA", clobberFlags: true}, // convert float64 to int32
+ {name: "CGDBRA", argLength: 1, reg: fpgp, asm: "CGDBRA", clobberFlags: true}, // convert float64 to int64
+ {name: "CFEBRA", argLength: 1, reg: fpgp, asm: "CFEBRA", clobberFlags: true}, // convert float32 to int32
+ {name: "CGEBRA", argLength: 1, reg: fpgp, asm: "CGEBRA", clobberFlags: true}, // convert float32 to int64
+ {name: "CEFBRA", argLength: 1, reg: gpfp, asm: "CEFBRA", clobberFlags: true}, // convert int32 to float32
+ {name: "CDFBRA", argLength: 1, reg: gpfp, asm: "CDFBRA", clobberFlags: true}, // convert int32 to float64
+ {name: "CEGBRA", argLength: 1, reg: gpfp, asm: "CEGBRA", clobberFlags: true}, // convert int64 to float32
+ {name: "CDGBRA", argLength: 1, reg: gpfp, asm: "CDGBRA", clobberFlags: true}, // convert int64 to float64
+ {name: "CLFEBR", argLength: 1, reg: fpgp, asm: "CLFEBR", clobberFlags: true}, // convert float32 to uint32
+ {name: "CLFDBR", argLength: 1, reg: fpgp, asm: "CLFDBR", clobberFlags: true}, // convert float64 to uint32
+ {name: "CLGEBR", argLength: 1, reg: fpgp, asm: "CLGEBR", clobberFlags: true}, // convert float32 to uint64
+ {name: "CLGDBR", argLength: 1, reg: fpgp, asm: "CLGDBR", clobberFlags: true}, // convert float64 to uint64
+ {name: "CELFBR", argLength: 1, reg: gpfp, asm: "CELFBR", clobberFlags: true}, // convert uint32 to float32
+ {name: "CDLFBR", argLength: 1, reg: gpfp, asm: "CDLFBR", clobberFlags: true}, // convert uint32 to float64
+ {name: "CELGBR", argLength: 1, reg: gpfp, asm: "CELGBR", clobberFlags: true}, // convert uint64 to float32
+ {name: "CDLGBR", argLength: 1, reg: gpfp, asm: "CDLGBR", clobberFlags: true}, // convert uint64 to float64
+
+ {name: "LEDBR", argLength: 1, reg: fp11, asm: "LEDBR"}, // convert float64 to float32
+ {name: "LDEBR", argLength: 1, reg: fp11, asm: "LDEBR"}, // convert float32 to float64
+
+ {name: "MOVDaddr", argLength: 1, reg: addr, aux: "SymOff", rematerializeable: true, symEffect: "Read"}, // arg0 + auxint + offset encoded in aux
+ {name: "MOVDaddridx", argLength: 2, reg: addridx, aux: "SymOff", symEffect: "Read"}, // arg0 + arg1 + auxint + aux
+
+ // auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
+ {name: "MOVBZload", argLength: 2, reg: gpload, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load byte from arg0+auxint+aux. arg1=mem. Zero extend.
+ {name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVB", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
+ {name: "MOVHZload", argLength: 2, reg: gpload, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
+ {name: "MOVHload", argLength: 2, reg: gpload, asm: "MOVH", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
+ {name: "MOVWZload", argLength: 2, reg: gpload, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
+ {name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVW", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
+ {name: "MOVDload", argLength: 2, reg: gpload, asm: "MOVD", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes from arg0+auxint+aux. arg1=mem
+
+ {name: "MOVWBR", argLength: 1, reg: gp11, asm: "MOVWBR"}, // arg0 swap bytes
+ {name: "MOVDBR", argLength: 1, reg: gp11, asm: "MOVDBR"}, // arg0 swap bytes
+
+ {name: "MOVHBRload", argLength: 2, reg: gpload, asm: "MOVHBR", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Reverse bytes.
+ {name: "MOVWBRload", argLength: 2, reg: gpload, asm: "MOVWBR", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Reverse bytes.
+ {name: "MOVDBRload", argLength: 2, reg: gpload, asm: "MOVDBR", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes from arg0+auxint+aux. arg1=mem. Reverse bytes.
+
+ {name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem
+ {name: "MOVHstore", argLength: 3, reg: gpstore, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
+ {name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
+ {name: "MOVDstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem
+ {name: "MOVHBRstore", argLength: 3, reg: gpstorebr, asm: "MOVHBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem. Reverse bytes.
+ {name: "MOVWBRstore", argLength: 3, reg: gpstorebr, asm: "MOVWBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem. Reverse bytes.
+ {name: "MOVDBRstore", argLength: 3, reg: gpstorebr, asm: "MOVDBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem. Reverse bytes.
+
+ {name: "MVC", argLength: 3, reg: gpmvc, asm: "MVC", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, faultOnNilArg1: true, symEffect: "None"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size,off
+
+ // indexed loads/stores
+ {name: "MOVBZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", symEffect: "Read"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem. Zero extend.
+ {name: "MOVBloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVB", aux: "SymOff", typ: "Int8", symEffect: "Read"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem. Sign extend.
+ {name: "MOVHZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem. Zero extend.
+ {name: "MOVHloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVH", aux: "SymOff", typ: "Int16", symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem. Sign extend.
+ {name: "MOVWZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem. Zero extend.
+ {name: "MOVWloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVW", aux: "SymOff", typ: "Int32", symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem. Sign extend.
+ {name: "MOVDloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVD", aux: "SymOff", typ: "UInt64", symEffect: "Read"}, // load 8 bytes from arg0+arg1+auxint+aux. arg2=mem
+ {name: "MOVHBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVHBR", aux: "SymOff", typ: "Int16", symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem. Reverse bytes.
+ {name: "MOVWBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWBR", aux: "SymOff", typ: "Int32", symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem. Reverse bytes.
+ {name: "MOVDBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVDBR", aux: "SymOff", typ: "Int64", symEffect: "Read"}, // load 8 bytes from arg0+arg1+auxint+aux. arg2=mem. Reverse bytes.
+ {name: "MOVBstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVB", aux: "SymOff", symEffect: "Write"}, // store byte in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVHstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVH", aux: "SymOff", symEffect: "Write"}, // store 2 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVWstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVW", aux: "SymOff", symEffect: "Write"}, // store 4 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVDstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVD", aux: "SymOff", symEffect: "Write"}, // store 8 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
+ {name: "MOVHBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVHBR", aux: "SymOff", symEffect: "Write"}, // store 2 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem. Reverse bytes.
+ {name: "MOVWBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVWBR", aux: "SymOff", symEffect: "Write"}, // store 4 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem. Reverse bytes.
+ {name: "MOVDBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVDBR", aux: "SymOff", symEffect: "Write"}, // store 8 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem. Reverse bytes.
+
+ // For storeconst ops, the AuxInt field encodes both
+ // the value to store and an address offset of the store.
+ // Cast AuxInt to a ValAndOff to extract Val and Off fields.
+ {name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem
+ {name: "MOVHstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVH", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 2 bytes of ...
+ {name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 4 bytes of ...
+ {name: "MOVDstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVD", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of ...
+
+ {name: "CLEAR", argLength: 2, reg: regInfo{inputs: []regMask{ptr, 0}}, asm: "CLEAR", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"},
+
+ {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
+ {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{ptrsp, buildReg("R12"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
+ {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{ptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
+
+ // (InvertFlags (CMP a b)) == (CMP b a)
+ // InvertFlags is a pseudo-op which can't appear in assembly output.
+ {name: "InvertFlags", argLength: 1}, // reverse direction of arg0
+
+ // Pseudo-ops
+ {name: "LoweredGetG", argLength: 1, reg: gp01}, // arg0=mem
+ // Scheduler ensures LoweredGetClosurePtr occurs only in entry block,
+ // and sorts it to the very beginning of the block to prevent other
+ // use of R12 (the closure pointer)
+ {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R12")}}, zeroWidth: true},
+ // arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
+ // LoweredGetCallerSP returns the SP of the caller of the current function.
+ {name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
+ // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+ // I.e., if f calls g "calls" getcallerpc,
+ // the result should be the PC within f that g will return to.
+ // See runtime/stubs.go for a more detailed discussion.
+ {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
+ {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{ptrsp}}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
+ // Round ops to block fused-multiply-add extraction.
+ {name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
+ {name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
+
+ // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+ // It saves all GP registers if necessary,
+ // but clobbers R14 (LR) because it's a call.
+ {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R14")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
+
+ // There are three of these functions so that they can have three different register inputs.
+ // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
+ // default registers to match so we don't need to copy registers around unnecessarily.
+ {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
+ {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
+ {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r0, r1}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
+
+ // Constant condition code values. The condition code can be 0, 1, 2 or 3.
+ {name: "FlagEQ"}, // CC=0 (equal)
+ {name: "FlagLT"}, // CC=1 (less than)
+ {name: "FlagGT"}, // CC=2 (greater than)
+ {name: "FlagOV"}, // CC=3 (overflow)
+
+ // Fast-BCR-serialization to ensure store-load ordering.
+ {name: "SYNC", argLength: 1, reg: sync, asm: "SYNC", typ: "Mem"},
+
+ // Atomic loads. These are just normal loads but return <value,memory> tuples
+ // so they can be properly ordered with other loads.
+ // load from arg0+auxint+aux. arg1=mem.
+ {name: "MOVBZatomicload", argLength: 2, reg: gpload, asm: "MOVBZ", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},
+ {name: "MOVWZatomicload", argLength: 2, reg: gpload, asm: "MOVWZ", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},
+ {name: "MOVDatomicload", argLength: 2, reg: gpload, asm: "MOVD", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},
+
+ // Atomic stores. These are just normal stores.
+ // store arg1 to arg0+auxint+aux. arg2=mem.
+ {name: "MOVBatomicstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"},
+ {name: "MOVWatomicstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"},
+ {name: "MOVDatomicstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"},
+
+ // Atomic adds.
+ // *(arg0+auxint+aux) += arg1. arg2=mem.
+ // Returns a tuple of <old contents of *(arg0+auxint+aux), memory>.
+ {name: "LAA", argLength: 3, reg: gpstorelaa, asm: "LAA", typ: "(UInt32,Mem)", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
+ {name: "LAAG", argLength: 3, reg: gpstorelaa, asm: "LAAG", typ: "(UInt64,Mem)", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
+ {name: "AddTupleFirst32", argLength: 2}, // arg1=tuple <x,y>. Returns <x+arg0,y>.
+ {name: "AddTupleFirst64", argLength: 2}, // arg1=tuple <x,y>. Returns <x+arg0,y>.
+
+ // Atomic bitwise operations.
+ // Note: 'floor' operations round the pointer down to the nearest word boundary
+ // which reflects how they are used in the runtime.
+ {name: "LAN", argLength: 3, reg: gpstore, asm: "LAN", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *arg0 &= arg1. arg2 = mem.
+ {name: "LANfloor", argLength: 3, reg: gpstorelab, asm: "LAN", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *(floor(arg0, 4)) &= arg1. arg2 = mem.
+ {name: "LAO", argLength: 3, reg: gpstore, asm: "LAO", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *arg0 |= arg1. arg2 = mem.
+ {name: "LAOfloor", argLength: 3, reg: gpstorelab, asm: "LAO", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *(floor(arg0, 4)) |= arg1. arg2 = mem.
+
+ // Compare and swap.
+ // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory.
+ // if *(arg0+auxint+aux) == arg1 {
+ // *(arg0+auxint+aux) = arg2
+ // return (true, memory)
+ // } else {
+ // return (false, memory)
+ // }
+ // Note that these instructions also return the old value in arg1, but we ignore it.
+ // TODO: have these return flags instead of bool. The current system generates:
+ // CS ...
+ // MOVD $0, ret
+ // BNE 2(PC)
+ // MOVD $1, ret
+ // CMPW ret, $0
+ // BNE ...
+ // instead of just
+ // CS ...
+ // BEQ ...
+ // but we can't do that because memory-using ops can't generate flags yet
+ // (flagalloc wants to move flag-generating instructions around).
+ {name: "LoweredAtomicCas32", argLength: 4, reg: cas, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
+ {name: "LoweredAtomicCas64", argLength: 4, reg: cas, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
+
+ // Lowered atomic swaps, emulated using compare-and-swap.
+ // store arg1 to arg0+auxint+aux, arg2=mem.
+ {name: "LoweredAtomicExchange32", argLength: 3, reg: exchange, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
+ {name: "LoweredAtomicExchange64", argLength: 3, reg: exchange, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
+
+ // find leftmost one
+ {
+ name: "FLOGR",
+ argLength: 1,
+ reg: regInfo{inputs: gponly, outputs: []regMask{buildReg("R0")}, clobbers: buildReg("R1")},
+ asm: "FLOGR",
+ typ: "UInt64",
+ clobberFlags: true,
+ },
+
+ // population count
+ //
+ // Counts the number of ones in each byte of arg0
+ // and places the result into the corresponding byte
+ // of the result.
+ {
+ name: "POPCNT",
+ argLength: 1,
+ reg: gp11,
+ asm: "POPCNT",
+ typ: "UInt64",
+ clobberFlags: true,
+ },
+
+ // unsigned multiplication (64x64 → 128)
+ //
+ // Multiply the two 64-bit input operands together and place the 128-bit result into
+ // an even-odd register pair. The second register in the target pair also contains
+ // one of the input operands. Since we don't currently have a way to specify an
+ // even-odd register pair we hardcode this register pair as R2:R3.
+ {
+ name: "MLGR",
+ argLength: 2,
+ reg: regInfo{inputs: []regMask{gp, r3}, outputs: []regMask{r2, r3}},
+ asm: "MLGR",
+ },
+
+ // pseudo operations to sum the output of the POPCNT instruction
+ {name: "SumBytes2", argLength: 1, typ: "UInt8"}, // sum the rightmost 2 bytes in arg0 ignoring overflow
+ {name: "SumBytes4", argLength: 1, typ: "UInt8"}, // sum the rightmost 4 bytes in arg0 ignoring overflow
+ {name: "SumBytes8", argLength: 1, typ: "UInt8"}, // sum all the bytes in arg0 ignoring overflow
+
+ // store multiple
+ {
+ name: "STMG2",
+ argLength: 4,
+ reg: regInfo{inputs: []regMask{ptrsp, buildReg("R1"), buildReg("R2"), 0}},
+ aux: "SymOff",
+ typ: "Mem",
+ asm: "STMG",
+ faultOnNilArg0: true,
+ symEffect: "Write",
+ clobberFlags: true, // TODO(mundaym): currently uses AGFI to handle large offsets
+ },
+ {
+ name: "STMG3",
+ argLength: 5,
+ reg: regInfo{inputs: []regMask{ptrsp, buildReg("R1"), buildReg("R2"), buildReg("R3"), 0}},
+ aux: "SymOff",
+ typ: "Mem",
+ asm: "STMG",
+ faultOnNilArg0: true,
+ symEffect: "Write",
+ clobberFlags: true, // TODO(mundaym): currently uses AGFI to handle large offsets
+ },
+ {
+ name: "STMG4",
+ argLength: 6,
+ reg: regInfo{inputs: []regMask{
+ ptrsp,
+ buildReg("R1"),
+ buildReg("R2"),
+ buildReg("R3"),
+ buildReg("R4"),
+ 0,
+ }},
+ aux: "SymOff",
+ typ: "Mem",
+ asm: "STMG",
+ faultOnNilArg0: true,
+ symEffect: "Write",
+ clobberFlags: true, // TODO(mundaym): currently uses AGFI to handle large offsets
+ },
+ {
+ name: "STM2",
+ argLength: 4,
+ reg: regInfo{inputs: []regMask{ptrsp, buildReg("R1"), buildReg("R2"), 0}},
+ aux: "SymOff",
+ typ: "Mem",
+ asm: "STMY",
+ faultOnNilArg0: true,
+ symEffect: "Write",
+ clobberFlags: true, // TODO(mundaym): currently uses AGFI to handle large offsets
+ },
+ {
+ name: "STM3",
+ argLength: 5,
+ reg: regInfo{inputs: []regMask{ptrsp, buildReg("R1"), buildReg("R2"), buildReg("R3"), 0}},
+ aux: "SymOff",
+ typ: "Mem",
+ asm: "STMY",
+ faultOnNilArg0: true,
+ symEffect: "Write",
+ clobberFlags: true, // TODO(mundaym): currently uses AGFI to handle large offsets
+ },
+ {
+ name: "STM4",
+ argLength: 6,
+ reg: regInfo{inputs: []regMask{
+ ptrsp,
+ buildReg("R1"),
+ buildReg("R2"),
+ buildReg("R3"),
+ buildReg("R4"),
+ 0,
+ }},
+ aux: "SymOff",
+ typ: "Mem",
+ asm: "STMY",
+ faultOnNilArg0: true,
+ symEffect: "Write",
+ clobberFlags: true, // TODO(mundaym): currently uses AGFI to handle large offsets
+ },
+
+ // large move
+ // auxint = remaining bytes after loop (rem)
+ // arg0 = address of dst memory (in R1, changed as a side effect)
+ // arg1 = address of src memory (in R2, changed as a side effect)
+ // arg2 = pointer to last address to move in loop + 256
+ // arg3 = mem
+ // returns mem
+ //
+ // mvc: MVC $256, 0(R2), 0(R1)
+ // MOVD $256(R1), R1
+ // MOVD $256(R2), R2
+ // CMP R2, Rarg2
+ // BNE mvc
+ // MVC $rem, 0(R2), 0(R1) // if rem > 0
+ {
+ name: "LoweredMove",
+ aux: "Int64",
+ argLength: 4,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R1"), buildReg("R2"), gpsp},
+ clobbers: buildReg("R1 R2"),
+ },
+ clobberFlags: true,
+ typ: "Mem",
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ },
+
+ // large clear
+ // auxint = remaining bytes after loop (rem)
+ // arg0 = address of dst memory (in R1, changed as a side effect)
+ // arg1 = pointer to last address to zero in loop + 256
+ // arg2 = mem
+ // returns mem
+ //
+ // clear: CLEAR $256, 0(R1)
+ // MOVD $256(R1), R1
+ // CMP R1, Rarg2
+ // BNE clear
+ // CLEAR $rem, 0(R1) // if rem > 0
+ {
+ name: "LoweredZero",
+ aux: "Int64",
+ argLength: 3,
+ reg: regInfo{
+ inputs: []regMask{buildReg("R1"), gpsp},
+ clobbers: buildReg("R1"),
+ },
+ clobberFlags: true,
+ typ: "Mem",
+ faultOnNilArg0: true,
+ },
+ }
+
+ // All blocks on s390x have their condition code mask (s390x.CCMask) as the Aux value.
+ // The condition code mask is a 4-bit mask where each bit corresponds to a condition
+ // code value. If the value of the condition code matches a bit set in the condition
+ // code mask then the first successor is executed. Otherwise the second successor is
+ // executed.
+ //
+ // | condition code value | mask bit |
+ // +----------------------+------------+
+ // | 0 (equal) | 0b1000 (8) |
+ // | 1 (less than) | 0b0100 (4) |
+ // | 2 (greater than) | 0b0010 (2) |
+ // | 3 (unordered) | 0b0001 (1) |
+ //
+ // Note: that compare-and-branch instructions must not have bit 3 (0b0001) set.
+ var S390Xblocks = []blockData{
+ // branch on condition
+ {name: "BRC", controls: 1, aux: "S390XCCMask"}, // condition code value (flags) is Controls[0]
+
+ // compare-and-branch (register-register)
+ // - integrates comparison of Controls[0] with Controls[1]
+ // - both control values must be in general purpose registers
+ {name: "CRJ", controls: 2, aux: "S390XCCMask"}, // signed 32-bit integer comparison
+ {name: "CGRJ", controls: 2, aux: "S390XCCMask"}, // signed 64-bit integer comparison
+ {name: "CLRJ", controls: 2, aux: "S390XCCMask"}, // unsigned 32-bit integer comparison
+ {name: "CLGRJ", controls: 2, aux: "S390XCCMask"}, // unsigned 64-bit integer comparison
+
+ // compare-and-branch (register-immediate)
+ // - integrates comparison of Controls[0] with AuxInt
+ // - control value must be in a general purpose register
+ // - the AuxInt value is sign-extended for signed comparisons
+ // and zero-extended for unsigned comparisons
+ {name: "CIJ", controls: 1, aux: "S390XCCMaskInt8"}, // signed 32-bit integer comparison
+ {name: "CGIJ", controls: 1, aux: "S390XCCMaskInt8"}, // signed 64-bit integer comparison
+ {name: "CLIJ", controls: 1, aux: "S390XCCMaskUint8"}, // unsigned 32-bit integer comparison
+ {name: "CLGIJ", controls: 1, aux: "S390XCCMaskUint8"}, // unsigned 64-bit integer comparison
+ }
+
+ archs = append(archs, arch{
+ name: "S390X",
+ pkg: "cmd/internal/obj/s390x",
+ genfile: "../../s390x/ssa.go",
+ ops: S390Xops,
+ blocks: S390Xblocks,
+ regnames: regNamesS390X,
+ gpregmask: gp,
+ fpregmask: fp,
+ framepointerreg: -1, // not used
+ linkreg: int8(num["R14"]),
+ imports: []string{
+ "cmd/internal/obj/s390x",
+ },
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/Wasm.rules b/src/cmd/compile/internal/ssa/gen/Wasm.rules
new file mode 100644
index 0000000..fc45cd3
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/Wasm.rules
@@ -0,0 +1,408 @@
+// Copyright 2018 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.
+
+// Lowering arithmetic
+(Add(64|32|16|8|Ptr) ...) => (I64Add ...)
+(Add(64|32)F ...) => (F(64|32)Add ...)
+
+(Sub(64|32|16|8|Ptr) ...) => (I64Sub ...)
+(Sub(64|32)F ...) => (F(64|32)Sub ...)
+
+(Mul(64|32|16|8) ...) => (I64Mul ...)
+(Mul(64|32)F ...) => (F(64|32)Mul ...)
+
+(Div64 [false] x y) => (I64DivS x y)
+(Div32 [false] x y) => (I64DivS (SignExt32to64 x) (SignExt32to64 y))
+(Div16 [false] x y) => (I64DivS (SignExt16to64 x) (SignExt16to64 y))
+(Div8 x y) => (I64DivS (SignExt8to64 x) (SignExt8to64 y))
+(Div64u ...) => (I64DivU ...)
+(Div32u x y) => (I64DivU (ZeroExt32to64 x) (ZeroExt32to64 y))
+(Div16u x y) => (I64DivU (ZeroExt16to64 x) (ZeroExt16to64 y))
+(Div8u x y) => (I64DivU (ZeroExt8to64 x) (ZeroExt8to64 y))
+(Div(64|32)F ...) => (F(64|32)Div ...)
+
+(Mod64 [false] x y) => (I64RemS x y)
+(Mod32 [false] x y) => (I64RemS (SignExt32to64 x) (SignExt32to64 y))
+(Mod16 [false] x y) => (I64RemS (SignExt16to64 x) (SignExt16to64 y))
+(Mod8 x y) => (I64RemS (SignExt8to64 x) (SignExt8to64 y))
+(Mod64u ...) => (I64RemU ...)
+(Mod32u x y) => (I64RemU (ZeroExt32to64 x) (ZeroExt32to64 y))
+(Mod16u x y) => (I64RemU (ZeroExt16to64 x) (ZeroExt16to64 y))
+(Mod8u x y) => (I64RemU (ZeroExt8to64 x) (ZeroExt8to64 y))
+
+(And(64|32|16|8|B) ...) => (I64And ...)
+
+(Or(64|32|16|8|B) ...) => (I64Or ...)
+
+(Xor(64|32|16|8) ...) => (I64Xor ...)
+
+(Neg(64|32|16|8) x) => (I64Sub (I64Const [0]) x)
+(Neg(64|32)F ...) => (F(64|32)Neg ...)
+
+(Com(64|32|16|8) x) => (I64Xor x (I64Const [-1]))
+
+(Not ...) => (I64Eqz ...)
+
+// Lowering pointer arithmetic
+(OffPtr ...) => (I64AddConst ...)
+
+// Lowering extension
+// It is unnecessary to extend loads
+(SignExt32to64 x:(I64Load32S _ _)) => x
+(SignExt16to(64|32) x:(I64Load16S _ _)) => x
+(SignExt8to(64|32|16) x:(I64Load8S _ _)) => x
+(ZeroExt32to64 x:(I64Load32U _ _)) => x
+(ZeroExt16to(64|32) x:(I64Load16U _ _)) => x
+(ZeroExt8to(64|32|16) x:(I64Load8U _ _)) => x
+(SignExt32to64 x) && objabi.GOWASM.SignExt => (I64Extend32S x)
+(SignExt8to(64|32|16) x) && objabi.GOWASM.SignExt => (I64Extend8S x)
+(SignExt16to(64|32) x) && objabi.GOWASM.SignExt => (I64Extend16S x)
+(SignExt32to64 x) => (I64ShrS (I64Shl x (I64Const [32])) (I64Const [32]))
+(SignExt16to(64|32) x) => (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48]))
+(SignExt8to(64|32|16) x) => (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
+(ZeroExt32to64 x) => (I64And x (I64Const [0xffffffff]))
+(ZeroExt16to(64|32) x) => (I64And x (I64Const [0xffff]))
+(ZeroExt8to(64|32|16) x) => (I64And x (I64Const [0xff]))
+
+(Slicemask x) => (I64ShrS (I64Sub (I64Const [0]) x) (I64Const [63]))
+
+// Lowering truncation
+// Because we ignore the high parts, truncates are just copies.
+(Trunc64to(32|16|8) ...) => (Copy ...)
+(Trunc32to(16|8) ...) => (Copy ...)
+(Trunc16to8 ...) => (Copy ...)
+
+// Lowering float <=> int
+(Cvt32to(64|32)F x) => (F(64|32)ConvertI64S (SignExt32to64 x))
+(Cvt64to(64|32)F ...) => (F(64|32)ConvertI64S ...)
+(Cvt32Uto(64|32)F x) => (F(64|32)ConvertI64U (ZeroExt32to64 x))
+(Cvt64Uto(64|32)F ...) => (F(64|32)ConvertI64U ...)
+
+(Cvt32Fto32 ...) => (I64TruncSatF32S ...)
+(Cvt32Fto64 ...) => (I64TruncSatF32S ...)
+(Cvt64Fto32 ...) => (I64TruncSatF64S ...)
+(Cvt64Fto64 ...) => (I64TruncSatF64S ...)
+(Cvt32Fto32U ...) => (I64TruncSatF32U ...)
+(Cvt32Fto64U ...) => (I64TruncSatF32U ...)
+(Cvt64Fto32U ...) => (I64TruncSatF64U ...)
+(Cvt64Fto64U ...) => (I64TruncSatF64U ...)
+
+(Cvt32Fto64F ...) => (F64PromoteF32 ...)
+(Cvt64Fto32F ...) => (F32DemoteF64 ...)
+
+(CvtBoolToUint8 ...) => (Copy ...)
+
+(Round32F ...) => (Copy ...)
+(Round64F ...) => (Copy ...)
+
+// Lowering shifts
+// Unsigned shifts need to return 0 if shift amount is >= width of shifted value.
+
+(Lsh64x64 x y) && shiftIsBounded(v) => (I64Shl x y)
+(Lsh64x64 x (I64Const [c])) && uint64(c) < 64 => (I64Shl x (I64Const [c]))
+(Lsh64x64 x (I64Const [c])) && uint64(c) >= 64 => (I64Const [0])
+(Lsh64x64 x y) => (Select (I64Shl x y) (I64Const [0]) (I64LtU y (I64Const [64])))
+(Lsh64x(32|16|8) [c] x y) => (Lsh64x64 [c] x (ZeroExt(32|16|8)to64 y))
+
+(Lsh32x64 ...) => (Lsh64x64 ...)
+(Lsh32x(32|16|8) [c] x y) => (Lsh64x64 [c] x (ZeroExt(32|16|8)to64 y))
+
+(Lsh16x64 ...) => (Lsh64x64 ...)
+(Lsh16x(32|16|8) [c] x y) => (Lsh64x64 [c] x (ZeroExt(32|16|8)to64 y))
+
+(Lsh8x64 ...) => (Lsh64x64 ...)
+(Lsh8x(32|16|8) [c] x y) => (Lsh64x64 [c] x (ZeroExt(32|16|8)to64 y))
+
+(Rsh64Ux64 x y) && shiftIsBounded(v) => (I64ShrU x y)
+(Rsh64Ux64 x (I64Const [c])) && uint64(c) < 64 => (I64ShrU x (I64Const [c]))
+(Rsh64Ux64 x (I64Const [c])) && uint64(c) >= 64 => (I64Const [0])
+(Rsh64Ux64 x y) => (Select (I64ShrU x y) (I64Const [0]) (I64LtU y (I64Const [64])))
+(Rsh64Ux(32|16|8) [c] x y) => (Rsh64Ux64 [c] x (ZeroExt(32|16|8)to64 y))
+
+(Rsh32Ux64 [c] x y) => (Rsh64Ux64 [c] (ZeroExt32to64 x) y)
+(Rsh32Ux(32|16|8) [c] x y) => (Rsh64Ux64 [c] (ZeroExt32to64 x) (ZeroExt(32|16|8)to64 y))
+
+(Rsh16Ux64 [c] x y) => (Rsh64Ux64 [c] (ZeroExt16to64 x) y)
+(Rsh16Ux(32|16|8) [c] x y) => (Rsh64Ux64 [c] (ZeroExt16to64 x) (ZeroExt(32|16|8)to64 y))
+
+(Rsh8Ux64 [c] x y) => (Rsh64Ux64 [c] (ZeroExt8to64 x) y)
+(Rsh8Ux(32|16|8) [c] x y) => (Rsh64Ux64 [c] (ZeroExt8to64 x) (ZeroExt(32|16|8)to64 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 (width - 1) if the shift value is >= width.
+
+(Rsh64x64 x y) && shiftIsBounded(v) => (I64ShrS x y)
+(Rsh64x64 x (I64Const [c])) && uint64(c) < 64 => (I64ShrS x (I64Const [c]))
+(Rsh64x64 x (I64Const [c])) && uint64(c) >= 64 => (I64ShrS x (I64Const [63]))
+(Rsh64x64 x y) => (I64ShrS x (Select <typ.Int64> y (I64Const [63]) (I64LtU y (I64Const [64]))))
+(Rsh64x(32|16|8) [c] x y) => (Rsh64x64 [c] x (ZeroExt(32|16|8)to64 y))
+
+(Rsh32x64 [c] x y) => (Rsh64x64 [c] (SignExt32to64 x) y)
+(Rsh32x(32|16|8) [c] x y) => (Rsh64x64 [c] (SignExt32to64 x) (ZeroExt(32|16|8)to64 y))
+
+(Rsh16x64 [c] x y) => (Rsh64x64 [c] (SignExt16to64 x) y)
+(Rsh16x(32|16|8) [c] x y) => (Rsh64x64 [c] (SignExt16to64 x) (ZeroExt(32|16|8)to64 y))
+
+(Rsh8x64 [c] x y) => (Rsh64x64 [c] (SignExt8to64 x) y)
+(Rsh8x(32|16|8) [c] x y) => (Rsh64x64 [c] (SignExt8to64 x) (ZeroExt(32|16|8)to64 y))
+
+// Lowering rotates
+(RotateLeft8 <t> x (I64Const [c])) => (Or8 (Lsh8x64 <t> x (I64Const [c&7])) (Rsh8Ux64 <t> x (I64Const [-c&7])))
+(RotateLeft16 <t> x (I64Const [c])) => (Or16 (Lsh16x64 <t> x (I64Const [c&15])) (Rsh16Ux64 <t> x (I64Const [-c&15])))
+(RotateLeft32 ...) => (I32Rotl ...)
+(RotateLeft64 ...) => (I64Rotl ...)
+
+// Lowering comparisons
+(Less64 ...) => (I64LtS ...)
+(Less32 x y) => (I64LtS (SignExt32to64 x) (SignExt32to64 y))
+(Less16 x y) => (I64LtS (SignExt16to64 x) (SignExt16to64 y))
+(Less8 x y) => (I64LtS (SignExt8to64 x) (SignExt8to64 y))
+(Less64U ...) => (I64LtU ...)
+(Less32U x y) => (I64LtU (ZeroExt32to64 x) (ZeroExt32to64 y))
+(Less16U x y) => (I64LtU (ZeroExt16to64 x) (ZeroExt16to64 y))
+(Less8U x y) => (I64LtU (ZeroExt8to64 x) (ZeroExt8to64 y))
+(Less(64|32)F ...) => (F(64|32)Lt ...)
+
+(Leq64 ...) => (I64LeS ...)
+(Leq32 x y) => (I64LeS (SignExt32to64 x) (SignExt32to64 y))
+(Leq16 x y) => (I64LeS (SignExt16to64 x) (SignExt16to64 y))
+(Leq8 x y) => (I64LeS (SignExt8to64 x) (SignExt8to64 y))
+(Leq64U ...) => (I64LeU ...)
+(Leq32U x y) => (I64LeU (ZeroExt32to64 x) (ZeroExt32to64 y))
+(Leq16U x y) => (I64LeU (ZeroExt16to64 x) (ZeroExt16to64 y))
+(Leq8U x y) => (I64LeU (ZeroExt8to64 x) (ZeroExt8to64 y))
+(Leq(64|32)F ...) => (F(64|32)Le ...)
+
+(Eq64 ...) => (I64Eq ...)
+(Eq32 x y) => (I64Eq (ZeroExt32to64 x) (ZeroExt32to64 y))
+(Eq16 x y) => (I64Eq (ZeroExt16to64 x) (ZeroExt16to64 y))
+(Eq8 x y) => (I64Eq (ZeroExt8to64 x) (ZeroExt8to64 y))
+(EqB ...) => (I64Eq ...)
+(EqPtr ...) => (I64Eq ...)
+(Eq(64|32)F ...) => (F(64|32)Eq ...)
+
+(Neq64 ...) => (I64Ne ...)
+(Neq32 x y) => (I64Ne (ZeroExt32to64 x) (ZeroExt32to64 y))
+(Neq16 x y) => (I64Ne (ZeroExt16to64 x) (ZeroExt16to64 y))
+(Neq8 x y) => (I64Ne (ZeroExt8to64 x) (ZeroExt8to64 y))
+(NeqB ...) => (I64Ne ...)
+(NeqPtr ...) => (I64Ne ...)
+(Neq(64|32)F ...) => (F(64|32)Ne ...)
+
+// Lowering loads
+(Load <t> ptr mem) && is32BitFloat(t) => (F32Load ptr mem)
+(Load <t> ptr mem) && is64BitFloat(t) => (F64Load ptr mem)
+(Load <t> ptr mem) && t.Size() == 8 => (I64Load ptr mem)
+(Load <t> ptr mem) && t.Size() == 4 && !t.IsSigned() => (I64Load32U ptr mem)
+(Load <t> ptr mem) && t.Size() == 4 && t.IsSigned() => (I64Load32S ptr mem)
+(Load <t> ptr mem) && t.Size() == 2 && !t.IsSigned() => (I64Load16U ptr mem)
+(Load <t> ptr mem) && t.Size() == 2 && t.IsSigned() => (I64Load16S ptr mem)
+(Load <t> ptr mem) && t.Size() == 1 && !t.IsSigned() => (I64Load8U ptr mem)
+(Load <t> ptr mem) && t.Size() == 1 && t.IsSigned() => (I64Load8S ptr mem)
+
+// Lowering stores
+(Store {t} ptr val mem) && is64BitFloat(t) => (F64Store ptr val mem)
+(Store {t} ptr val mem) && is32BitFloat(t) => (F32Store ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 8 => (I64Store ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 4 => (I64Store32 ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 2 => (I64Store16 ptr val mem)
+(Store {t} ptr val mem) && t.Size() == 1 => (I64Store8 ptr val mem)
+
+// Lowering moves
+(Move [0] _ _ mem) => mem
+(Move [1] dst src mem) => (I64Store8 dst (I64Load8U src mem) mem)
+(Move [2] dst src mem) => (I64Store16 dst (I64Load16U src mem) mem)
+(Move [4] dst src mem) => (I64Store32 dst (I64Load32U src mem) mem)
+(Move [8] dst src mem) => (I64Store dst (I64Load src mem) mem)
+(Move [16] dst src mem) =>
+ (I64Store [8] dst (I64Load [8] src mem)
+ (I64Store dst (I64Load src mem) mem))
+(Move [3] dst src mem) =>
+ (I64Store8 [2] dst (I64Load8U [2] src mem)
+ (I64Store16 dst (I64Load16U src mem) mem))
+(Move [5] dst src mem) =>
+ (I64Store8 [4] dst (I64Load8U [4] src mem)
+ (I64Store32 dst (I64Load32U src mem) mem))
+(Move [6] dst src mem) =>
+ (I64Store16 [4] dst (I64Load16U [4] src mem)
+ (I64Store32 dst (I64Load32U src mem) mem))
+(Move [7] dst src mem) =>
+ (I64Store32 [3] dst (I64Load32U [3] src mem)
+ (I64Store32 dst (I64Load32U src mem) mem))
+(Move [s] dst src mem) && s > 8 && s < 16 =>
+ (I64Store [s-8] dst (I64Load [s-8] src mem)
+ (I64Store dst (I64Load src mem) mem))
+
+// Adjust moves to be a multiple of 16 bytes.
+(Move [s] dst src mem)
+ && s > 16 && s%16 != 0 && s%16 <= 8 =>
+ (Move [s-s%16]
+ (OffPtr <dst.Type> dst [s%16])
+ (OffPtr <src.Type> src [s%16])
+ (I64Store dst (I64Load src mem) mem))
+(Move [s] dst src mem)
+ && s > 16 && s%16 != 0 && s%16 > 8 =>
+ (Move [s-s%16]
+ (OffPtr <dst.Type> dst [s%16])
+ (OffPtr <src.Type> src [s%16])
+ (I64Store [8] dst (I64Load [8] src mem)
+ (I64Store dst (I64Load src mem) mem)))
+
+// Large copying uses helper.
+(Move [s] dst src mem) && s%8 == 0 && logLargeCopy(v, s) =>
+ (LoweredMove [s/8] dst src mem)
+
+// Lowering Zero instructions
+(Zero [0] _ mem) => mem
+(Zero [1] destptr mem) => (I64Store8 destptr (I64Const [0]) mem)
+(Zero [2] destptr mem) => (I64Store16 destptr (I64Const [0]) mem)
+(Zero [4] destptr mem) => (I64Store32 destptr (I64Const [0]) mem)
+(Zero [8] destptr mem) => (I64Store destptr (I64Const [0]) mem)
+
+(Zero [3] destptr mem) =>
+ (I64Store8 [2] destptr (I64Const [0])
+ (I64Store16 destptr (I64Const [0]) mem))
+(Zero [5] destptr mem) =>
+ (I64Store8 [4] destptr (I64Const [0])
+ (I64Store32 destptr (I64Const [0]) mem))
+(Zero [6] destptr mem) =>
+ (I64Store16 [4] destptr (I64Const [0])
+ (I64Store32 destptr (I64Const [0]) mem))
+(Zero [7] destptr mem) =>
+ (I64Store32 [3] destptr (I64Const [0])
+ (I64Store32 destptr (I64Const [0]) mem))
+
+// Strip off any fractional word zeroing.
+(Zero [s] destptr mem) && s%8 != 0 && s > 8 =>
+ (Zero [s-s%8] (OffPtr <destptr.Type> destptr [s%8])
+ (I64Store destptr (I64Const [0]) mem))
+
+// Zero small numbers of words directly.
+(Zero [16] destptr mem) =>
+ (I64Store [8] destptr (I64Const [0])
+ (I64Store destptr (I64Const [0]) mem))
+(Zero [24] destptr mem) =>
+ (I64Store [16] destptr (I64Const [0])
+ (I64Store [8] destptr (I64Const [0])
+ (I64Store destptr (I64Const [0]) mem)))
+(Zero [32] destptr mem) =>
+ (I64Store [24] destptr (I64Const [0])
+ (I64Store [16] destptr (I64Const [0])
+ (I64Store [8] destptr (I64Const [0])
+ (I64Store destptr (I64Const [0]) mem))))
+
+// Large zeroing uses helper.
+(Zero [s] destptr mem) && s%8 == 0 && s > 32 =>
+ (LoweredZero [s/8] destptr mem)
+
+// Lowering constants
+(Const64 ...) => (I64Const ...)
+(Const(32|16|8) [c]) => (I64Const [int64(c)])
+(Const(64|32)F ...) => (F(64|32)Const ...)
+(ConstNil) => (I64Const [0])
+(ConstBool [c]) => (I64Const [b2i(c)])
+
+// Lowering calls
+(StaticCall ...) => (LoweredStaticCall ...)
+(ClosureCall ...) => (LoweredClosureCall ...)
+(InterCall ...) => (LoweredInterCall ...)
+
+// Miscellaneous
+(Convert ...) => (LoweredConvert ...)
+(IsNonNil p) => (I64Eqz (I64Eqz p))
+(IsInBounds ...) => (I64LtU ...)
+(IsSliceInBounds ...) => (I64LeU ...)
+(NilCheck ...) => (LoweredNilCheck ...)
+(GetClosurePtr ...) => (LoweredGetClosurePtr ...)
+(GetCallerPC ...) => (LoweredGetCallerPC ...)
+(GetCallerSP ...) => (LoweredGetCallerSP ...)
+(Addr {sym} base) => (LoweredAddr {sym} [0] base)
+(LocalAddr {sym} base _) => (LoweredAddr {sym} base)
+
+// Write barrier.
+(WB ...) => (LoweredWB ...)
+
+// --- Intrinsics ---
+(Sqrt ...) => (F64Sqrt ...)
+(Trunc ...) => (F64Trunc ...)
+(Ceil ...) => (F64Ceil ...)
+(Floor ...) => (F64Floor ...)
+(RoundToEven ...) => (F64Nearest ...)
+(Abs ...) => (F64Abs ...)
+(Copysign ...) => (F64Copysign ...)
+
+(Ctz64 ...) => (I64Ctz ...)
+(Ctz32 x) => (I64Ctz (I64Or x (I64Const [0x100000000])))
+(Ctz16 x) => (I64Ctz (I64Or x (I64Const [0x10000])))
+(Ctz8 x) => (I64Ctz (I64Or x (I64Const [0x100])))
+
+(Ctz(64|32|16|8)NonZero ...) => (I64Ctz ...)
+
+(BitLen64 x) => (I64Sub (I64Const [64]) (I64Clz x))
+
+(PopCount64 ...) => (I64Popcnt ...)
+(PopCount32 x) => (I64Popcnt (ZeroExt32to64 x))
+(PopCount16 x) => (I64Popcnt (ZeroExt16to64 x))
+(PopCount8 x) => (I64Popcnt (ZeroExt8to64 x))
+
+(CondSelect ...) => (Select ...)
+
+// --- Optimizations ---
+(I64Add (I64Const [x]) (I64Const [y])) => (I64Const [x + y])
+(I64Mul (I64Const [x]) (I64Const [y])) => (I64Const [x * y])
+(I64And (I64Const [x]) (I64Const [y])) => (I64Const [x & y])
+(I64Or (I64Const [x]) (I64Const [y])) => (I64Const [x | y])
+(I64Xor (I64Const [x]) (I64Const [y])) => (I64Const [x ^ y])
+(F64Add (F64Const [x]) (F64Const [y])) => (F64Const [x + y])
+(F64Mul (F64Const [x]) (F64Const [y])) && !math.IsNaN(x * y) => (F64Const [x * y])
+(I64Eq (I64Const [x]) (I64Const [y])) && x == y => (I64Const [1])
+(I64Eq (I64Const [x]) (I64Const [y])) && x != y => (I64Const [0])
+(I64Ne (I64Const [x]) (I64Const [y])) && x == y => (I64Const [0])
+(I64Ne (I64Const [x]) (I64Const [y])) && x != y => (I64Const [1])
+
+(I64Shl (I64Const [x]) (I64Const [y])) => (I64Const [x << uint64(y)])
+(I64ShrU (I64Const [x]) (I64Const [y])) => (I64Const [int64(uint64(x) >> uint64(y))])
+(I64ShrS (I64Const [x]) (I64Const [y])) => (I64Const [x >> uint64(y)])
+
+// TODO: declare these operations as commutative and get rid of these rules?
+(I64Add (I64Const [x]) y) && y.Op != OpWasmI64Const => (I64Add y (I64Const [x]))
+(I64Mul (I64Const [x]) y) && y.Op != OpWasmI64Const => (I64Mul y (I64Const [x]))
+(I64And (I64Const [x]) y) && y.Op != OpWasmI64Const => (I64And y (I64Const [x]))
+(I64Or (I64Const [x]) y) && y.Op != OpWasmI64Const => (I64Or y (I64Const [x]))
+(I64Xor (I64Const [x]) y) && y.Op != OpWasmI64Const => (I64Xor y (I64Const [x]))
+(F64Add (F64Const [x]) y) && y.Op != OpWasmF64Const => (F64Add y (F64Const [x]))
+(F64Mul (F64Const [x]) y) && y.Op != OpWasmF64Const => (F64Mul y (F64Const [x]))
+(I64Eq (I64Const [x]) y) && y.Op != OpWasmI64Const => (I64Eq y (I64Const [x]))
+(I64Ne (I64Const [x]) y) && y.Op != OpWasmI64Const => (I64Ne y (I64Const [x]))
+
+(I64Eq x (I64Const [0])) => (I64Eqz x)
+(I64LtU (I64Const [0]) x) => (I64Eqz (I64Eqz x))
+(I64LeU x (I64Const [0])) => (I64Eqz x)
+(I64LtU x (I64Const [1])) => (I64Eqz x)
+(I64LeU (I64Const [1]) x) => (I64Eqz (I64Eqz x))
+(I64Ne x (I64Const [0])) => (I64Eqz (I64Eqz x))
+
+(I64Add x (I64Const [y])) => (I64AddConst [y] x)
+(I64AddConst [0] x) => x
+(I64Eqz (I64Eqz (I64Eqz x))) => (I64Eqz x)
+
+// folding offset into load/store
+((I64Load|I64Load32U|I64Load32S|I64Load16U|I64Load16S|I64Load8U|I64Load8S) [off] (I64AddConst [off2] ptr) mem)
+ && isU32Bit(off+off2) =>
+ ((I64Load|I64Load32U|I64Load32S|I64Load16U|I64Load16S|I64Load8U|I64Load8S) [off+off2] ptr mem)
+
+((I64Store|I64Store32|I64Store16|I64Store8) [off] (I64AddConst [off2] ptr) val mem)
+ && isU32Bit(off+off2) =>
+ ((I64Store|I64Store32|I64Store16|I64Store8) [off+off2] ptr val mem)
+
+// folding offset into address
+(I64AddConst [off] (LoweredAddr {sym} [off2] base)) && isU32Bit(off+int64(off2)) =>
+ (LoweredAddr {sym} [int32(off)+off2] base)
+(I64AddConst [off] x:(SP)) && isU32Bit(off) => (LoweredAddr [int32(off)] x) // so it is rematerializeable
+
+// transforming readonly globals into constants
+(I64Load [off] (LoweredAddr {sym} [off2] (SB)) _) && symIsRO(sym) && isU32Bit(off+int64(off2)) => (I64Const [int64(read64(sym, off+int64(off2), config.ctxt.Arch.ByteOrder))])
+(I64Load32U [off] (LoweredAddr {sym} [off2] (SB)) _) && symIsRO(sym) && isU32Bit(off+int64(off2)) => (I64Const [int64(read32(sym, off+int64(off2), config.ctxt.Arch.ByteOrder))])
+(I64Load16U [off] (LoweredAddr {sym} [off2] (SB)) _) && symIsRO(sym) && isU32Bit(off+int64(off2)) => (I64Const [int64(read16(sym, off+int64(off2), config.ctxt.Arch.ByteOrder))])
+(I64Load8U [off] (LoweredAddr {sym} [off2] (SB)) _) && symIsRO(sym) && isU32Bit(off+int64(off2)) => (I64Const [int64(read8(sym, off+int64(off2)))])
diff --git a/src/cmd/compile/internal/ssa/gen/WasmOps.go b/src/cmd/compile/internal/ssa/gen/WasmOps.go
new file mode 100644
index 0000000..36c53bc
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/WasmOps.go
@@ -0,0 +1,278 @@
+// Copyright 2018 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.
+
+// +build ignore
+
+package main
+
+import "strings"
+
+var regNamesWasm = []string{
+ "R0",
+ "R1",
+ "R2",
+ "R3",
+ "R4",
+ "R5",
+ "R6",
+ "R7",
+ "R8",
+ "R9",
+ "R10",
+ "R11",
+ "R12",
+ "R13",
+ "R14",
+ "R15",
+
+ "F0",
+ "F1",
+ "F2",
+ "F3",
+ "F4",
+ "F5",
+ "F6",
+ "F7",
+ "F8",
+ "F9",
+ "F10",
+ "F11",
+ "F12",
+ "F13",
+ "F14",
+ "F15",
+
+ "F16",
+ "F17",
+ "F18",
+ "F19",
+ "F20",
+ "F21",
+ "F22",
+ "F23",
+ "F24",
+ "F25",
+ "F26",
+ "F27",
+ "F28",
+ "F29",
+ "F30",
+ "F31",
+
+ "SP",
+ "g",
+
+ // pseudo-registers
+ "SB",
+}
+
+func init() {
+ // Make map from reg names to reg integers.
+ if len(regNamesWasm) > 64 {
+ panic("too many registers")
+ }
+ num := map[string]int{}
+ for i, name := range regNamesWasm {
+ num[name] = 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
+ }
+
+ var (
+ gp = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15")
+ fp32 = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15")
+ fp64 = buildReg("F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31")
+ gpsp = gp | buildReg("SP")
+ gpspsb = gpsp | buildReg("SB")
+ // The "registers", which are actually local variables, can get clobbered
+ // if we're switching goroutines, because it unwinds the WebAssembly stack.
+ callerSave = gp | fp32 | fp64 | buildReg("g")
+ )
+
+ // Common regInfo
+ var (
+ gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
+ gp11 = regInfo{inputs: []regMask{gpsp}, outputs: []regMask{gp}}
+ gp21 = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: []regMask{gp}}
+ gp31 = regInfo{inputs: []regMask{gpsp, gpsp, gpsp}, outputs: []regMask{gp}}
+ fp32_01 = regInfo{inputs: nil, outputs: []regMask{fp32}}
+ fp32_11 = regInfo{inputs: []regMask{fp32}, outputs: []regMask{fp32}}
+ fp32_21 = regInfo{inputs: []regMask{fp32, fp32}, outputs: []regMask{fp32}}
+ fp32_21gp = regInfo{inputs: []regMask{fp32, fp32}, outputs: []regMask{gp}}
+ fp64_01 = regInfo{inputs: nil, outputs: []regMask{fp64}}
+ fp64_11 = regInfo{inputs: []regMask{fp64}, outputs: []regMask{fp64}}
+ fp64_21 = regInfo{inputs: []regMask{fp64, fp64}, outputs: []regMask{fp64}}
+ fp64_21gp = regInfo{inputs: []regMask{fp64, fp64}, outputs: []regMask{gp}}
+ gpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: []regMask{gp}}
+ gpstore = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
+ fp32load = regInfo{inputs: []regMask{gpspsb, 0}, outputs: []regMask{fp32}}
+ fp32store = regInfo{inputs: []regMask{gpspsb, fp32, 0}}
+ fp64load = regInfo{inputs: []regMask{gpspsb, 0}, outputs: []regMask{fp64}}
+ fp64store = regInfo{inputs: []regMask{gpspsb, fp64, 0}}
+ )
+
+ var WasmOps = []opData{
+ {name: "LoweredStaticCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
+ {name: "LoweredClosureCall", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp, 0}, clobbers: callerSave}, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
+ {name: "LoweredInterCall", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
+
+ {name: "LoweredAddr", argLength: 1, reg: gp11, aux: "SymOff", rematerializeable: true, symEffect: "Addr"}, // returns base+aux+auxint, arg0=base
+ {name: "LoweredMove", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp}}, aux: "Int64"}, // large move. arg0=dst, arg1=src, arg2=mem, auxint=len/8, returns mem
+ {name: "LoweredZero", argLength: 2, reg: regInfo{inputs: []regMask{gp}}, aux: "Int64"}, // large zeroing. arg0=start, arg1=mem, auxint=len/8, returns mem
+
+ {name: "LoweredGetClosurePtr", reg: gp01}, // returns wasm.REG_CTXT, the closure pointer
+ {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true}, // returns the PC of the caller of the current function
+ {name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true}, // returns the SP of the caller of the current function
+ {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gp}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem
+ {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp}}, aux: "Sym", symEffect: "None"}, // invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+
+ // LoweredConvert converts between pointers and integers.
+ // We have a special op for this so as to not confuse GCCallOff
+ // (particularly stack maps). It takes a memory arg so it
+ // gets correctly ordered with respect to GC safepoints.
+ // arg0=ptr/int arg1=mem, output=int/ptr
+ //
+ // TODO(neelance): LoweredConvert should not be necessary any more, since OpConvert does not need to be lowered any more (CL 108496).
+ {name: "LoweredConvert", argLength: 2, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}},
+
+ // The following are native WebAssembly instructions, see https://webassembly.github.io/spec/core/syntax/instructions.html
+
+ {name: "Select", asm: "Select", argLength: 3, reg: gp31}, // returns arg0 if arg2 != 0, otherwise returns arg1
+
+ {name: "I64Load8U", asm: "I64Load8U", argLength: 2, reg: gpload, aux: "Int64", typ: "UInt8"}, // read unsigned 8-bit integer from address arg0+aux, arg1=mem
+ {name: "I64Load8S", asm: "I64Load8S", argLength: 2, reg: gpload, aux: "Int64", typ: "Int8"}, // read signed 8-bit integer from address arg0+aux, arg1=mem
+ {name: "I64Load16U", asm: "I64Load16U", argLength: 2, reg: gpload, aux: "Int64", typ: "UInt16"}, // read unsigned 16-bit integer from address arg0+aux, arg1=mem
+ {name: "I64Load16S", asm: "I64Load16S", argLength: 2, reg: gpload, aux: "Int64", typ: "Int16"}, // read signed 16-bit integer from address arg0+aux, arg1=mem
+ {name: "I64Load32U", asm: "I64Load32U", argLength: 2, reg: gpload, aux: "Int64", typ: "UInt32"}, // read unsigned 32-bit integer from address arg0+aux, arg1=mem
+ {name: "I64Load32S", asm: "I64Load32S", argLength: 2, reg: gpload, aux: "Int64", typ: "Int32"}, // read signed 32-bit integer from address arg0+aux, arg1=mem
+ {name: "I64Load", asm: "I64Load", argLength: 2, reg: gpload, aux: "Int64", typ: "UInt64"}, // read 64-bit integer from address arg0+aux, arg1=mem
+ {name: "I64Store8", asm: "I64Store8", argLength: 3, reg: gpstore, aux: "Int64", typ: "Mem"}, // store 8-bit integer arg1 at address arg0+aux, arg2=mem, returns mem
+ {name: "I64Store16", asm: "I64Store16", argLength: 3, reg: gpstore, aux: "Int64", typ: "Mem"}, // store 16-bit integer arg1 at address arg0+aux, arg2=mem, returns mem
+ {name: "I64Store32", asm: "I64Store32", argLength: 3, reg: gpstore, aux: "Int64", typ: "Mem"}, // store 32-bit integer arg1 at address arg0+aux, arg2=mem, returns mem
+ {name: "I64Store", asm: "I64Store", argLength: 3, reg: gpstore, aux: "Int64", typ: "Mem"}, // store 64-bit integer arg1 at address arg0+aux, arg2=mem, returns mem
+
+ {name: "F32Load", asm: "F32Load", argLength: 2, reg: fp32load, aux: "Int64", typ: "Float32"}, // read 32-bit float from address arg0+aux, arg1=mem
+ {name: "F64Load", asm: "F64Load", argLength: 2, reg: fp64load, aux: "Int64", typ: "Float64"}, // read 64-bit float from address arg0+aux, arg1=mem
+ {name: "F32Store", asm: "F32Store", argLength: 3, reg: fp32store, aux: "Int64", typ: "Mem"}, // store 32-bit float arg1 at address arg0+aux, arg2=mem, returns mem
+ {name: "F64Store", asm: "F64Store", argLength: 3, reg: fp64store, aux: "Int64", typ: "Mem"}, // store 64-bit float arg1 at address arg0+aux, arg2=mem, returns mem
+
+ {name: "I64Const", reg: gp01, aux: "Int64", rematerializeable: true, typ: "Int64"}, // returns the constant integer aux
+ {name: "F32Const", reg: fp32_01, aux: "Float32", rematerializeable: true, typ: "Float32"}, // returns the constant float aux
+ {name: "F64Const", reg: fp64_01, aux: "Float64", rematerializeable: true, typ: "Float64"}, // returns the constant float aux
+
+ {name: "I64Eqz", asm: "I64Eqz", argLength: 1, reg: gp11, typ: "Bool"}, // arg0 == 0
+ {name: "I64Eq", asm: "I64Eq", argLength: 2, reg: gp21, typ: "Bool"}, // arg0 == arg1
+ {name: "I64Ne", asm: "I64Ne", argLength: 2, reg: gp21, typ: "Bool"}, // arg0 != arg1
+ {name: "I64LtS", asm: "I64LtS", argLength: 2, reg: gp21, typ: "Bool"}, // arg0 < arg1 (signed)
+ {name: "I64LtU", asm: "I64LtU", argLength: 2, reg: gp21, typ: "Bool"}, // arg0 < arg1 (unsigned)
+ {name: "I64GtS", asm: "I64GtS", argLength: 2, reg: gp21, typ: "Bool"}, // arg0 > arg1 (signed)
+ {name: "I64GtU", asm: "I64GtU", argLength: 2, reg: gp21, typ: "Bool"}, // arg0 > arg1 (unsigned)
+ {name: "I64LeS", asm: "I64LeS", argLength: 2, reg: gp21, typ: "Bool"}, // arg0 <= arg1 (signed)
+ {name: "I64LeU", asm: "I64LeU", argLength: 2, reg: gp21, typ: "Bool"}, // arg0 <= arg1 (unsigned)
+ {name: "I64GeS", asm: "I64GeS", argLength: 2, reg: gp21, typ: "Bool"}, // arg0 >= arg1 (signed)
+ {name: "I64GeU", asm: "I64GeU", argLength: 2, reg: gp21, typ: "Bool"}, // arg0 >= arg1 (unsigned)
+
+ {name: "F32Eq", asm: "F32Eq", argLength: 2, reg: fp32_21gp, typ: "Bool"}, // arg0 == arg1
+ {name: "F32Ne", asm: "F32Ne", argLength: 2, reg: fp32_21gp, typ: "Bool"}, // arg0 != arg1
+ {name: "F32Lt", asm: "F32Lt", argLength: 2, reg: fp32_21gp, typ: "Bool"}, // arg0 < arg1
+ {name: "F32Gt", asm: "F32Gt", argLength: 2, reg: fp32_21gp, typ: "Bool"}, // arg0 > arg1
+ {name: "F32Le", asm: "F32Le", argLength: 2, reg: fp32_21gp, typ: "Bool"}, // arg0 <= arg1
+ {name: "F32Ge", asm: "F32Ge", argLength: 2, reg: fp32_21gp, typ: "Bool"}, // arg0 >= arg1
+
+ {name: "F64Eq", asm: "F64Eq", argLength: 2, reg: fp64_21gp, typ: "Bool"}, // arg0 == arg1
+ {name: "F64Ne", asm: "F64Ne", argLength: 2, reg: fp64_21gp, typ: "Bool"}, // arg0 != arg1
+ {name: "F64Lt", asm: "F64Lt", argLength: 2, reg: fp64_21gp, typ: "Bool"}, // arg0 < arg1
+ {name: "F64Gt", asm: "F64Gt", argLength: 2, reg: fp64_21gp, typ: "Bool"}, // arg0 > arg1
+ {name: "F64Le", asm: "F64Le", argLength: 2, reg: fp64_21gp, typ: "Bool"}, // arg0 <= arg1
+ {name: "F64Ge", asm: "F64Ge", argLength: 2, reg: fp64_21gp, typ: "Bool"}, // arg0 >= arg1
+
+ {name: "I64Add", asm: "I64Add", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 + arg1
+ {name: "I64AddConst", asm: "I64Add", argLength: 1, reg: gp11, aux: "Int64", typ: "Int64"}, // arg0 + aux
+ {name: "I64Sub", asm: "I64Sub", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 - arg1
+ {name: "I64Mul", asm: "I64Mul", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 * arg1
+ {name: "I64DivS", asm: "I64DivS", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 / arg1 (signed)
+ {name: "I64DivU", asm: "I64DivU", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 / arg1 (unsigned)
+ {name: "I64RemS", asm: "I64RemS", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 % arg1 (signed)
+ {name: "I64RemU", asm: "I64RemU", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 % arg1 (unsigned)
+ {name: "I64And", asm: "I64And", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 & arg1
+ {name: "I64Or", asm: "I64Or", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 | arg1
+ {name: "I64Xor", asm: "I64Xor", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 ^ arg1
+ {name: "I64Shl", asm: "I64Shl", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 << (arg1 % 64)
+ {name: "I64ShrS", asm: "I64ShrS", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 >> (arg1 % 64) (signed)
+ {name: "I64ShrU", asm: "I64ShrU", argLength: 2, reg: gp21, typ: "Int64"}, // arg0 >> (arg1 % 64) (unsigned)
+
+ {name: "F32Neg", asm: "F32Neg", argLength: 1, reg: fp32_11, typ: "Float32"}, // -arg0
+ {name: "F32Add", asm: "F32Add", argLength: 2, reg: fp32_21, typ: "Float32"}, // arg0 + arg1
+ {name: "F32Sub", asm: "F32Sub", argLength: 2, reg: fp32_21, typ: "Float32"}, // arg0 - arg1
+ {name: "F32Mul", asm: "F32Mul", argLength: 2, reg: fp32_21, typ: "Float32"}, // arg0 * arg1
+ {name: "F32Div", asm: "F32Div", argLength: 2, reg: fp32_21, typ: "Float32"}, // arg0 / arg1
+
+ {name: "F64Neg", asm: "F64Neg", argLength: 1, reg: fp64_11, typ: "Float64"}, // -arg0
+ {name: "F64Add", asm: "F64Add", argLength: 2, reg: fp64_21, typ: "Float64"}, // arg0 + arg1
+ {name: "F64Sub", asm: "F64Sub", argLength: 2, reg: fp64_21, typ: "Float64"}, // arg0 - arg1
+ {name: "F64Mul", asm: "F64Mul", argLength: 2, reg: fp64_21, typ: "Float64"}, // arg0 * arg1
+ {name: "F64Div", asm: "F64Div", argLength: 2, reg: fp64_21, typ: "Float64"}, // arg0 / arg1
+
+ {name: "I64TruncSatF64S", asm: "I64TruncSatF64S", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to a signed integer (saturating)
+ {name: "I64TruncSatF64U", asm: "I64TruncSatF64U", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to an unsigned integer (saturating)
+ {name: "I64TruncSatF32S", asm: "I64TruncSatF32S", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to a signed integer (saturating)
+ {name: "I64TruncSatF32U", asm: "I64TruncSatF32U", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to an unsigned integer (saturating)
+ {name: "F32ConvertI64S", asm: "F32ConvertI64S", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp32}}, typ: "Float32"}, // converts the signed integer arg0 to a float
+ {name: "F32ConvertI64U", asm: "F32ConvertI64U", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp32}}, typ: "Float32"}, // converts the unsigned integer arg0 to a float
+ {name: "F64ConvertI64S", asm: "F64ConvertI64S", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp64}}, typ: "Float64"}, // converts the signed integer arg0 to a float
+ {name: "F64ConvertI64U", asm: "F64ConvertI64U", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp64}}, typ: "Float64"}, // converts the unsigned integer arg0 to a float
+ {name: "F32DemoteF64", asm: "F32DemoteF64", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{fp32}}, typ: "Float32"},
+ {name: "F64PromoteF32", asm: "F64PromoteF32", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{fp64}}, typ: "Float64"},
+
+ {name: "I64Extend8S", asm: "I64Extend8S", argLength: 1, reg: gp11, typ: "Int64"}, // sign-extend arg0 from 8 to 64 bit
+ {name: "I64Extend16S", asm: "I64Extend16S", argLength: 1, reg: gp11, typ: "Int64"}, // sign-extend arg0 from 16 to 64 bit
+ {name: "I64Extend32S", asm: "I64Extend32S", argLength: 1, reg: gp11, typ: "Int64"}, // sign-extend arg0 from 32 to 64 bit
+
+ {name: "F32Sqrt", asm: "F32Sqrt", argLength: 1, reg: fp64_11, typ: "Float32"}, // sqrt(arg0)
+ {name: "F32Trunc", asm: "F32Trunc", argLength: 1, reg: fp64_11, typ: "Float32"}, // trunc(arg0)
+ {name: "F32Ceil", asm: "F32Ceil", argLength: 1, reg: fp64_11, typ: "Float32"}, // ceil(arg0)
+ {name: "F32Floor", asm: "F32Floor", argLength: 1, reg: fp64_11, typ: "Float32"}, // floor(arg0)
+ {name: "F32Nearest", asm: "F32Nearest", argLength: 1, reg: fp64_11, typ: "Float32"}, // round(arg0)
+ {name: "F32Abs", asm: "F32Abs", argLength: 1, reg: fp64_11, typ: "Float32"}, // abs(arg0)
+ {name: "F32Copysign", asm: "F32Copysign", argLength: 2, reg: fp64_21, typ: "Float32"}, // copysign(arg0, arg1)
+
+ {name: "F64Sqrt", asm: "F64Sqrt", argLength: 1, reg: fp64_11, typ: "Float64"}, // sqrt(arg0)
+ {name: "F64Trunc", asm: "F64Trunc", argLength: 1, reg: fp64_11, typ: "Float64"}, // trunc(arg0)
+ {name: "F64Ceil", asm: "F64Ceil", argLength: 1, reg: fp64_11, typ: "Float64"}, // ceil(arg0)
+ {name: "F64Floor", asm: "F64Floor", argLength: 1, reg: fp64_11, typ: "Float64"}, // floor(arg0)
+ {name: "F64Nearest", asm: "F64Nearest", argLength: 1, reg: fp64_11, typ: "Float64"}, // round(arg0)
+ {name: "F64Abs", asm: "F64Abs", argLength: 1, reg: fp64_11, typ: "Float64"}, // abs(arg0)
+ {name: "F64Copysign", asm: "F64Copysign", argLength: 2, reg: fp64_21, typ: "Float64"}, // copysign(arg0, arg1)
+
+ {name: "I64Ctz", asm: "I64Ctz", argLength: 1, reg: gp11, typ: "Int64"}, // ctz(arg0)
+ {name: "I64Clz", asm: "I64Clz", argLength: 1, reg: gp11, typ: "Int64"}, // clz(arg0)
+ {name: "I32Rotl", asm: "I32Rotl", argLength: 2, reg: gp21, typ: "Int32"}, // rotl(arg0, arg1)
+ {name: "I64Rotl", asm: "I64Rotl", argLength: 2, reg: gp21, typ: "Int64"}, // rotl(arg0, arg1)
+ {name: "I64Popcnt", asm: "I64Popcnt", argLength: 1, reg: gp11, typ: "Int64"}, // popcnt(arg0)
+ }
+
+ archs = append(archs, arch{
+ name: "Wasm",
+ pkg: "cmd/internal/obj/wasm",
+ genfile: "../../wasm/ssa.go",
+ ops: WasmOps,
+ blocks: nil,
+ regnames: regNamesWasm,
+ gpregmask: gp,
+ fpregmask: fp32 | fp64,
+ fp32regmask: fp32,
+ fp64regmask: fp64,
+ framepointerreg: -1, // not used
+ linkreg: -1, // not used
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/cover.bash b/src/cmd/compile/internal/ssa/gen/cover.bash
new file mode 100755
index 0000000..6c860fc
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/cover.bash
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# Copyright 2020 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.
+
+# A quick and dirty way to obtain code coverage from rulegen's main func. For
+# example:
+#
+# ./cover.bash && go tool cover -html=cover.out
+#
+# This script is needed to set up a temporary test file, so that we don't break
+# regular 'go run *.go' usage to run the generator.
+
+cat >main_test.go <<-EOF
+ // +build ignore
+
+ package main
+
+ import "testing"
+
+ func TestCoverage(t *testing.T) { main() }
+EOF
+
+go test -run='^TestCoverage$' -coverprofile=cover.out "$@" *.go
+
+rm -f main_test.go
diff --git a/src/cmd/compile/internal/ssa/gen/dec.rules b/src/cmd/compile/internal/ssa/gen/dec.rules
new file mode 100644
index 0000000..4c677f8
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/dec.rules
@@ -0,0 +1,92 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains rules to decompose builtin compound types
+// (complex,string,slice,interface) into their constituent
+// types. These rules work together with the decomposeBuiltIn
+// pass which handles phis of these types.
+
+// complex ops
+(ComplexReal (ComplexMake real _ )) => real
+(ComplexImag (ComplexMake _ imag )) => imag
+
+(Load <t> ptr mem) && t.IsComplex() && t.Size() == 8 =>
+ (ComplexMake
+ (Load <typ.Float32> ptr mem)
+ (Load <typ.Float32>
+ (OffPtr <typ.Float32Ptr> [4] ptr)
+ mem)
+ )
+(Store {t} dst (ComplexMake real imag) mem) && t.Size() == 8 =>
+ (Store {typ.Float32}
+ (OffPtr <typ.Float32Ptr> [4] dst)
+ imag
+ (Store {typ.Float32} dst real mem))
+(Load <t> ptr mem) && t.IsComplex() && t.Size() == 16 =>
+ (ComplexMake
+ (Load <typ.Float64> ptr mem)
+ (Load <typ.Float64>
+ (OffPtr <typ.Float64Ptr> [8] ptr)
+ mem)
+ )
+(Store {t} dst (ComplexMake real imag) mem) && t.Size() == 16 =>
+ (Store {typ.Float64}
+ (OffPtr <typ.Float64Ptr> [8] dst)
+ imag
+ (Store {typ.Float64} dst real mem))
+
+// string ops
+(StringPtr (StringMake ptr _)) => ptr
+(StringLen (StringMake _ len)) => len
+
+(Load <t> ptr mem) && t.IsString() =>
+ (StringMake
+ (Load <typ.BytePtr> ptr mem)
+ (Load <typ.Int>
+ (OffPtr <typ.IntPtr> [config.PtrSize] ptr)
+ mem))
+(Store dst (StringMake ptr len) mem) =>
+ (Store {typ.Int}
+ (OffPtr <typ.IntPtr> [config.PtrSize] dst)
+ len
+ (Store {typ.BytePtr} dst ptr mem))
+
+// slice ops
+(SlicePtr (SliceMake ptr _ _ )) => ptr
+(SliceLen (SliceMake _ len _)) => len
+(SliceCap (SliceMake _ _ cap)) => cap
+
+(Load <t> ptr mem) && t.IsSlice() =>
+ (SliceMake
+ (Load <t.Elem().PtrTo()> ptr mem)
+ (Load <typ.Int>
+ (OffPtr <typ.IntPtr> [config.PtrSize] ptr)
+ mem)
+ (Load <typ.Int>
+ (OffPtr <typ.IntPtr> [2*config.PtrSize] ptr)
+ mem))
+(Store {t} dst (SliceMake ptr len cap) mem) =>
+ (Store {typ.Int}
+ (OffPtr <typ.IntPtr> [2*config.PtrSize] dst)
+ cap
+ (Store {typ.Int}
+ (OffPtr <typ.IntPtr> [config.PtrSize] dst)
+ len
+ (Store {t.Elem().PtrTo()} dst ptr mem)))
+
+// interface ops
+(ITab (IMake itab _)) => itab
+(IData (IMake _ data)) => data
+
+(Load <t> ptr mem) && t.IsInterface() =>
+ (IMake
+ (Load <typ.Uintptr> ptr mem)
+ (Load <typ.BytePtr>
+ (OffPtr <typ.BytePtrPtr> [config.PtrSize] ptr)
+ mem))
+(Store dst (IMake itab data) mem) =>
+ (Store {typ.BytePtr}
+ (OffPtr <typ.BytePtrPtr> [config.PtrSize] dst)
+ data
+ (Store {typ.Uintptr} dst itab mem))
diff --git a/src/cmd/compile/internal/ssa/gen/dec64.rules b/src/cmd/compile/internal/ssa/gen/dec64.rules
new file mode 100644
index 0000000..9297ed8
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/dec64.rules
@@ -0,0 +1,396 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains rules to decompose [u]int64 types on 32-bit
+// architectures. These rules work together with the decomposeBuiltIn
+// pass which handles phis of these typ.
+
+(Int64Hi (Int64Make hi _)) => hi
+(Int64Lo (Int64Make _ lo)) => lo
+
+(Load <t> ptr mem) && is64BitInt(t) && !config.BigEndian && t.IsSigned() =>
+ (Int64Make
+ (Load <typ.Int32> (OffPtr <typ.Int32Ptr> [4] ptr) mem)
+ (Load <typ.UInt32> ptr mem))
+
+(Load <t> ptr mem) && is64BitInt(t) && !config.BigEndian && !t.IsSigned() =>
+ (Int64Make
+ (Load <typ.UInt32> (OffPtr <typ.UInt32Ptr> [4] ptr) mem)
+ (Load <typ.UInt32> ptr mem))
+
+(Load <t> ptr mem) && is64BitInt(t) && config.BigEndian && t.IsSigned() =>
+ (Int64Make
+ (Load <typ.Int32> ptr mem)
+ (Load <typ.UInt32> (OffPtr <typ.UInt32Ptr> [4] ptr) mem))
+
+(Load <t> ptr mem) && is64BitInt(t) && config.BigEndian && !t.IsSigned() =>
+ (Int64Make
+ (Load <typ.UInt32> ptr mem)
+ (Load <typ.UInt32> (OffPtr <typ.UInt32Ptr> [4] ptr) mem))
+
+(Store {t} dst (Int64Make hi lo) mem) && t.Size() == 8 && !config.BigEndian =>
+ (Store {hi.Type}
+ (OffPtr <hi.Type.PtrTo()> [4] dst)
+ hi
+ (Store {lo.Type} dst lo mem))
+
+(Store {t} dst (Int64Make hi lo) mem) && t.Size() == 8 && config.BigEndian =>
+ (Store {lo.Type}
+ (OffPtr <lo.Type.PtrTo()> [4] dst)
+ lo
+ (Store {hi.Type} dst hi mem))
+
+// These are not enabled during decomposeBuiltin if late call expansion, but they are always enabled for softFloat
+(Arg {n} [off]) && is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin") =>
+ (Int64Make
+ (Arg <typ.Int32> {n} [off+4])
+ (Arg <typ.UInt32> {n} [off]))
+(Arg {n} [off]) && is64BitInt(v.Type) && !config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin") =>
+ (Int64Make
+ (Arg <typ.UInt32> {n} [off+4])
+ (Arg <typ.UInt32> {n} [off]))
+
+(Arg {n} [off]) && is64BitInt(v.Type) && config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin") =>
+ (Int64Make
+ (Arg <typ.Int32> {n} [off])
+ (Arg <typ.UInt32> {n} [off+4]))
+(Arg {n} [off]) && is64BitInt(v.Type) && config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin") =>
+ (Int64Make
+ (Arg <typ.UInt32> {n} [off])
+ (Arg <typ.UInt32> {n} [off+4]))
+
+(Add64 x y) =>
+ (Int64Make
+ (Add32withcarry <typ.Int32>
+ (Int64Hi x)
+ (Int64Hi y)
+ (Select1 <types.TypeFlags> (Add32carry (Int64Lo x) (Int64Lo y))))
+ (Select0 <typ.UInt32> (Add32carry (Int64Lo x) (Int64Lo y))))
+
+(Sub64 x y) =>
+ (Int64Make
+ (Sub32withcarry <typ.Int32>
+ (Int64Hi x)
+ (Int64Hi y)
+ (Select1 <types.TypeFlags> (Sub32carry (Int64Lo x) (Int64Lo y))))
+ (Select0 <typ.UInt32> (Sub32carry (Int64Lo x) (Int64Lo y))))
+
+(Mul64 x y) =>
+ (Int64Make
+ (Add32 <typ.UInt32>
+ (Mul32 <typ.UInt32> (Int64Lo x) (Int64Hi y))
+ (Add32 <typ.UInt32>
+ (Mul32 <typ.UInt32> (Int64Hi x) (Int64Lo y))
+ (Select0 <typ.UInt32> (Mul32uhilo (Int64Lo x) (Int64Lo y)))))
+ (Select1 <typ.UInt32> (Mul32uhilo (Int64Lo x) (Int64Lo y))))
+
+(And64 x y) =>
+ (Int64Make
+ (And32 <typ.UInt32> (Int64Hi x) (Int64Hi y))
+ (And32 <typ.UInt32> (Int64Lo x) (Int64Lo y)))
+
+(Or64 x y) =>
+ (Int64Make
+ (Or32 <typ.UInt32> (Int64Hi x) (Int64Hi y))
+ (Or32 <typ.UInt32> (Int64Lo x) (Int64Lo y)))
+
+(Xor64 x y) =>
+ (Int64Make
+ (Xor32 <typ.UInt32> (Int64Hi x) (Int64Hi y))
+ (Xor32 <typ.UInt32> (Int64Lo x) (Int64Lo y)))
+
+(Neg64 <t> x) => (Sub64 (Const64 <t> [0]) x)
+
+(Com64 x) =>
+ (Int64Make
+ (Com32 <typ.UInt32> (Int64Hi x))
+ (Com32 <typ.UInt32> (Int64Lo x)))
+
+// Sadly, just because we know that x is non-zero,
+// we don't know whether either component is,
+// so just treat Ctz64NonZero the same as Ctz64.
+(Ctz64NonZero ...) => (Ctz64 ...)
+
+(Ctz64 x) =>
+ (Add32 <typ.UInt32>
+ (Ctz32 <typ.UInt32> (Int64Lo x))
+ (And32 <typ.UInt32>
+ (Com32 <typ.UInt32> (Zeromask (Int64Lo x)))
+ (Ctz32 <typ.UInt32> (Int64Hi x))))
+
+(BitLen64 x) =>
+ (Add32 <typ.Int>
+ (BitLen32 <typ.Int> (Int64Hi x))
+ (BitLen32 <typ.Int>
+ (Or32 <typ.UInt32>
+ (Int64Lo x)
+ (Zeromask (Int64Hi x)))))
+
+(Bswap64 x) =>
+ (Int64Make
+ (Bswap32 <typ.UInt32> (Int64Lo x))
+ (Bswap32 <typ.UInt32> (Int64Hi x)))
+
+(SignExt32to64 x) => (Int64Make (Signmask x) x)
+(SignExt16to64 x) => (SignExt32to64 (SignExt16to32 x))
+(SignExt8to64 x) => (SignExt32to64 (SignExt8to32 x))
+
+(ZeroExt32to64 x) => (Int64Make (Const32 <typ.UInt32> [0]) x)
+(ZeroExt16to64 x) => (ZeroExt32to64 (ZeroExt16to32 x))
+(ZeroExt8to64 x) => (ZeroExt32to64 (ZeroExt8to32 x))
+
+(Trunc64to32 (Int64Make _ lo)) => lo
+(Trunc64to16 (Int64Make _ lo)) => (Trunc32to16 lo)
+(Trunc64to8 (Int64Make _ lo)) => (Trunc32to8 lo)
+// Most general
+(Trunc64to32 x) => (Int64Lo x)
+(Trunc64to16 x) => (Trunc32to16 (Int64Lo x))
+(Trunc64to8 x) => (Trunc32to8 (Int64Lo x))
+
+(Lsh32x64 _ (Int64Make (Const32 [c]) _)) && c != 0 => (Const32 [0])
+(Rsh32x64 x (Int64Make (Const32 [c]) _)) && c != 0 => (Signmask x)
+(Rsh32Ux64 _ (Int64Make (Const32 [c]) _)) && c != 0 => (Const32 [0])
+(Lsh16x64 _ (Int64Make (Const32 [c]) _)) && c != 0 => (Const32 [0])
+(Rsh16x64 x (Int64Make (Const32 [c]) _)) && c != 0 => (Signmask (SignExt16to32 x))
+(Rsh16Ux64 _ (Int64Make (Const32 [c]) _)) && c != 0 => (Const32 [0])
+(Lsh8x64 _ (Int64Make (Const32 [c]) _)) && c != 0 => (Const32 [0])
+(Rsh8x64 x (Int64Make (Const32 [c]) _)) && c != 0 => (Signmask (SignExt8to32 x))
+(Rsh8Ux64 _ (Int64Make (Const32 [c]) _)) && c != 0 => (Const32 [0])
+
+(Lsh32x64 [c] x (Int64Make (Const32 [0]) lo)) => (Lsh32x32 [c] x lo)
+(Rsh32x64 [c] x (Int64Make (Const32 [0]) lo)) => (Rsh32x32 [c] x lo)
+(Rsh32Ux64 [c] x (Int64Make (Const32 [0]) lo)) => (Rsh32Ux32 [c] x lo)
+(Lsh16x64 [c] x (Int64Make (Const32 [0]) lo)) => (Lsh16x32 [c] x lo)
+(Rsh16x64 [c] x (Int64Make (Const32 [0]) lo)) => (Rsh16x32 [c] x lo)
+(Rsh16Ux64 [c] x (Int64Make (Const32 [0]) lo)) => (Rsh16Ux32 [c] x lo)
+(Lsh8x64 [c] x (Int64Make (Const32 [0]) lo)) => (Lsh8x32 [c] x lo)
+(Rsh8x64 [c] x (Int64Make (Const32 [0]) lo)) => (Rsh8x32 [c] x lo)
+(Rsh8Ux64 [c] x (Int64Make (Const32 [0]) lo)) => (Rsh8Ux32 [c] x lo)
+
+(Lsh64x64 _ (Int64Make (Const32 [c]) _)) && c != 0 => (Const64 [0])
+(Rsh64x64 x (Int64Make (Const32 [c]) _)) && c != 0 => (Int64Make (Signmask (Int64Hi x)) (Signmask (Int64Hi x)))
+(Rsh64Ux64 _ (Int64Make (Const32 [c]) _)) && c != 0 => (Const64 [0])
+
+(Lsh64x64 [c] x (Int64Make (Const32 [0]) lo)) => (Lsh64x32 [c] x lo)
+(Rsh64x64 [c] x (Int64Make (Const32 [0]) lo)) => (Rsh64x32 [c] x lo)
+(Rsh64Ux64 [c] x (Int64Make (Const32 [0]) lo)) => (Rsh64Ux32 [c] x lo)
+
+// turn x64 non-constant shifts to x32 shifts
+// if high 32-bit of the shift is nonzero, make a huge shift
+(Lsh64x64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Lsh64x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Rsh64x64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Rsh64x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Rsh64Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Rsh64Ux32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Lsh32x64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Lsh32x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Rsh32x64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Rsh32x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Rsh32Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Rsh32Ux32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Lsh16x64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Lsh16x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Rsh16x64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Rsh16x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Rsh16Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Rsh16Ux32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Lsh8x64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Lsh8x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Rsh8x64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Rsh8x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+(Rsh8Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 =>
+ (Rsh8Ux32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+
+// Most general
+(Lsh64x64 x y) => (Lsh64x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Rsh64x64 x y) => (Rsh64x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Rsh64Ux64 x y) => (Rsh64Ux32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Lsh32x64 x y) => (Lsh32x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Rsh32x64 x y) => (Rsh32x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Rsh32Ux64 x y) => (Rsh32Ux32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Lsh16x64 x y) => (Lsh16x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Rsh16x64 x y) => (Rsh16x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Rsh16Ux64 x y) => (Rsh16Ux32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Lsh8x64 x y) => (Lsh8x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Rsh8x64 x y) => (Rsh8x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+(Rsh8Ux64 x y) => (Rsh8Ux32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+
+// Clean up constants a little
+(Or32 <typ.UInt32> (Zeromask (Const32 [c])) y) && c == 0 => y
+(Or32 <typ.UInt32> (Zeromask (Const32 [c])) y) && c != 0 => (Const32 <typ.UInt32> [-1])
+
+// 64x left shift
+// result.hi = hi<<s | lo>>(32-s) | lo<<(s-32) // >> is unsigned, large shifts result 0
+// result.lo = lo<<s
+(Lsh64x32 x s) =>
+ (Int64Make
+ (Or32 <typ.UInt32>
+ (Or32 <typ.UInt32>
+ (Lsh32x32 <typ.UInt32> (Int64Hi x) s)
+ (Rsh32Ux32 <typ.UInt32>
+ (Int64Lo x)
+ (Sub32 <typ.UInt32> (Const32 <typ.UInt32> [32]) s)))
+ (Lsh32x32 <typ.UInt32>
+ (Int64Lo x)
+ (Sub32 <typ.UInt32> s (Const32 <typ.UInt32> [32]))))
+ (Lsh32x32 <typ.UInt32> (Int64Lo x) s))
+(Lsh64x16 x s) =>
+ (Int64Make
+ (Or32 <typ.UInt32>
+ (Or32 <typ.UInt32>
+ (Lsh32x16 <typ.UInt32> (Int64Hi x) s)
+ (Rsh32Ux16 <typ.UInt32>
+ (Int64Lo x)
+ (Sub16 <typ.UInt16> (Const16 <typ.UInt16> [32]) s)))
+ (Lsh32x16 <typ.UInt32>
+ (Int64Lo x)
+ (Sub16 <typ.UInt16> s (Const16 <typ.UInt16> [32]))))
+ (Lsh32x16 <typ.UInt32> (Int64Lo x) s))
+(Lsh64x8 x s) =>
+ (Int64Make
+ (Or32 <typ.UInt32>
+ (Or32 <typ.UInt32>
+ (Lsh32x8 <typ.UInt32> (Int64Hi x) s)
+ (Rsh32Ux8 <typ.UInt32>
+ (Int64Lo x)
+ (Sub8 <typ.UInt8> (Const8 <typ.UInt8> [32]) s)))
+ (Lsh32x8 <typ.UInt32>
+ (Int64Lo x)
+ (Sub8 <typ.UInt8> s (Const8 <typ.UInt8> [32]))))
+ (Lsh32x8 <typ.UInt32> (Int64Lo x) s))
+
+// 64x unsigned right shift
+// result.hi = hi>>s
+// result.lo = lo>>s | hi<<(32-s) | hi>>(s-32) // >> is unsigned, large shifts result 0
+(Rsh64Ux32 x s) =>
+ (Int64Make
+ (Rsh32Ux32 <typ.UInt32> (Int64Hi x) s)
+ (Or32 <typ.UInt32>
+ (Or32 <typ.UInt32>
+ (Rsh32Ux32 <typ.UInt32> (Int64Lo x) s)
+ (Lsh32x32 <typ.UInt32>
+ (Int64Hi x)
+ (Sub32 <typ.UInt32> (Const32 <typ.UInt32> [32]) s)))
+ (Rsh32Ux32 <typ.UInt32>
+ (Int64Hi x)
+ (Sub32 <typ.UInt32> s (Const32 <typ.UInt32> [32])))))
+(Rsh64Ux16 x s) =>
+ (Int64Make
+ (Rsh32Ux16 <typ.UInt32> (Int64Hi x) s)
+ (Or32 <typ.UInt32>
+ (Or32 <typ.UInt32>
+ (Rsh32Ux16 <typ.UInt32> (Int64Lo x) s)
+ (Lsh32x16 <typ.UInt32>
+ (Int64Hi x)
+ (Sub16 <typ.UInt16> (Const16 <typ.UInt16> [32]) s)))
+ (Rsh32Ux16 <typ.UInt32>
+ (Int64Hi x)
+ (Sub16 <typ.UInt16> s (Const16 <typ.UInt16> [32])))))
+(Rsh64Ux8 x s) =>
+ (Int64Make
+ (Rsh32Ux8 <typ.UInt32> (Int64Hi x) s)
+ (Or32 <typ.UInt32>
+ (Or32 <typ.UInt32>
+ (Rsh32Ux8 <typ.UInt32> (Int64Lo x) s)
+ (Lsh32x8 <typ.UInt32>
+ (Int64Hi x)
+ (Sub8 <typ.UInt8> (Const8 <typ.UInt8> [32]) s)))
+ (Rsh32Ux8 <typ.UInt32>
+ (Int64Hi x)
+ (Sub8 <typ.UInt8> s (Const8 <typ.UInt8> [32])))))
+
+// 64x signed right shift
+// result.hi = hi>>s
+// result.lo = lo>>s | hi<<(32-s) | (hi>>(s-32))&zeromask(s>>5) // hi>>(s-32) is signed, large shifts result 0/-1
+(Rsh64x32 x s) =>
+ (Int64Make
+ (Rsh32x32 <typ.UInt32> (Int64Hi x) s)
+ (Or32 <typ.UInt32>
+ (Or32 <typ.UInt32>
+ (Rsh32Ux32 <typ.UInt32> (Int64Lo x) s)
+ (Lsh32x32 <typ.UInt32>
+ (Int64Hi x)
+ (Sub32 <typ.UInt32> (Const32 <typ.UInt32> [32]) s)))
+ (And32 <typ.UInt32>
+ (Rsh32x32 <typ.UInt32>
+ (Int64Hi x)
+ (Sub32 <typ.UInt32> s (Const32 <typ.UInt32> [32])))
+ (Zeromask
+ (Rsh32Ux32 <typ.UInt32> s (Const32 <typ.UInt32> [5]))))))
+(Rsh64x16 x s) =>
+ (Int64Make
+ (Rsh32x16 <typ.UInt32> (Int64Hi x) s)
+ (Or32 <typ.UInt32>
+ (Or32 <typ.UInt32>
+ (Rsh32Ux16 <typ.UInt32> (Int64Lo x) s)
+ (Lsh32x16 <typ.UInt32>
+ (Int64Hi x)
+ (Sub16 <typ.UInt16> (Const16 <typ.UInt16> [32]) s)))
+ (And32 <typ.UInt32>
+ (Rsh32x16 <typ.UInt32>
+ (Int64Hi x)
+ (Sub16 <typ.UInt16> s (Const16 <typ.UInt16> [32])))
+ (Zeromask
+ (ZeroExt16to32
+ (Rsh16Ux32 <typ.UInt16> s (Const32 <typ.UInt32> [5])))))))
+(Rsh64x8 x s) =>
+ (Int64Make
+ (Rsh32x8 <typ.UInt32> (Int64Hi x) s)
+ (Or32 <typ.UInt32>
+ (Or32 <typ.UInt32>
+ (Rsh32Ux8 <typ.UInt32> (Int64Lo x) s)
+ (Lsh32x8 <typ.UInt32>
+ (Int64Hi x)
+ (Sub8 <typ.UInt8> (Const8 <typ.UInt8> [32]) s)))
+ (And32 <typ.UInt32>
+ (Rsh32x8 <typ.UInt32>
+ (Int64Hi x)
+ (Sub8 <typ.UInt8> s (Const8 <typ.UInt8> [32])))
+ (Zeromask
+ (ZeroExt8to32
+ (Rsh8Ux32 <typ.UInt8> s (Const32 <typ.UInt32> [5])))))))
+
+(Const64 <t> [c]) && t.IsSigned() =>
+ (Int64Make (Const32 <typ.Int32> [int32(c>>32)]) (Const32 <typ.UInt32> [int32(c)]))
+(Const64 <t> [c]) && !t.IsSigned() =>
+ (Int64Make (Const32 <typ.UInt32> [int32(c>>32)]) (Const32 <typ.UInt32> [int32(c)]))
+
+(Eq64 x y) =>
+ (AndB
+ (Eq32 (Int64Hi x) (Int64Hi y))
+ (Eq32 (Int64Lo x) (Int64Lo y)))
+
+(Neq64 x y) =>
+ (OrB
+ (Neq32 (Int64Hi x) (Int64Hi y))
+ (Neq32 (Int64Lo x) (Int64Lo y)))
+
+(Less64U x y) =>
+ (OrB
+ (Less32U (Int64Hi x) (Int64Hi y))
+ (AndB
+ (Eq32 (Int64Hi x) (Int64Hi y))
+ (Less32U (Int64Lo x) (Int64Lo y))))
+
+(Leq64U x y) =>
+ (OrB
+ (Less32U (Int64Hi x) (Int64Hi y))
+ (AndB
+ (Eq32 (Int64Hi x) (Int64Hi y))
+ (Leq32U (Int64Lo x) (Int64Lo y))))
+
+(Less64 x y) =>
+ (OrB
+ (Less32 (Int64Hi x) (Int64Hi y))
+ (AndB
+ (Eq32 (Int64Hi x) (Int64Hi y))
+ (Less32U (Int64Lo x) (Int64Lo y))))
+
+(Leq64 x y) =>
+ (OrB
+ (Less32 (Int64Hi x) (Int64Hi y))
+ (AndB
+ (Eq32 (Int64Hi x) (Int64Hi y))
+ (Leq32U (Int64Lo x) (Int64Lo y))))
diff --git a/src/cmd/compile/internal/ssa/gen/dec64Ops.go b/src/cmd/compile/internal/ssa/gen/dec64Ops.go
new file mode 100644
index 0000000..8c5883b
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/dec64Ops.go
@@ -0,0 +1,20 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+var dec64Ops = []opData{}
+
+var dec64Blocks = []blockData{}
+
+func init() {
+ archs = append(archs, arch{
+ name: "dec64",
+ ops: dec64Ops,
+ blocks: dec64Blocks,
+ generic: true,
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/decArgs.rules b/src/cmd/compile/internal/ssa/gen/decArgs.rules
new file mode 100644
index 0000000..1c9a0bb
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/decArgs.rules
@@ -0,0 +1,58 @@
+// Copyright 2018 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.
+
+// Decompose compound argument values
+// Do this early to simplify tracking names for debugging.
+
+(Arg {n} [off]) && v.Type.IsString() =>
+ (StringMake
+ (Arg <typ.BytePtr> {n} [off])
+ (Arg <typ.Int> {n} [off+int32(config.PtrSize)]))
+
+(Arg {n} [off]) && v.Type.IsSlice() =>
+ (SliceMake
+ (Arg <v.Type.Elem().PtrTo()> {n} [off])
+ (Arg <typ.Int> {n} [off+int32(config.PtrSize)])
+ (Arg <typ.Int> {n} [off+2*int32(config.PtrSize)]))
+
+(Arg {n} [off]) && v.Type.IsInterface() =>
+ (IMake
+ (Arg <typ.Uintptr> {n} [off])
+ (Arg <typ.BytePtr> {n} [off+int32(config.PtrSize)]))
+
+(Arg {n} [off]) && v.Type.IsComplex() && v.Type.Size() == 16 =>
+ (ComplexMake
+ (Arg <typ.Float64> {n} [off])
+ (Arg <typ.Float64> {n} [off+8]))
+
+(Arg {n} [off]) && v.Type.IsComplex() && v.Type.Size() == 8 =>
+ (ComplexMake
+ (Arg <typ.Float32> {n} [off])
+ (Arg <typ.Float32> {n} [off+4]))
+
+(Arg <t>) && t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t) =>
+ (StructMake0)
+(Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t) =>
+ (StructMake1
+ (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))]))
+(Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t) =>
+ (StructMake2
+ (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))])
+ (Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))]))
+(Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t) =>
+ (StructMake3
+ (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))])
+ (Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))])
+ (Arg <t.FieldType(2)> {n} [off+int32(t.FieldOff(2))]))
+(Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t) =>
+ (StructMake4
+ (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))])
+ (Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))])
+ (Arg <t.FieldType(2)> {n} [off+int32(t.FieldOff(2))])
+ (Arg <t.FieldType(3)> {n} [off+int32(t.FieldOff(3))]))
+
+(Arg <t>) && t.IsArray() && t.NumElem() == 0 =>
+ (ArrayMake0)
+(Arg <t> {n} [off]) && t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t) =>
+ (ArrayMake1 (Arg <t.Elem()> {n} [off]))
diff --git a/src/cmd/compile/internal/ssa/gen/decArgsOps.go b/src/cmd/compile/internal/ssa/gen/decArgsOps.go
new file mode 100644
index 0000000..b73d9d3
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/decArgsOps.go
@@ -0,0 +1,20 @@
+// Copyright 2018 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.
+
+// +build ignore
+
+package main
+
+var decArgsOps = []opData{}
+
+var decArgsBlocks = []blockData{}
+
+func init() {
+ archs = append(archs, arch{
+ name: "decArgs",
+ ops: decArgsOps,
+ blocks: decArgsBlocks,
+ generic: true,
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/decOps.go b/src/cmd/compile/internal/ssa/gen/decOps.go
new file mode 100644
index 0000000..b826481
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/decOps.go
@@ -0,0 +1,20 @@
+// 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.
+
+// +build ignore
+
+package main
+
+var decOps = []opData{}
+
+var decBlocks = []blockData{}
+
+func init() {
+ archs = append(archs, arch{
+ name: "dec",
+ ops: decOps,
+ blocks: decBlocks,
+ generic: true,
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules
new file mode 100644
index 0000000..1784923
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/generic.rules
@@ -0,0 +1,2535 @@
+// 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.
+
+// Simplifications that apply to all backend architectures. As an example, this
+// Go source code
+//
+// y := 0 * x
+//
+// can be translated into y := 0 without losing any information, which saves a
+// pointless multiplication instruction. Other .rules files in this directory
+// (for example AMD64.rules) contain rules specific to the architecture in the
+// filename. The rules here apply to every architecture.
+//
+// The code for parsing this file lives in rulegen.go; this file generates
+// ssa/rewritegeneric.go.
+
+// values are specified using the following format:
+// (op <type> [auxint] {aux} arg0 arg1 ...)
+// the type, aux, and auxint fields are optional
+// on the matching side
+// - the type, aux, and auxint fields must match if they are specified.
+// - the first occurrence of a variable defines that variable. Subsequent
+// uses must match (be == to) the first use.
+// - v is defined to be the value matched.
+// - an additional conditional can be provided after the match pattern with "&&".
+// on the generated side
+// - the type of the top-level expression is the same as the one on the left-hand side.
+// - the type of any subexpressions must be specified explicitly (or
+// be specified in the op's type field).
+// - auxint will be 0 if not specified.
+// - aux will be nil if not specified.
+
+// blocks are specified using the following format:
+// (kind controlvalue succ0 succ1 ...)
+// controlvalue must be "nil" or a value expression
+// succ* fields must be variables
+// For now, the generated successors must be a permutation of the matched successors.
+
+// constant folding
+(Trunc16to8 (Const16 [c])) => (Const8 [int8(c)])
+(Trunc32to8 (Const32 [c])) => (Const8 [int8(c)])
+(Trunc32to16 (Const32 [c])) => (Const16 [int16(c)])
+(Trunc64to8 (Const64 [c])) => (Const8 [int8(c)])
+(Trunc64to16 (Const64 [c])) => (Const16 [int16(c)])
+(Trunc64to32 (Const64 [c])) => (Const32 [int32(c)])
+(Cvt64Fto32F (Const64F [c])) => (Const32F [float32(c)])
+(Cvt32Fto64F (Const32F [c])) => (Const64F [float64(c)])
+(Cvt32to32F (Const32 [c])) => (Const32F [float32(c)])
+(Cvt32to64F (Const32 [c])) => (Const64F [float64(c)])
+(Cvt64to32F (Const64 [c])) => (Const32F [float32(c)])
+(Cvt64to64F (Const64 [c])) => (Const64F [float64(c)])
+(Cvt32Fto32 (Const32F [c])) => (Const32 [int32(c)])
+(Cvt32Fto64 (Const32F [c])) => (Const64 [int64(c)])
+(Cvt64Fto32 (Const64F [c])) => (Const32 [int32(c)])
+(Cvt64Fto64 (Const64F [c])) => (Const64 [int64(c)])
+(Round32F x:(Const32F)) => x
+(Round64F x:(Const64F)) => x
+(CvtBoolToUint8 (ConstBool [false])) => (Const8 [0])
+(CvtBoolToUint8 (ConstBool [true])) => (Const8 [1])
+
+(Trunc16to8 (ZeroExt8to16 x)) => x
+(Trunc32to8 (ZeroExt8to32 x)) => x
+(Trunc32to16 (ZeroExt8to32 x)) => (ZeroExt8to16 x)
+(Trunc32to16 (ZeroExt16to32 x)) => x
+(Trunc64to8 (ZeroExt8to64 x)) => x
+(Trunc64to16 (ZeroExt8to64 x)) => (ZeroExt8to16 x)
+(Trunc64to16 (ZeroExt16to64 x)) => x
+(Trunc64to32 (ZeroExt8to64 x)) => (ZeroExt8to32 x)
+(Trunc64to32 (ZeroExt16to64 x)) => (ZeroExt16to32 x)
+(Trunc64to32 (ZeroExt32to64 x)) => x
+(Trunc16to8 (SignExt8to16 x)) => x
+(Trunc32to8 (SignExt8to32 x)) => x
+(Trunc32to16 (SignExt8to32 x)) => (SignExt8to16 x)
+(Trunc32to16 (SignExt16to32 x)) => x
+(Trunc64to8 (SignExt8to64 x)) => x
+(Trunc64to16 (SignExt8to64 x)) => (SignExt8to16 x)
+(Trunc64to16 (SignExt16to64 x)) => x
+(Trunc64to32 (SignExt8to64 x)) => (SignExt8to32 x)
+(Trunc64to32 (SignExt16to64 x)) => (SignExt16to32 x)
+(Trunc64to32 (SignExt32to64 x)) => x
+
+(ZeroExt8to16 (Const8 [c])) => (Const16 [int16( uint8(c))])
+(ZeroExt8to32 (Const8 [c])) => (Const32 [int32( uint8(c))])
+(ZeroExt8to64 (Const8 [c])) => (Const64 [int64( uint8(c))])
+(ZeroExt16to32 (Const16 [c])) => (Const32 [int32(uint16(c))])
+(ZeroExt16to64 (Const16 [c])) => (Const64 [int64(uint16(c))])
+(ZeroExt32to64 (Const32 [c])) => (Const64 [int64(uint32(c))])
+(SignExt8to16 (Const8 [c])) => (Const16 [int16(c)])
+(SignExt8to32 (Const8 [c])) => (Const32 [int32(c)])
+(SignExt8to64 (Const8 [c])) => (Const64 [int64(c)])
+(SignExt16to32 (Const16 [c])) => (Const32 [int32(c)])
+(SignExt16to64 (Const16 [c])) => (Const64 [int64(c)])
+(SignExt32to64 (Const32 [c])) => (Const64 [int64(c)])
+
+(Neg8 (Const8 [c])) => (Const8 [-c])
+(Neg16 (Const16 [c])) => (Const16 [-c])
+(Neg32 (Const32 [c])) => (Const32 [-c])
+(Neg64 (Const64 [c])) => (Const64 [-c])
+(Neg32F (Const32F [c])) && c != 0 => (Const32F [-c])
+(Neg64F (Const64F [c])) && c != 0 => (Const64F [-c])
+
+(Add8 (Const8 [c]) (Const8 [d])) => (Const8 [c+d])
+(Add16 (Const16 [c]) (Const16 [d])) => (Const16 [c+d])
+(Add32 (Const32 [c]) (Const32 [d])) => (Const32 [c+d])
+(Add64 (Const64 [c]) (Const64 [d])) => (Const64 [c+d])
+(Add32F (Const32F [c]) (Const32F [d])) && c+d == c+d => (Const32F [c+d])
+(Add64F (Const64F [c]) (Const64F [d])) && c+d == c+d => (Const64F [c+d])
+(AddPtr <t> x (Const64 [c])) => (OffPtr <t> x [c])
+(AddPtr <t> x (Const32 [c])) => (OffPtr <t> x [int64(c)])
+
+(Sub8 (Const8 [c]) (Const8 [d])) => (Const8 [c-d])
+(Sub16 (Const16 [c]) (Const16 [d])) => (Const16 [c-d])
+(Sub32 (Const32 [c]) (Const32 [d])) => (Const32 [c-d])
+(Sub64 (Const64 [c]) (Const64 [d])) => (Const64 [c-d])
+(Sub32F (Const32F [c]) (Const32F [d])) && c-d == c-d => (Const32F [c-d])
+(Sub64F (Const64F [c]) (Const64F [d])) && c-d == c-d => (Const64F [c-d])
+
+(Mul8 (Const8 [c]) (Const8 [d])) => (Const8 [c*d])
+(Mul16 (Const16 [c]) (Const16 [d])) => (Const16 [c*d])
+(Mul32 (Const32 [c]) (Const32 [d])) => (Const32 [c*d])
+(Mul64 (Const64 [c]) (Const64 [d])) => (Const64 [c*d])
+(Mul32F (Const32F [c]) (Const32F [d])) && c*d == c*d => (Const32F [c*d])
+(Mul64F (Const64F [c]) (Const64F [d])) && c*d == c*d => (Const64F [c*d])
+
+(And8 (Const8 [c]) (Const8 [d])) => (Const8 [c&d])
+(And16 (Const16 [c]) (Const16 [d])) => (Const16 [c&d])
+(And32 (Const32 [c]) (Const32 [d])) => (Const32 [c&d])
+(And64 (Const64 [c]) (Const64 [d])) => (Const64 [c&d])
+
+(Or8 (Const8 [c]) (Const8 [d])) => (Const8 [c|d])
+(Or16 (Const16 [c]) (Const16 [d])) => (Const16 [c|d])
+(Or32 (Const32 [c]) (Const32 [d])) => (Const32 [c|d])
+(Or64 (Const64 [c]) (Const64 [d])) => (Const64 [c|d])
+
+(Xor8 (Const8 [c]) (Const8 [d])) => (Const8 [c^d])
+(Xor16 (Const16 [c]) (Const16 [d])) => (Const16 [c^d])
+(Xor32 (Const32 [c]) (Const32 [d])) => (Const32 [c^d])
+(Xor64 (Const64 [c]) (Const64 [d])) => (Const64 [c^d])
+
+(Ctz64 (Const64 [c])) && config.PtrSize == 4 => (Const32 [int32(ntz64(c))])
+(Ctz32 (Const32 [c])) && config.PtrSize == 4 => (Const32 [int32(ntz32(c))])
+(Ctz16 (Const16 [c])) && config.PtrSize == 4 => (Const32 [int32(ntz16(c))])
+(Ctz8 (Const8 [c])) && config.PtrSize == 4 => (Const32 [int32(ntz8(c))])
+
+(Ctz64 (Const64 [c])) && config.PtrSize == 8 => (Const64 [int64(ntz64(c))])
+(Ctz32 (Const32 [c])) && config.PtrSize == 8 => (Const64 [int64(ntz32(c))])
+(Ctz16 (Const16 [c])) && config.PtrSize == 8 => (Const64 [int64(ntz16(c))])
+(Ctz8 (Const8 [c])) && config.PtrSize == 8 => (Const64 [int64(ntz8(c))])
+
+(Div8 (Const8 [c]) (Const8 [d])) && d != 0 => (Const8 [c/d])
+(Div16 (Const16 [c]) (Const16 [d])) && d != 0 => (Const16 [c/d])
+(Div32 (Const32 [c]) (Const32 [d])) && d != 0 => (Const32 [c/d])
+(Div64 (Const64 [c]) (Const64 [d])) && d != 0 => (Const64 [c/d])
+(Div8u (Const8 [c]) (Const8 [d])) && d != 0 => (Const8 [int8(uint8(c)/uint8(d))])
+(Div16u (Const16 [c]) (Const16 [d])) && d != 0 => (Const16 [int16(uint16(c)/uint16(d))])
+(Div32u (Const32 [c]) (Const32 [d])) && d != 0 => (Const32 [int32(uint32(c)/uint32(d))])
+(Div64u (Const64 [c]) (Const64 [d])) && d != 0 => (Const64 [int64(uint64(c)/uint64(d))])
+(Div32F (Const32F [c]) (Const32F [d])) && c/d == c/d => (Const32F [c/d])
+(Div64F (Const64F [c]) (Const64F [d])) && c/d == c/d => (Const64F [c/d])
+(Select0 (Div128u (Const64 [0]) lo y)) => (Div64u lo y)
+(Select1 (Div128u (Const64 [0]) lo y)) => (Mod64u lo y)
+
+(Not (ConstBool [c])) => (ConstBool [!c])
+
+// Convert x * 1 to x.
+(Mul(8|16|32|64) (Const(8|16|32|64) [1]) x) => x
+
+// Convert x * -1 to -x.
+(Mul(8|16|32|64) (Const(8|16|32|64) [-1]) x) => (Neg(8|16|32|64) x)
+
+// Convert multiplication by a power of two to a shift.
+(Mul8 <t> n (Const8 [c])) && isPowerOfTwo8(c) => (Lsh8x64 <t> n (Const64 <typ.UInt64> [log8(c)]))
+(Mul16 <t> n (Const16 [c])) && isPowerOfTwo16(c) => (Lsh16x64 <t> n (Const64 <typ.UInt64> [log16(c)]))
+(Mul32 <t> n (Const32 [c])) && isPowerOfTwo32(c) => (Lsh32x64 <t> n (Const64 <typ.UInt64> [log32(c)]))
+(Mul64 <t> n (Const64 [c])) && isPowerOfTwo64(c) => (Lsh64x64 <t> n (Const64 <typ.UInt64> [log64(c)]))
+(Mul8 <t> n (Const8 [c])) && t.IsSigned() && isPowerOfTwo8(-c) => (Neg8 (Lsh8x64 <t> n (Const64 <typ.UInt64> [log8(-c)])))
+(Mul16 <t> n (Const16 [c])) && t.IsSigned() && isPowerOfTwo16(-c) => (Neg16 (Lsh16x64 <t> n (Const64 <typ.UInt64> [log16(-c)])))
+(Mul32 <t> n (Const32 [c])) && t.IsSigned() && isPowerOfTwo32(-c) => (Neg32 (Lsh32x64 <t> n (Const64 <typ.UInt64> [log32(-c)])))
+(Mul64 <t> n (Const64 [c])) && t.IsSigned() && isPowerOfTwo64(-c) => (Neg64 (Lsh64x64 <t> n (Const64 <typ.UInt64> [log64(-c)])))
+
+(Mod8 (Const8 [c]) (Const8 [d])) && d != 0 => (Const8 [c % d])
+(Mod16 (Const16 [c]) (Const16 [d])) && d != 0 => (Const16 [c % d])
+(Mod32 (Const32 [c]) (Const32 [d])) && d != 0 => (Const32 [c % d])
+(Mod64 (Const64 [c]) (Const64 [d])) && d != 0 => (Const64 [c % d])
+
+(Mod8u (Const8 [c]) (Const8 [d])) && d != 0 => (Const8 [int8(uint8(c) % uint8(d))])
+(Mod16u (Const16 [c]) (Const16 [d])) && d != 0 => (Const16 [int16(uint16(c) % uint16(d))])
+(Mod32u (Const32 [c]) (Const32 [d])) && d != 0 => (Const32 [int32(uint32(c) % uint32(d))])
+(Mod64u (Const64 [c]) (Const64 [d])) && d != 0 => (Const64 [int64(uint64(c) % uint64(d))])
+
+(Lsh64x64 (Const64 [c]) (Const64 [d])) => (Const64 [c << uint64(d)])
+(Rsh64x64 (Const64 [c]) (Const64 [d])) => (Const64 [c >> uint64(d)])
+(Rsh64Ux64 (Const64 [c]) (Const64 [d])) => (Const64 [int64(uint64(c) >> uint64(d))])
+(Lsh32x64 (Const32 [c]) (Const64 [d])) => (Const32 [c << uint64(d)])
+(Rsh32x64 (Const32 [c]) (Const64 [d])) => (Const32 [c >> uint64(d)])
+(Rsh32Ux64 (Const32 [c]) (Const64 [d])) => (Const32 [int32(uint32(c) >> uint64(d))])
+(Lsh16x64 (Const16 [c]) (Const64 [d])) => (Const16 [c << uint64(d)])
+(Rsh16x64 (Const16 [c]) (Const64 [d])) => (Const16 [c >> uint64(d)])
+(Rsh16Ux64 (Const16 [c]) (Const64 [d])) => (Const16 [int16(uint16(c) >> uint64(d))])
+(Lsh8x64 (Const8 [c]) (Const64 [d])) => (Const8 [c << uint64(d)])
+(Rsh8x64 (Const8 [c]) (Const64 [d])) => (Const8 [c >> uint64(d)])
+(Rsh8Ux64 (Const8 [c]) (Const64 [d])) => (Const8 [int8(uint8(c) >> uint64(d))])
+
+// Fold IsInBounds when the range of the index cannot exceed the limit.
+(IsInBounds (ZeroExt8to32 _) (Const32 [c])) && (1 << 8) <= c => (ConstBool [true])
+(IsInBounds (ZeroExt8to64 _) (Const64 [c])) && (1 << 8) <= c => (ConstBool [true])
+(IsInBounds (ZeroExt16to32 _) (Const32 [c])) && (1 << 16) <= c => (ConstBool [true])
+(IsInBounds (ZeroExt16to64 _) (Const64 [c])) && (1 << 16) <= c => (ConstBool [true])
+(IsInBounds x x) => (ConstBool [false])
+(IsInBounds (And8 (Const8 [c]) _) (Const8 [d])) && 0 <= c && c < d => (ConstBool [true])
+(IsInBounds (ZeroExt8to16 (And8 (Const8 [c]) _)) (Const16 [d])) && 0 <= c && int16(c) < d => (ConstBool [true])
+(IsInBounds (ZeroExt8to32 (And8 (Const8 [c]) _)) (Const32 [d])) && 0 <= c && int32(c) < d => (ConstBool [true])
+(IsInBounds (ZeroExt8to64 (And8 (Const8 [c]) _)) (Const64 [d])) && 0 <= c && int64(c) < d => (ConstBool [true])
+(IsInBounds (And16 (Const16 [c]) _) (Const16 [d])) && 0 <= c && c < d => (ConstBool [true])
+(IsInBounds (ZeroExt16to32 (And16 (Const16 [c]) _)) (Const32 [d])) && 0 <= c && int32(c) < d => (ConstBool [true])
+(IsInBounds (ZeroExt16to64 (And16 (Const16 [c]) _)) (Const64 [d])) && 0 <= c && int64(c) < d => (ConstBool [true])
+(IsInBounds (And32 (Const32 [c]) _) (Const32 [d])) && 0 <= c && c < d => (ConstBool [true])
+(IsInBounds (ZeroExt32to64 (And32 (Const32 [c]) _)) (Const64 [d])) && 0 <= c && int64(c) < d => (ConstBool [true])
+(IsInBounds (And64 (Const64 [c]) _) (Const64 [d])) && 0 <= c && c < d => (ConstBool [true])
+(IsInBounds (Const32 [c]) (Const32 [d])) => (ConstBool [0 <= c && c < d])
+(IsInBounds (Const64 [c]) (Const64 [d])) => (ConstBool [0 <= c && c < d])
+// (Mod64u x y) is always between 0 (inclusive) and y (exclusive).
+(IsInBounds (Mod32u _ y) y) => (ConstBool [true])
+(IsInBounds (Mod64u _ y) y) => (ConstBool [true])
+// Right shifting an unsigned number limits its value.
+(IsInBounds (ZeroExt8to64 (Rsh8Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 8 && 1<<uint( 8-c)-1 < d => (ConstBool [true])
+(IsInBounds (ZeroExt8to32 (Rsh8Ux64 _ (Const64 [c]))) (Const32 [d])) && 0 < c && c < 8 && 1<<uint( 8-c)-1 < d => (ConstBool [true])
+(IsInBounds (ZeroExt8to16 (Rsh8Ux64 _ (Const64 [c]))) (Const16 [d])) && 0 < c && c < 8 && 1<<uint( 8-c)-1 < d => (ConstBool [true])
+(IsInBounds (Rsh8Ux64 _ (Const64 [c])) (Const64 [d])) && 0 < c && c < 8 && 1<<uint( 8-c)-1 < d => (ConstBool [true])
+(IsInBounds (ZeroExt16to64 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 16 && 1<<uint(16-c)-1 < d => (ConstBool [true])
+(IsInBounds (ZeroExt16to32 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 16 && 1<<uint(16-c)-1 < d => (ConstBool [true])
+(IsInBounds (Rsh16Ux64 _ (Const64 [c])) (Const64 [d])) && 0 < c && c < 16 && 1<<uint(16-c)-1 < d => (ConstBool [true])
+(IsInBounds (ZeroExt32to64 (Rsh32Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 32 && 1<<uint(32-c)-1 < d => (ConstBool [true])
+(IsInBounds (Rsh32Ux64 _ (Const64 [c])) (Const64 [d])) && 0 < c && c < 32 && 1<<uint(32-c)-1 < d => (ConstBool [true])
+(IsInBounds (Rsh64Ux64 _ (Const64 [c])) (Const64 [d])) && 0 < c && c < 64 && 1<<uint(64-c)-1 < d => (ConstBool [true])
+
+(IsSliceInBounds x x) => (ConstBool [true])
+(IsSliceInBounds (And32 (Const32 [c]) _) (Const32 [d])) && 0 <= c && c <= d => (ConstBool [true])
+(IsSliceInBounds (And64 (Const64 [c]) _) (Const64 [d])) && 0 <= c && c <= d => (ConstBool [true])
+(IsSliceInBounds (Const32 [0]) _) => (ConstBool [true])
+(IsSliceInBounds (Const64 [0]) _) => (ConstBool [true])
+(IsSliceInBounds (Const32 [c]) (Const32 [d])) => (ConstBool [0 <= c && c <= d])
+(IsSliceInBounds (Const64 [c]) (Const64 [d])) => (ConstBool [0 <= c && c <= d])
+(IsSliceInBounds (SliceLen x) (SliceCap x)) => (ConstBool [true])
+
+(Eq(64|32|16|8) x x) => (ConstBool [true])
+(EqB (ConstBool [c]) (ConstBool [d])) => (ConstBool [c == d])
+(EqB (ConstBool [false]) x) => (Not x)
+(EqB (ConstBool [true]) x) => x
+
+(Neq(64|32|16|8) x x) => (ConstBool [false])
+(NeqB (ConstBool [c]) (ConstBool [d])) => (ConstBool [c != d])
+(NeqB (ConstBool [false]) x) => x
+(NeqB (ConstBool [true]) x) => (Not x)
+(NeqB (Not x) (Not y)) => (NeqB x y)
+
+(Eq64 (Const64 <t> [c]) (Add64 (Const64 <t> [d]) x)) => (Eq64 (Const64 <t> [c-d]) x)
+(Eq32 (Const32 <t> [c]) (Add32 (Const32 <t> [d]) x)) => (Eq32 (Const32 <t> [c-d]) x)
+(Eq16 (Const16 <t> [c]) (Add16 (Const16 <t> [d]) x)) => (Eq16 (Const16 <t> [c-d]) x)
+(Eq8 (Const8 <t> [c]) (Add8 (Const8 <t> [d]) x)) => (Eq8 (Const8 <t> [c-d]) x)
+
+(Neq64 (Const64 <t> [c]) (Add64 (Const64 <t> [d]) x)) => (Neq64 (Const64 <t> [c-d]) x)
+(Neq32 (Const32 <t> [c]) (Add32 (Const32 <t> [d]) x)) => (Neq32 (Const32 <t> [c-d]) x)
+(Neq16 (Const16 <t> [c]) (Add16 (Const16 <t> [d]) x)) => (Neq16 (Const16 <t> [c-d]) x)
+(Neq8 (Const8 <t> [c]) (Add8 (Const8 <t> [d]) x)) => (Neq8 (Const8 <t> [c-d]) x)
+
+// signed integer range: ( c <= x && x (<|<=) d ) -> ( unsigned(x-c) (<|<=) unsigned(d-c) )
+(AndB (Leq64 (Const64 [c]) x) ((Less|Leq)64 x (Const64 [d]))) && d >= c => ((Less|Leq)64U (Sub64 <x.Type> x (Const64 <x.Type> [c])) (Const64 <x.Type> [d-c]))
+(AndB (Leq32 (Const32 [c]) x) ((Less|Leq)32 x (Const32 [d]))) && d >= c => ((Less|Leq)32U (Sub32 <x.Type> x (Const32 <x.Type> [c])) (Const32 <x.Type> [d-c]))
+(AndB (Leq16 (Const16 [c]) x) ((Less|Leq)16 x (Const16 [d]))) && d >= c => ((Less|Leq)16U (Sub16 <x.Type> x (Const16 <x.Type> [c])) (Const16 <x.Type> [d-c]))
+(AndB (Leq8 (Const8 [c]) x) ((Less|Leq)8 x (Const8 [d]))) && d >= c => ((Less|Leq)8U (Sub8 <x.Type> x (Const8 <x.Type> [c])) (Const8 <x.Type> [d-c]))
+
+// signed integer range: ( c < x && x (<|<=) d ) -> ( unsigned(x-(c+1)) (<|<=) unsigned(d-(c+1)) )
+(AndB (Less64 (Const64 [c]) x) ((Less|Leq)64 x (Const64 [d]))) && d >= c+1 && c+1 > c => ((Less|Leq)64U (Sub64 <x.Type> x (Const64 <x.Type> [c+1])) (Const64 <x.Type> [d-c-1]))
+(AndB (Less32 (Const32 [c]) x) ((Less|Leq)32 x (Const32 [d]))) && d >= c+1 && c+1 > c => ((Less|Leq)32U (Sub32 <x.Type> x (Const32 <x.Type> [c+1])) (Const32 <x.Type> [d-c-1]))
+(AndB (Less16 (Const16 [c]) x) ((Less|Leq)16 x (Const16 [d]))) && d >= c+1 && c+1 > c => ((Less|Leq)16U (Sub16 <x.Type> x (Const16 <x.Type> [c+1])) (Const16 <x.Type> [d-c-1]))
+(AndB (Less8 (Const8 [c]) x) ((Less|Leq)8 x (Const8 [d]))) && d >= c+1 && c+1 > c => ((Less|Leq)8U (Sub8 <x.Type> x (Const8 <x.Type> [c+1])) (Const8 <x.Type> [d-c-1]))
+
+// unsigned integer range: ( c <= x && x (<|<=) d ) -> ( x-c (<|<=) d-c )
+(AndB (Leq64U (Const64 [c]) x) ((Less|Leq)64U x (Const64 [d]))) && uint64(d) >= uint64(c) => ((Less|Leq)64U (Sub64 <x.Type> x (Const64 <x.Type> [c])) (Const64 <x.Type> [d-c]))
+(AndB (Leq32U (Const32 [c]) x) ((Less|Leq)32U x (Const32 [d]))) && uint32(d) >= uint32(c) => ((Less|Leq)32U (Sub32 <x.Type> x (Const32 <x.Type> [c])) (Const32 <x.Type> [d-c]))
+(AndB (Leq16U (Const16 [c]) x) ((Less|Leq)16U x (Const16 [d]))) && uint16(d) >= uint16(c) => ((Less|Leq)16U (Sub16 <x.Type> x (Const16 <x.Type> [c])) (Const16 <x.Type> [d-c]))
+(AndB (Leq8U (Const8 [c]) x) ((Less|Leq)8U x (Const8 [d]))) && uint8(d) >= uint8(c) => ((Less|Leq)8U (Sub8 <x.Type> x (Const8 <x.Type> [c])) (Const8 <x.Type> [d-c]))
+
+// unsigned integer range: ( c < x && x (<|<=) d ) -> ( x-(c+1) (<|<=) d-(c+1) )
+(AndB (Less64U (Const64 [c]) x) ((Less|Leq)64U x (Const64 [d]))) && uint64(d) >= uint64(c+1) && uint64(c+1) > uint64(c) => ((Less|Leq)64U (Sub64 <x.Type> x (Const64 <x.Type> [c+1])) (Const64 <x.Type> [d-c-1]))
+(AndB (Less32U (Const32 [c]) x) ((Less|Leq)32U x (Const32 [d]))) && uint32(d) >= uint32(c+1) && uint32(c+1) > uint32(c) => ((Less|Leq)32U (Sub32 <x.Type> x (Const32 <x.Type> [c+1])) (Const32 <x.Type> [d-c-1]))
+(AndB (Less16U (Const16 [c]) x) ((Less|Leq)16U x (Const16 [d]))) && uint16(d) >= uint16(c+1) && uint16(c+1) > uint16(c) => ((Less|Leq)16U (Sub16 <x.Type> x (Const16 <x.Type> [c+1])) (Const16 <x.Type> [d-c-1]))
+(AndB (Less8U (Const8 [c]) x) ((Less|Leq)8U x (Const8 [d]))) && uint8(d) >= uint8(c+1) && uint8(c+1) > uint8(c) => ((Less|Leq)8U (Sub8 <x.Type> x (Const8 <x.Type> [c+1])) (Const8 <x.Type> [d-c-1]))
+
+// signed integer range: ( c (<|<=) x || x < d ) -> ( unsigned(c-d) (<|<=) unsigned(x-d) )
+(OrB ((Less|Leq)64 (Const64 [c]) x) (Less64 x (Const64 [d]))) && c >= d => ((Less|Leq)64U (Const64 <x.Type> [c-d]) (Sub64 <x.Type> x (Const64 <x.Type> [d])))
+(OrB ((Less|Leq)32 (Const32 [c]) x) (Less32 x (Const32 [d]))) && c >= d => ((Less|Leq)32U (Const32 <x.Type> [c-d]) (Sub32 <x.Type> x (Const32 <x.Type> [d])))
+(OrB ((Less|Leq)16 (Const16 [c]) x) (Less16 x (Const16 [d]))) && c >= d => ((Less|Leq)16U (Const16 <x.Type> [c-d]) (Sub16 <x.Type> x (Const16 <x.Type> [d])))
+(OrB ((Less|Leq)8 (Const8 [c]) x) (Less8 x (Const8 [d]))) && c >= d => ((Less|Leq)8U (Const8 <x.Type> [c-d]) (Sub8 <x.Type> x (Const8 <x.Type> [d])))
+
+// signed integer range: ( c (<|<=) x || x <= d ) -> ( unsigned(c-(d+1)) (<|<=) unsigned(x-(d+1)) )
+(OrB ((Less|Leq)64 (Const64 [c]) x) (Leq64 x (Const64 [d]))) && c >= d+1 && d+1 > d => ((Less|Leq)64U (Const64 <x.Type> [c-d-1]) (Sub64 <x.Type> x (Const64 <x.Type> [d+1])))
+(OrB ((Less|Leq)32 (Const32 [c]) x) (Leq32 x (Const32 [d]))) && c >= d+1 && d+1 > d => ((Less|Leq)32U (Const32 <x.Type> [c-d-1]) (Sub32 <x.Type> x (Const32 <x.Type> [d+1])))
+(OrB ((Less|Leq)16 (Const16 [c]) x) (Leq16 x (Const16 [d]))) && c >= d+1 && d+1 > d => ((Less|Leq)16U (Const16 <x.Type> [c-d-1]) (Sub16 <x.Type> x (Const16 <x.Type> [d+1])))
+(OrB ((Less|Leq)8 (Const8 [c]) x) (Leq8 x (Const8 [d]))) && c >= d+1 && d+1 > d => ((Less|Leq)8U (Const8 <x.Type> [c-d-1]) (Sub8 <x.Type> x (Const8 <x.Type> [d+1])))
+
+// unsigned integer range: ( c (<|<=) x || x < d ) -> ( c-d (<|<=) x-d )
+(OrB ((Less|Leq)64U (Const64 [c]) x) (Less64U x (Const64 [d]))) && uint64(c) >= uint64(d) => ((Less|Leq)64U (Const64 <x.Type> [c-d]) (Sub64 <x.Type> x (Const64 <x.Type> [d])))
+(OrB ((Less|Leq)32U (Const32 [c]) x) (Less32U x (Const32 [d]))) && uint32(c) >= uint32(d) => ((Less|Leq)32U (Const32 <x.Type> [c-d]) (Sub32 <x.Type> x (Const32 <x.Type> [d])))
+(OrB ((Less|Leq)16U (Const16 [c]) x) (Less16U x (Const16 [d]))) && uint16(c) >= uint16(d) => ((Less|Leq)16U (Const16 <x.Type> [c-d]) (Sub16 <x.Type> x (Const16 <x.Type> [d])))
+(OrB ((Less|Leq)8U (Const8 [c]) x) (Less8U x (Const8 [d]))) && uint8(c) >= uint8(d) => ((Less|Leq)8U (Const8 <x.Type> [c-d]) (Sub8 <x.Type> x (Const8 <x.Type> [d])))
+
+// unsigned integer range: ( c (<|<=) x || x <= d ) -> ( c-(d+1) (<|<=) x-(d+1) )
+(OrB ((Less|Leq)64U (Const64 [c]) x) (Leq64U x (Const64 [d]))) && uint64(c) >= uint64(d+1) && uint64(d+1) > uint64(d) => ((Less|Leq)64U (Const64 <x.Type> [c-d-1]) (Sub64 <x.Type> x (Const64 <x.Type> [d+1])))
+(OrB ((Less|Leq)32U (Const32 [c]) x) (Leq32U x (Const32 [d]))) && uint32(c) >= uint32(d+1) && uint32(d+1) > uint32(d) => ((Less|Leq)32U (Const32 <x.Type> [c-d-1]) (Sub32 <x.Type> x (Const32 <x.Type> [d+1])))
+(OrB ((Less|Leq)16U (Const16 [c]) x) (Leq16U x (Const16 [d]))) && uint16(c) >= uint16(d+1) && uint16(d+1) > uint16(d) => ((Less|Leq)16U (Const16 <x.Type> [c-d-1]) (Sub16 <x.Type> x (Const16 <x.Type> [d+1])))
+(OrB ((Less|Leq)8U (Const8 [c]) x) (Leq8U x (Const8 [d]))) && uint8(c) >= uint8(d+1) && uint8(d+1) > uint8(d) => ((Less|Leq)8U (Const8 <x.Type> [c-d-1]) (Sub8 <x.Type> x (Const8 <x.Type> [d+1])))
+
+// Canonicalize x-const to x+(-const)
+(Sub64 x (Const64 <t> [c])) && x.Op != OpConst64 => (Add64 (Const64 <t> [-c]) x)
+(Sub32 x (Const32 <t> [c])) && x.Op != OpConst32 => (Add32 (Const32 <t> [-c]) x)
+(Sub16 x (Const16 <t> [c])) && x.Op != OpConst16 => (Add16 (Const16 <t> [-c]) x)
+(Sub8 x (Const8 <t> [c])) && x.Op != OpConst8 => (Add8 (Const8 <t> [-c]) x)
+
+// fold negation into comparison operators
+(Not (Eq(64|32|16|8|B|Ptr|64F|32F) x y)) => (Neq(64|32|16|8|B|Ptr|64F|32F) x y)
+(Not (Neq(64|32|16|8|B|Ptr|64F|32F) x y)) => (Eq(64|32|16|8|B|Ptr|64F|32F) x y)
+
+(Not (Less(64|32|16|8) x y)) => (Leq(64|32|16|8) y x)
+(Not (Less(64|32|16|8)U x y)) => (Leq(64|32|16|8)U y x)
+(Not (Leq(64|32|16|8) x y)) => (Less(64|32|16|8) y x)
+(Not (Leq(64|32|16|8)U x y)) => (Less(64|32|16|8)U y x)
+
+// Distribute multiplication c * (d+x) -> c*d + c*x. Useful for:
+// a[i].b = ...; a[i+1].b = ...
+(Mul64 (Const64 <t> [c]) (Add64 <t> (Const64 <t> [d]) x)) =>
+ (Add64 (Const64 <t> [c*d]) (Mul64 <t> (Const64 <t> [c]) x))
+(Mul32 (Const32 <t> [c]) (Add32 <t> (Const32 <t> [d]) x)) =>
+ (Add32 (Const32 <t> [c*d]) (Mul32 <t> (Const32 <t> [c]) x))
+
+// Rewrite x*y ± x*z to x*(y±z)
+(Add(64|32|16|8) <t> (Mul(64|32|16|8) x y) (Mul(64|32|16|8) x z))
+ => (Mul(64|32|16|8) x (Add(64|32|16|8) <t> y z))
+(Sub(64|32|16|8) <t> (Mul(64|32|16|8) x y) (Mul(64|32|16|8) x z))
+ => (Mul(64|32|16|8) x (Sub(64|32|16|8) <t> y z))
+
+// rewrite shifts of 8/16/32 bit consts into 64 bit consts to reduce
+// the number of the other rewrite rules for const shifts
+(Lsh64x32 <t> x (Const32 [c])) => (Lsh64x64 x (Const64 <t> [int64(uint32(c))]))
+(Lsh64x16 <t> x (Const16 [c])) => (Lsh64x64 x (Const64 <t> [int64(uint16(c))]))
+(Lsh64x8 <t> x (Const8 [c])) => (Lsh64x64 x (Const64 <t> [int64(uint8(c))]))
+(Rsh64x32 <t> x (Const32 [c])) => (Rsh64x64 x (Const64 <t> [int64(uint32(c))]))
+(Rsh64x16 <t> x (Const16 [c])) => (Rsh64x64 x (Const64 <t> [int64(uint16(c))]))
+(Rsh64x8 <t> x (Const8 [c])) => (Rsh64x64 x (Const64 <t> [int64(uint8(c))]))
+(Rsh64Ux32 <t> x (Const32 [c])) => (Rsh64Ux64 x (Const64 <t> [int64(uint32(c))]))
+(Rsh64Ux16 <t> x (Const16 [c])) => (Rsh64Ux64 x (Const64 <t> [int64(uint16(c))]))
+(Rsh64Ux8 <t> x (Const8 [c])) => (Rsh64Ux64 x (Const64 <t> [int64(uint8(c))]))
+
+(Lsh32x32 <t> x (Const32 [c])) => (Lsh32x64 x (Const64 <t> [int64(uint32(c))]))
+(Lsh32x16 <t> x (Const16 [c])) => (Lsh32x64 x (Const64 <t> [int64(uint16(c))]))
+(Lsh32x8 <t> x (Const8 [c])) => (Lsh32x64 x (Const64 <t> [int64(uint8(c))]))
+(Rsh32x32 <t> x (Const32 [c])) => (Rsh32x64 x (Const64 <t> [int64(uint32(c))]))
+(Rsh32x16 <t> x (Const16 [c])) => (Rsh32x64 x (Const64 <t> [int64(uint16(c))]))
+(Rsh32x8 <t> x (Const8 [c])) => (Rsh32x64 x (Const64 <t> [int64(uint8(c))]))
+(Rsh32Ux32 <t> x (Const32 [c])) => (Rsh32Ux64 x (Const64 <t> [int64(uint32(c))]))
+(Rsh32Ux16 <t> x (Const16 [c])) => (Rsh32Ux64 x (Const64 <t> [int64(uint16(c))]))
+(Rsh32Ux8 <t> x (Const8 [c])) => (Rsh32Ux64 x (Const64 <t> [int64(uint8(c))]))
+
+(Lsh16x32 <t> x (Const32 [c])) => (Lsh16x64 x (Const64 <t> [int64(uint32(c))]))
+(Lsh16x16 <t> x (Const16 [c])) => (Lsh16x64 x (Const64 <t> [int64(uint16(c))]))
+(Lsh16x8 <t> x (Const8 [c])) => (Lsh16x64 x (Const64 <t> [int64(uint8(c))]))
+(Rsh16x32 <t> x (Const32 [c])) => (Rsh16x64 x (Const64 <t> [int64(uint32(c))]))
+(Rsh16x16 <t> x (Const16 [c])) => (Rsh16x64 x (Const64 <t> [int64(uint16(c))]))
+(Rsh16x8 <t> x (Const8 [c])) => (Rsh16x64 x (Const64 <t> [int64(uint8(c))]))
+(Rsh16Ux32 <t> x (Const32 [c])) => (Rsh16Ux64 x (Const64 <t> [int64(uint32(c))]))
+(Rsh16Ux16 <t> x (Const16 [c])) => (Rsh16Ux64 x (Const64 <t> [int64(uint16(c))]))
+(Rsh16Ux8 <t> x (Const8 [c])) => (Rsh16Ux64 x (Const64 <t> [int64(uint8(c))]))
+
+(Lsh8x32 <t> x (Const32 [c])) => (Lsh8x64 x (Const64 <t> [int64(uint32(c))]))
+(Lsh8x16 <t> x (Const16 [c])) => (Lsh8x64 x (Const64 <t> [int64(uint16(c))]))
+(Lsh8x8 <t> x (Const8 [c])) => (Lsh8x64 x (Const64 <t> [int64(uint8(c))]))
+(Rsh8x32 <t> x (Const32 [c])) => (Rsh8x64 x (Const64 <t> [int64(uint32(c))]))
+(Rsh8x16 <t> x (Const16 [c])) => (Rsh8x64 x (Const64 <t> [int64(uint16(c))]))
+(Rsh8x8 <t> x (Const8 [c])) => (Rsh8x64 x (Const64 <t> [int64(uint8(c))]))
+(Rsh8Ux32 <t> x (Const32 [c])) => (Rsh8Ux64 x (Const64 <t> [int64(uint32(c))]))
+(Rsh8Ux16 <t> x (Const16 [c])) => (Rsh8Ux64 x (Const64 <t> [int64(uint16(c))]))
+(Rsh8Ux8 <t> x (Const8 [c])) => (Rsh8Ux64 x (Const64 <t> [int64(uint8(c))]))
+
+// shifts by zero
+(Lsh(64|32|16|8)x64 x (Const64 [0])) => x
+(Rsh(64|32|16|8)x64 x (Const64 [0])) => x
+(Rsh(64|32|16|8)Ux64 x (Const64 [0])) => x
+
+// rotates by multiples of register width
+(RotateLeft64 x (Const64 [c])) && c%64 == 0 => x
+(RotateLeft32 x (Const32 [c])) && c%32 == 0 => x
+(RotateLeft16 x (Const16 [c])) && c%16 == 0 => x
+(RotateLeft8 x (Const8 [c])) && c%8 == 0 => x
+
+// zero shifted
+(Lsh64x(64|32|16|8) (Const64 [0]) _) => (Const64 [0])
+(Rsh64x(64|32|16|8) (Const64 [0]) _) => (Const64 [0])
+(Rsh64Ux(64|32|16|8) (Const64 [0]) _) => (Const64 [0])
+(Lsh32x(64|32|16|8) (Const32 [0]) _) => (Const32 [0])
+(Rsh32x(64|32|16|8) (Const32 [0]) _) => (Const32 [0])
+(Rsh32Ux(64|32|16|8) (Const32 [0]) _) => (Const32 [0])
+(Lsh16x(64|32|16|8) (Const16 [0]) _) => (Const16 [0])
+(Rsh16x(64|32|16|8) (Const16 [0]) _) => (Const16 [0])
+(Rsh16Ux(64|32|16|8) (Const16 [0]) _) => (Const16 [0])
+(Lsh8x(64|32|16|8) (Const8 [0]) _) => (Const8 [0])
+(Rsh8x(64|32|16|8) (Const8 [0]) _) => (Const8 [0])
+(Rsh8Ux(64|32|16|8) (Const8 [0]) _) => (Const8 [0])
+
+// large left shifts of all values, and right shifts of unsigned values
+((Lsh64|Rsh64U)x64 _ (Const64 [c])) && uint64(c) >= 64 => (Const64 [0])
+((Lsh32|Rsh32U)x64 _ (Const64 [c])) && uint64(c) >= 32 => (Const32 [0])
+((Lsh16|Rsh16U)x64 _ (Const64 [c])) && uint64(c) >= 16 => (Const16 [0])
+((Lsh8|Rsh8U)x64 _ (Const64 [c])) && uint64(c) >= 8 => (Const8 [0])
+
+// combine const shifts
+(Lsh64x64 <t> (Lsh64x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Lsh64x64 x (Const64 <t> [c+d]))
+(Lsh32x64 <t> (Lsh32x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Lsh32x64 x (Const64 <t> [c+d]))
+(Lsh16x64 <t> (Lsh16x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Lsh16x64 x (Const64 <t> [c+d]))
+(Lsh8x64 <t> (Lsh8x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Lsh8x64 x (Const64 <t> [c+d]))
+
+(Rsh64x64 <t> (Rsh64x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Rsh64x64 x (Const64 <t> [c+d]))
+(Rsh32x64 <t> (Rsh32x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Rsh32x64 x (Const64 <t> [c+d]))
+(Rsh16x64 <t> (Rsh16x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Rsh16x64 x (Const64 <t> [c+d]))
+(Rsh8x64 <t> (Rsh8x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Rsh8x64 x (Const64 <t> [c+d]))
+
+(Rsh64Ux64 <t> (Rsh64Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Rsh64Ux64 x (Const64 <t> [c+d]))
+(Rsh32Ux64 <t> (Rsh32Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Rsh32Ux64 x (Const64 <t> [c+d]))
+(Rsh16Ux64 <t> (Rsh16Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Rsh16Ux64 x (Const64 <t> [c+d]))
+(Rsh8Ux64 <t> (Rsh8Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) => (Rsh8Ux64 x (Const64 <t> [c+d]))
+
+// Remove signed right shift before an unsigned right shift that extracts the sign bit.
+(Rsh8Ux64 (Rsh8x64 x _) (Const64 <t> [7] )) => (Rsh8Ux64 x (Const64 <t> [7] ))
+(Rsh16Ux64 (Rsh16x64 x _) (Const64 <t> [15])) => (Rsh16Ux64 x (Const64 <t> [15]))
+(Rsh32Ux64 (Rsh32x64 x _) (Const64 <t> [31])) => (Rsh32Ux64 x (Const64 <t> [31]))
+(Rsh64Ux64 (Rsh64x64 x _) (Const64 <t> [63])) => (Rsh64Ux64 x (Const64 <t> [63]))
+
+// ((x >> c1) << c2) >> c3
+(Rsh(64|32|16|8)Ux64 (Lsh(64|32|16|8)x64 (Rsh(64|32|16|8)Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
+ && uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
+ => (Rsh(64|32|16|8)Ux64 x (Const64 <typ.UInt64> [c1-c2+c3]))
+
+// ((x << c1) >> c2) << c3
+(Lsh(64|32|16|8)x64 (Rsh(64|32|16|8)Ux64 (Lsh(64|32|16|8)x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
+ && uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
+ => (Lsh(64|32|16|8)x64 x (Const64 <typ.UInt64> [c1-c2+c3]))
+
+// (x >> c) & uppermask = 0
+(And64 (Const64 [m]) (Rsh64Ux64 _ (Const64 [c]))) && c >= int64(64-ntz64(m)) => (Const64 [0])
+(And32 (Const32 [m]) (Rsh32Ux64 _ (Const64 [c]))) && c >= int64(32-ntz32(m)) => (Const32 [0])
+(And16 (Const16 [m]) (Rsh16Ux64 _ (Const64 [c]))) && c >= int64(16-ntz16(m)) => (Const16 [0])
+(And8 (Const8 [m]) (Rsh8Ux64 _ (Const64 [c]))) && c >= int64(8-ntz8(m)) => (Const8 [0])
+
+// (x << c) & lowermask = 0
+(And64 (Const64 [m]) (Lsh64x64 _ (Const64 [c]))) && c >= int64(64-nlz64(m)) => (Const64 [0])
+(And32 (Const32 [m]) (Lsh32x64 _ (Const64 [c]))) && c >= int64(32-nlz32(m)) => (Const32 [0])
+(And16 (Const16 [m]) (Lsh16x64 _ (Const64 [c]))) && c >= int64(16-nlz16(m)) => (Const16 [0])
+(And8 (Const8 [m]) (Lsh8x64 _ (Const64 [c]))) && c >= int64(8-nlz8(m)) => (Const8 [0])
+
+// replace shifts with zero extensions
+(Rsh16Ux64 (Lsh16x64 x (Const64 [8])) (Const64 [8])) => (ZeroExt8to16 (Trunc16to8 <typ.UInt8> x))
+(Rsh32Ux64 (Lsh32x64 x (Const64 [24])) (Const64 [24])) => (ZeroExt8to32 (Trunc32to8 <typ.UInt8> x))
+(Rsh64Ux64 (Lsh64x64 x (Const64 [56])) (Const64 [56])) => (ZeroExt8to64 (Trunc64to8 <typ.UInt8> x))
+(Rsh32Ux64 (Lsh32x64 x (Const64 [16])) (Const64 [16])) => (ZeroExt16to32 (Trunc32to16 <typ.UInt16> x))
+(Rsh64Ux64 (Lsh64x64 x (Const64 [48])) (Const64 [48])) => (ZeroExt16to64 (Trunc64to16 <typ.UInt16> x))
+(Rsh64Ux64 (Lsh64x64 x (Const64 [32])) (Const64 [32])) => (ZeroExt32to64 (Trunc64to32 <typ.UInt32> x))
+
+// replace shifts with sign extensions
+(Rsh16x64 (Lsh16x64 x (Const64 [8])) (Const64 [8])) => (SignExt8to16 (Trunc16to8 <typ.Int8> x))
+(Rsh32x64 (Lsh32x64 x (Const64 [24])) (Const64 [24])) => (SignExt8to32 (Trunc32to8 <typ.Int8> x))
+(Rsh64x64 (Lsh64x64 x (Const64 [56])) (Const64 [56])) => (SignExt8to64 (Trunc64to8 <typ.Int8> x))
+(Rsh32x64 (Lsh32x64 x (Const64 [16])) (Const64 [16])) => (SignExt16to32 (Trunc32to16 <typ.Int16> x))
+(Rsh64x64 (Lsh64x64 x (Const64 [48])) (Const64 [48])) => (SignExt16to64 (Trunc64to16 <typ.Int16> x))
+(Rsh64x64 (Lsh64x64 x (Const64 [32])) (Const64 [32])) => (SignExt32to64 (Trunc64to32 <typ.Int32> x))
+
+// constant comparisons
+(Eq(64|32|16|8) (Const(64|32|16|8) [c]) (Const(64|32|16|8) [d])) => (ConstBool [c == d])
+(Neq(64|32|16|8) (Const(64|32|16|8) [c]) (Const(64|32|16|8) [d])) => (ConstBool [c != d])
+(Less(64|32|16|8) (Const(64|32|16|8) [c]) (Const(64|32|16|8) [d])) => (ConstBool [c < d])
+(Leq(64|32|16|8) (Const(64|32|16|8) [c]) (Const(64|32|16|8) [d])) => (ConstBool [c <= d])
+
+(Less64U (Const64 [c]) (Const64 [d])) => (ConstBool [uint64(c) < uint64(d)])
+(Less32U (Const32 [c]) (Const32 [d])) => (ConstBool [uint32(c) < uint32(d)])
+(Less16U (Const16 [c]) (Const16 [d])) => (ConstBool [uint16(c) < uint16(d)])
+(Less8U (Const8 [c]) (Const8 [d])) => (ConstBool [ uint8(c) < uint8(d)])
+
+(Leq64U (Const64 [c]) (Const64 [d])) => (ConstBool [uint64(c) <= uint64(d)])
+(Leq32U (Const32 [c]) (Const32 [d])) => (ConstBool [uint32(c) <= uint32(d)])
+(Leq16U (Const16 [c]) (Const16 [d])) => (ConstBool [uint16(c) <= uint16(d)])
+(Leq8U (Const8 [c]) (Const8 [d])) => (ConstBool [ uint8(c) <= uint8(d)])
+
+(Leq8 (Const8 [0]) (And8 _ (Const8 [c]))) && c >= 0 => (ConstBool [true])
+(Leq16 (Const16 [0]) (And16 _ (Const16 [c]))) && c >= 0 => (ConstBool [true])
+(Leq32 (Const32 [0]) (And32 _ (Const32 [c]))) && c >= 0 => (ConstBool [true])
+(Leq64 (Const64 [0]) (And64 _ (Const64 [c]))) && c >= 0 => (ConstBool [true])
+
+(Leq8 (Const8 [0]) (Rsh8Ux64 _ (Const64 [c]))) && c > 0 => (ConstBool [true])
+(Leq16 (Const16 [0]) (Rsh16Ux64 _ (Const64 [c]))) && c > 0 => (ConstBool [true])
+(Leq32 (Const32 [0]) (Rsh32Ux64 _ (Const64 [c]))) && c > 0 => (ConstBool [true])
+(Leq64 (Const64 [0]) (Rsh64Ux64 _ (Const64 [c]))) && c > 0 => (ConstBool [true])
+
+// constant floating point comparisons
+(Eq32F (Const32F [c]) (Const32F [d])) => (ConstBool [c == d])
+(Eq64F (Const64F [c]) (Const64F [d])) => (ConstBool [c == d])
+(Neq32F (Const32F [c]) (Const32F [d])) => (ConstBool [c != d])
+(Neq64F (Const64F [c]) (Const64F [d])) => (ConstBool [c != d])
+(Less32F (Const32F [c]) (Const32F [d])) => (ConstBool [c < d])
+(Less64F (Const64F [c]) (Const64F [d])) => (ConstBool [c < d])
+(Leq32F (Const32F [c]) (Const32F [d])) => (ConstBool [c <= d])
+(Leq64F (Const64F [c]) (Const64F [d])) => (ConstBool [c <= d])
+
+// simplifications
+(Or(64|32|16|8) x x) => x
+(Or(64|32|16|8) (Const(64|32|16|8) [0]) x) => x
+(Or(64|32|16|8) (Const(64|32|16|8) [-1]) _) => (Const(64|32|16|8) [-1])
+
+(And(64|32|16|8) x x) => x
+(And(64|32|16|8) (Const(64|32|16|8) [-1]) x) => x
+(And(64|32|16|8) (Const(64|32|16|8) [0]) _) => (Const(64|32|16|8) [0])
+
+(Xor(64|32|16|8) x x) => (Const(64|32|16|8) [0])
+(Xor(64|32|16|8) (Const(64|32|16|8) [0]) x) => x
+
+(Add(64|32|16|8) (Const(64|32|16|8) [0]) x) => x
+(Sub(64|32|16|8) x x) => (Const(64|32|16|8) [0])
+(Mul(64|32|16|8) (Const(64|32|16|8) [0]) _) => (Const(64|32|16|8) [0])
+
+(Com(64|32|16|8) (Com(64|32|16|8) x)) => x
+(Com(64|32|16|8) (Const(64|32|16|8) [c])) => (Const(64|32|16|8) [^c])
+
+(Neg(64|32|16|8) (Sub(64|32|16|8) x y)) => (Sub(64|32|16|8) y x)
+
+// ^(x-1) == ^x+1 == -x
+(Add(64|32|16|8) (Const(64|32|16|8) [1]) (Com(64|32|16|8) x)) => (Neg(64|32|16|8) x)
+(Com(64|32|16|8) (Add(64|32|16|8) (Const(64|32|16|8) [-1]) x)) => (Neg(64|32|16|8) x)
+
+// -(-x) == x
+(Neg(64|32|16|8) (Neg(64|32|16|8) x)) => x
+
+// -^x == x+1
+(Neg(64|32|16|8) <t> (Com(64|32|16|8) x)) => (Add(64|32|16|8) (Const(64|32|16|8) <t> [1]) x)
+
+(And(64|32|16|8) x (And(64|32|16|8) x y)) => (And(64|32|16|8) x y)
+(Or(64|32|16|8) x (Or(64|32|16|8) x y)) => (Or(64|32|16|8) x y)
+(Xor(64|32|16|8) x (Xor(64|32|16|8) x y)) => y
+
+// Unsigned comparisons to zero.
+(Less(64U|32U|16U|8U) _ (Const(64|32|16|8) [0])) => (ConstBool [false])
+(Leq(64U|32U|16U|8U) (Const(64|32|16|8) [0]) _) => (ConstBool [true])
+
+// Ands clear bits. Ors set bits.
+// If a subsequent Or will set all the bits
+// that an And cleared, we can skip the And.
+// This happens in bitmasking code like:
+// x &^= 3 << shift // clear two old bits
+// x |= v << shift // set two new bits
+// when shift is a small constant and v ends up a constant 3.
+(Or8 (And8 x (Const8 [c2])) (Const8 <t> [c1])) && ^(c1 | c2) == 0 => (Or8 (Const8 <t> [c1]) x)
+(Or16 (And16 x (Const16 [c2])) (Const16 <t> [c1])) && ^(c1 | c2) == 0 => (Or16 (Const16 <t> [c1]) x)
+(Or32 (And32 x (Const32 [c2])) (Const32 <t> [c1])) && ^(c1 | c2) == 0 => (Or32 (Const32 <t> [c1]) x)
+(Or64 (And64 x (Const64 [c2])) (Const64 <t> [c1])) && ^(c1 | c2) == 0 => (Or64 (Const64 <t> [c1]) x)
+
+(Trunc64to8 (And64 (Const64 [y]) x)) && y&0xFF == 0xFF => (Trunc64to8 x)
+(Trunc64to16 (And64 (Const64 [y]) x)) && y&0xFFFF == 0xFFFF => (Trunc64to16 x)
+(Trunc64to32 (And64 (Const64 [y]) x)) && y&0xFFFFFFFF == 0xFFFFFFFF => (Trunc64to32 x)
+(Trunc32to8 (And32 (Const32 [y]) x)) && y&0xFF == 0xFF => (Trunc32to8 x)
+(Trunc32to16 (And32 (Const32 [y]) x)) && y&0xFFFF == 0xFFFF => (Trunc32to16 x)
+(Trunc16to8 (And16 (Const16 [y]) x)) && y&0xFF == 0xFF => (Trunc16to8 x)
+
+(ZeroExt8to64 (Trunc64to8 x:(Rsh64Ux64 _ (Const64 [s])))) && s >= 56 => x
+(ZeroExt16to64 (Trunc64to16 x:(Rsh64Ux64 _ (Const64 [s])))) && s >= 48 => x
+(ZeroExt32to64 (Trunc64to32 x:(Rsh64Ux64 _ (Const64 [s])))) && s >= 32 => x
+(ZeroExt8to32 (Trunc32to8 x:(Rsh32Ux64 _ (Const64 [s])))) && s >= 24 => x
+(ZeroExt16to32 (Trunc32to16 x:(Rsh32Ux64 _ (Const64 [s])))) && s >= 16 => x
+(ZeroExt8to16 (Trunc16to8 x:(Rsh16Ux64 _ (Const64 [s])))) && s >= 8 => x
+
+(SignExt8to64 (Trunc64to8 x:(Rsh64x64 _ (Const64 [s])))) && s >= 56 => x
+(SignExt16to64 (Trunc64to16 x:(Rsh64x64 _ (Const64 [s])))) && s >= 48 => x
+(SignExt32to64 (Trunc64to32 x:(Rsh64x64 _ (Const64 [s])))) && s >= 32 => x
+(SignExt8to32 (Trunc32to8 x:(Rsh32x64 _ (Const64 [s])))) && s >= 24 => x
+(SignExt16to32 (Trunc32to16 x:(Rsh32x64 _ (Const64 [s])))) && s >= 16 => x
+(SignExt8to16 (Trunc16to8 x:(Rsh16x64 _ (Const64 [s])))) && s >= 8 => x
+
+(Slicemask (Const32 [x])) && x > 0 => (Const32 [-1])
+(Slicemask (Const32 [0])) => (Const32 [0])
+(Slicemask (Const64 [x])) && x > 0 => (Const64 [-1])
+(Slicemask (Const64 [0])) => (Const64 [0])
+
+// simplifications often used for lengths. e.g. len(s[i:i+5])==5
+(Sub(64|32|16|8) (Add(64|32|16|8) x y) x) => y
+(Sub(64|32|16|8) (Add(64|32|16|8) x y) y) => x
+
+// basic phi simplifications
+(Phi (Const8 [c]) (Const8 [c])) => (Const8 [c])
+(Phi (Const16 [c]) (Const16 [c])) => (Const16 [c])
+(Phi (Const32 [c]) (Const32 [c])) => (Const32 [c])
+(Phi (Const64 [c]) (Const64 [c])) => (Const64 [c])
+
+// slice and interface comparisons
+// The frontend ensures that we can only compare against nil,
+// so we need only compare the first word (interface type or slice ptr).
+(EqInter x y) => (EqPtr (ITab x) (ITab y))
+(NeqInter x y) => (NeqPtr (ITab x) (ITab y))
+(EqSlice x y) => (EqPtr (SlicePtr x) (SlicePtr y))
+(NeqSlice x y) => (NeqPtr (SlicePtr x) (SlicePtr y))
+
+// Load of store of same address, with compatibly typed value and same size
+(Load <t1> p1 (Store {t2} p2 x _))
+ && isSamePtr(p1, p2)
+ && t1.Compare(x.Type) == types.CMPeq
+ && t1.Size() == t2.Size()
+ => x
+(Load <t1> p1 (Store {t2} p2 _ (Store {t3} p3 x _)))
+ && isSamePtr(p1, p3)
+ && t1.Compare(x.Type) == types.CMPeq
+ && t1.Size() == t2.Size()
+ && disjoint(p3, t3.Size(), p2, t2.Size())
+ => x
+(Load <t1> p1 (Store {t2} p2 _ (Store {t3} p3 _ (Store {t4} p4 x _))))
+ && isSamePtr(p1, p4)
+ && t1.Compare(x.Type) == types.CMPeq
+ && t1.Size() == t2.Size()
+ && disjoint(p4, t4.Size(), p2, t2.Size())
+ && disjoint(p4, t4.Size(), p3, t3.Size())
+ => x
+(Load <t1> p1 (Store {t2} p2 _ (Store {t3} p3 _ (Store {t4} p4 _ (Store {t5} p5 x _)))))
+ && isSamePtr(p1, p5)
+ && t1.Compare(x.Type) == types.CMPeq
+ && t1.Size() == t2.Size()
+ && disjoint(p5, t5.Size(), p2, t2.Size())
+ && disjoint(p5, t5.Size(), p3, t3.Size())
+ && disjoint(p5, t5.Size(), p4, t4.Size())
+ => x
+
+// Pass constants through math.Float{32,64}bits and math.Float{32,64}frombits
+ (Load <t1> p1 (Store {t2} p2 (Const64 [x]) _)) && isSamePtr(p1,p2) && sizeof(t2) == 8 && is64BitFloat(t1) && !math.IsNaN(math.Float64frombits(uint64(x))) => (Const64F [math.Float64frombits(uint64(x))])
+ (Load <t1> p1 (Store {t2} p2 (Const32 [x]) _)) && isSamePtr(p1,p2) && sizeof(t2) == 4 && is32BitFloat(t1) && !math.IsNaN(float64(math.Float32frombits(uint32(x)))) => (Const32F [math.Float32frombits(uint32(x))])
+(Load <t1> p1 (Store {t2} p2 (Const64F [x]) _)) && isSamePtr(p1,p2) && sizeof(t2) == 8 && is64BitInt(t1) => (Const64 [int64(math.Float64bits(x))])
+(Load <t1> p1 (Store {t2} p2 (Const32F [x]) _)) && isSamePtr(p1,p2) && sizeof(t2) == 4 && is32BitInt(t1) => (Const32 [int32(math.Float32bits(x))])
+
+// Float Loads up to Zeros so they can be constant folded.
+(Load <t1> op:(OffPtr [o1] p1)
+ (Store {t2} p2 _
+ mem:(Zero [n] p3 _)))
+ && o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p3)
+ && fe.CanSSA(t1)
+ && disjoint(op, t1.Size(), p2, t2.Size())
+ => @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p3) mem)
+(Load <t1> op:(OffPtr [o1] p1)
+ (Store {t2} p2 _
+ (Store {t3} p3 _
+ mem:(Zero [n] p4 _))))
+ && o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p4)
+ && fe.CanSSA(t1)
+ && disjoint(op, t1.Size(), p2, t2.Size())
+ && disjoint(op, t1.Size(), p3, t3.Size())
+ => @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p4) mem)
+(Load <t1> op:(OffPtr [o1] p1)
+ (Store {t2} p2 _
+ (Store {t3} p3 _
+ (Store {t4} p4 _
+ mem:(Zero [n] p5 _)))))
+ && o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p5)
+ && fe.CanSSA(t1)
+ && disjoint(op, t1.Size(), p2, t2.Size())
+ && disjoint(op, t1.Size(), p3, t3.Size())
+ && disjoint(op, t1.Size(), p4, t4.Size())
+ => @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p5) mem)
+(Load <t1> op:(OffPtr [o1] p1)
+ (Store {t2} p2 _
+ (Store {t3} p3 _
+ (Store {t4} p4 _
+ (Store {t5} p5 _
+ mem:(Zero [n] p6 _))))))
+ && o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p6)
+ && fe.CanSSA(t1)
+ && disjoint(op, t1.Size(), p2, t2.Size())
+ && disjoint(op, t1.Size(), p3, t3.Size())
+ && disjoint(op, t1.Size(), p4, t4.Size())
+ && disjoint(op, t1.Size(), p5, t5.Size())
+ => @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p6) mem)
+
+// Zero to Load forwarding.
+(Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ && t1.IsBoolean()
+ && isSamePtr(p1, p2)
+ && n >= o + 1
+ => (ConstBool [false])
+(Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ && is8BitInt(t1)
+ && isSamePtr(p1, p2)
+ && n >= o + 1
+ => (Const8 [0])
+(Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ && is16BitInt(t1)
+ && isSamePtr(p1, p2)
+ && n >= o + 2
+ => (Const16 [0])
+(Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ && is32BitInt(t1)
+ && isSamePtr(p1, p2)
+ && n >= o + 4
+ => (Const32 [0])
+(Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ && is64BitInt(t1)
+ && isSamePtr(p1, p2)
+ && n >= o + 8
+ => (Const64 [0])
+(Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ && is32BitFloat(t1)
+ && isSamePtr(p1, p2)
+ && n >= o + 4
+ => (Const32F [0])
+(Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ && is64BitFloat(t1)
+ && isSamePtr(p1, p2)
+ && n >= o + 8
+ => (Const64F [0])
+
+// Eliminate stores of values that have just been loaded from the same location.
+// We also handle the common case where there are some intermediate stores.
+(Store {t1} p1 (Load <t2> p2 mem) mem)
+ && isSamePtr(p1, p2)
+ && t2.Size() == t1.Size()
+ => mem
+(Store {t1} p1 (Load <t2> p2 oldmem) mem:(Store {t3} p3 _ oldmem))
+ && isSamePtr(p1, p2)
+ && t2.Size() == t1.Size()
+ && disjoint(p1, t1.Size(), p3, t3.Size())
+ => mem
+(Store {t1} p1 (Load <t2> p2 oldmem) mem:(Store {t3} p3 _ (Store {t4} p4 _ oldmem)))
+ && isSamePtr(p1, p2)
+ && t2.Size() == t1.Size()
+ && disjoint(p1, t1.Size(), p3, t3.Size())
+ && disjoint(p1, t1.Size(), p4, t4.Size())
+ => mem
+(Store {t1} p1 (Load <t2> p2 oldmem) mem:(Store {t3} p3 _ (Store {t4} p4 _ (Store {t5} p5 _ oldmem))))
+ && isSamePtr(p1, p2)
+ && t2.Size() == t1.Size()
+ && disjoint(p1, t1.Size(), p3, t3.Size())
+ && disjoint(p1, t1.Size(), p4, t4.Size())
+ && disjoint(p1, t1.Size(), p5, t5.Size())
+ => mem
+
+// Don't Store zeros to cleared variables.
+(Store {t} (OffPtr [o] p1) x mem:(Zero [n] p2 _))
+ && isConstZero(x)
+ && o >= 0 && t.Size() + o <= n && isSamePtr(p1, p2)
+ => mem
+(Store {t1} op:(OffPtr [o1] p1) x mem:(Store {t2} p2 _ (Zero [n] p3 _)))
+ && isConstZero(x)
+ && o1 >= 0 && t1.Size() + o1 <= n && isSamePtr(p1, p3)
+ && disjoint(op, t1.Size(), p2, t2.Size())
+ => mem
+(Store {t1} op:(OffPtr [o1] p1) x mem:(Store {t2} p2 _ (Store {t3} p3 _ (Zero [n] p4 _))))
+ && isConstZero(x)
+ && o1 >= 0 && t1.Size() + o1 <= n && isSamePtr(p1, p4)
+ && disjoint(op, t1.Size(), p2, t2.Size())
+ && disjoint(op, t1.Size(), p3, t3.Size())
+ => mem
+(Store {t1} op:(OffPtr [o1] p1) x mem:(Store {t2} p2 _ (Store {t3} p3 _ (Store {t4} p4 _ (Zero [n] p5 _)))))
+ && isConstZero(x)
+ && o1 >= 0 && t1.Size() + o1 <= n && isSamePtr(p1, p5)
+ && disjoint(op, t1.Size(), p2, t2.Size())
+ && disjoint(op, t1.Size(), p3, t3.Size())
+ && disjoint(op, t1.Size(), p4, t4.Size())
+ => mem
+
+// Collapse OffPtr
+(OffPtr (OffPtr p [b]) [a]) => (OffPtr p [a+b])
+(OffPtr p [0]) && v.Type.Compare(p.Type) == types.CMPeq => p
+
+// indexing operations
+// Note: bounds check has already been done
+(PtrIndex <t> ptr idx) && config.PtrSize == 4 && is32Bit(t.Elem().Size()) => (AddPtr ptr (Mul32 <typ.Int> idx (Const32 <typ.Int> [int32(t.Elem().Size())])))
+(PtrIndex <t> ptr idx) && config.PtrSize == 8 => (AddPtr ptr (Mul64 <typ.Int> idx (Const64 <typ.Int> [t.Elem().Size()])))
+
+// struct operations
+(StructSelect (StructMake1 x)) => x
+(StructSelect [0] (StructMake2 x _)) => x
+(StructSelect [1] (StructMake2 _ x)) => x
+(StructSelect [0] (StructMake3 x _ _)) => x
+(StructSelect [1] (StructMake3 _ x _)) => x
+(StructSelect [2] (StructMake3 _ _ x)) => x
+(StructSelect [0] (StructMake4 x _ _ _)) => x
+(StructSelect [1] (StructMake4 _ x _ _)) => x
+(StructSelect [2] (StructMake4 _ _ x _)) => x
+(StructSelect [3] (StructMake4 _ _ _ x)) => x
+
+(Load <t> _ _) && t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t) =>
+ (StructMake0)
+(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t) =>
+ (StructMake1
+ (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem))
+(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t) =>
+ (StructMake2
+ (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem)
+ (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem))
+(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t) =>
+ (StructMake3
+ (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem)
+ (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem)
+ (Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem))
+(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t) =>
+ (StructMake4
+ (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem)
+ (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem)
+ (Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem)
+ (Load <t.FieldType(3)> (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] ptr) mem))
+
+(StructSelect [i] x:(Load <t> ptr mem)) && !fe.CanSSA(t) =>
+ @x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
+
+(Store _ (StructMake0) mem) => mem
+(Store dst (StructMake1 <t> f0) mem) =>
+ (Store {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)
+(Store dst (StructMake2 <t> f0 f1) mem) =>
+ (Store {t.FieldType(1)}
+ (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
+ f1
+ (Store {t.FieldType(0)}
+ (OffPtr <t.FieldType(0).PtrTo()> [0] dst)
+ f0 mem))
+(Store dst (StructMake3 <t> f0 f1 f2) mem) =>
+ (Store {t.FieldType(2)}
+ (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst)
+ f2
+ (Store {t.FieldType(1)}
+ (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
+ f1
+ (Store {t.FieldType(0)}
+ (OffPtr <t.FieldType(0).PtrTo()> [0] dst)
+ f0 mem)))
+(Store dst (StructMake4 <t> f0 f1 f2 f3) mem) =>
+ (Store {t.FieldType(3)}
+ (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] dst)
+ f3
+ (Store {t.FieldType(2)}
+ (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst)
+ f2
+ (Store {t.FieldType(1)}
+ (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
+ f1
+ (Store {t.FieldType(0)}
+ (OffPtr <t.FieldType(0).PtrTo()> [0] dst)
+ f0 mem))))
+
+// Putting struct{*byte} and similar into direct interfaces.
+(IMake typ (StructMake1 val)) => (IMake typ val)
+(StructSelect [0] (IData x)) => (IData x)
+
+// un-SSAable values use mem->mem copies
+(Store {t} dst (Load src mem) mem) && !fe.CanSSA(t) =>
+ (Move {t} [t.Size()] dst src mem)
+(Store {t} dst (Load src mem) (VarDef {x} mem)) && !fe.CanSSA(t) =>
+ (Move {t} [t.Size()] dst src (VarDef {x} mem))
+
+// array ops
+(ArraySelect (ArrayMake1 x)) => x
+
+(Load <t> _ _) && t.IsArray() && t.NumElem() == 0 =>
+ (ArrayMake0)
+
+(Load <t> ptr mem) && t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t) =>
+ (ArrayMake1 (Load <t.Elem()> ptr mem))
+
+(Store _ (ArrayMake0) mem) => mem
+(Store dst (ArrayMake1 e) mem) => (Store {e.Type} dst e mem)
+
+// Putting [1]*byte and similar into direct interfaces.
+(IMake typ (ArrayMake1 val)) => (IMake typ val)
+(ArraySelect [0] (IData x)) => (IData x)
+
+// string ops
+// Decomposing StringMake and lowering of StringPtr and StringLen
+// happens in a later pass, dec, so that these operations are available
+// to other passes for optimizations.
+(StringPtr (StringMake (Addr <t> {s} base) _)) => (Addr <t> {s} base)
+(StringLen (StringMake _ (Const64 <t> [c]))) => (Const64 <t> [c])
+(ConstString {str}) && config.PtrSize == 4 && str == "" =>
+ (StringMake (ConstNil) (Const32 <typ.Int> [0]))
+(ConstString {str}) && config.PtrSize == 8 && str == "" =>
+ (StringMake (ConstNil) (Const64 <typ.Int> [0]))
+(ConstString {str}) && config.PtrSize == 4 && str != "" =>
+ (StringMake
+ (Addr <typ.BytePtr> {fe.StringData(str)}
+ (SB))
+ (Const32 <typ.Int> [int32(len(str))]))
+(ConstString {str}) && config.PtrSize == 8 && str != "" =>
+ (StringMake
+ (Addr <typ.BytePtr> {fe.StringData(str)}
+ (SB))
+ (Const64 <typ.Int> [int64(len(str))]))
+
+// slice ops
+// Only a few slice rules are provided here. See dec.rules for
+// a more comprehensive set.
+(SliceLen (SliceMake _ (Const64 <t> [c]) _)) => (Const64 <t> [c])
+(SliceCap (SliceMake _ _ (Const64 <t> [c]))) => (Const64 <t> [c])
+(SliceLen (SliceMake _ (Const32 <t> [c]) _)) => (Const32 <t> [c])
+(SliceCap (SliceMake _ _ (Const32 <t> [c]))) => (Const32 <t> [c])
+(SlicePtr (SliceMake (SlicePtr x) _ _)) => (SlicePtr x)
+(SliceLen (SliceMake _ (SliceLen x) _)) => (SliceLen x)
+(SliceCap (SliceMake _ _ (SliceCap x))) => (SliceCap x)
+(SliceCap (SliceMake _ _ (SliceLen x))) => (SliceLen x)
+(ConstSlice) && config.PtrSize == 4 =>
+ (SliceMake
+ (ConstNil <v.Type.Elem().PtrTo()>)
+ (Const32 <typ.Int> [0])
+ (Const32 <typ.Int> [0]))
+(ConstSlice) && config.PtrSize == 8 =>
+ (SliceMake
+ (ConstNil <v.Type.Elem().PtrTo()>)
+ (Const64 <typ.Int> [0])
+ (Const64 <typ.Int> [0]))
+
+// interface ops
+(ConstInterface) =>
+ (IMake
+ (ConstNil <typ.Uintptr>)
+ (ConstNil <typ.BytePtr>))
+
+(NilCheck (GetG mem) mem) => mem
+
+(If (Not cond) yes no) => (If cond no yes)
+(If (ConstBool [c]) yes no) && c => (First yes no)
+(If (ConstBool [c]) yes no) && !c => (First no yes)
+
+// Get rid of Convert ops for pointer arithmetic on unsafe.Pointer.
+(Convert (Add(64|32) (Convert ptr mem) off) mem) => (AddPtr ptr off)
+(Convert (Convert ptr mem) mem) => ptr
+
+// strength reduction of divide by a constant.
+// See ../magic.go for a detailed description of these algorithms.
+
+// Unsigned divide by power of 2. Strength reduce to a shift.
+(Div8u n (Const8 [c])) && isPowerOfTwo8(c) => (Rsh8Ux64 n (Const64 <typ.UInt64> [log8(c)]))
+(Div16u n (Const16 [c])) && isPowerOfTwo16(c) => (Rsh16Ux64 n (Const64 <typ.UInt64> [log16(c)]))
+(Div32u n (Const32 [c])) && isPowerOfTwo32(c) => (Rsh32Ux64 n (Const64 <typ.UInt64> [log32(c)]))
+(Div64u n (Const64 [c])) && isPowerOfTwo64(c) => (Rsh64Ux64 n (Const64 <typ.UInt64> [log64(c)]))
+(Div64u n (Const64 [-1<<63])) => (Rsh64Ux64 n (Const64 <typ.UInt64> [63]))
+
+// Signed non-negative divide by power of 2.
+(Div8 n (Const8 [c])) && isNonNegative(n) && isPowerOfTwo8(c) => (Rsh8Ux64 n (Const64 <typ.UInt64> [log8(c)]))
+(Div16 n (Const16 [c])) && isNonNegative(n) && isPowerOfTwo16(c) => (Rsh16Ux64 n (Const64 <typ.UInt64> [log16(c)]))
+(Div32 n (Const32 [c])) && isNonNegative(n) && isPowerOfTwo32(c) => (Rsh32Ux64 n (Const64 <typ.UInt64> [log32(c)]))
+(Div64 n (Const64 [c])) && isNonNegative(n) && isPowerOfTwo64(c) => (Rsh64Ux64 n (Const64 <typ.UInt64> [log64(c)]))
+(Div64 n (Const64 [-1<<63])) && isNonNegative(n) => (Const64 [0])
+
+// Unsigned divide, not a power of 2. Strength reduce to a multiply.
+// For 8-bit divides, we just do a direct 9-bit by 8-bit multiply.
+(Div8u x (Const8 [c])) && umagicOK8(c) =>
+ (Trunc32to8
+ (Rsh32Ux64 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(1<<8+umagic8(c).m)])
+ (ZeroExt8to32 x))
+ (Const64 <typ.UInt64> [8+umagic8(c).s])))
+
+// For 16-bit divides on 64-bit machines, we do a direct 17-bit by 16-bit multiply.
+(Div16u x (Const16 [c])) && umagicOK16(c) && config.RegSize == 8 =>
+ (Trunc64to16
+ (Rsh64Ux64 <typ.UInt64>
+ (Mul64 <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(1<<16+umagic16(c).m)])
+ (ZeroExt16to64 x))
+ (Const64 <typ.UInt64> [16+umagic16(c).s])))
+
+// For 16-bit divides on 32-bit machines
+(Div16u x (Const16 [c])) && umagicOK16(c) && config.RegSize == 4 && umagic16(c).m&1 == 0 =>
+ (Trunc32to16
+ (Rsh32Ux64 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(1<<15+umagic16(c).m/2)])
+ (ZeroExt16to32 x))
+ (Const64 <typ.UInt64> [16+umagic16(c).s-1])))
+(Div16u x (Const16 [c])) && umagicOK16(c) && config.RegSize == 4 && c&1 == 0 =>
+ (Trunc32to16
+ (Rsh32Ux64 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(1<<15+(umagic16(c).m+1)/2)])
+ (Rsh32Ux64 <typ.UInt32> (ZeroExt16to32 x) (Const64 <typ.UInt64> [1])))
+ (Const64 <typ.UInt64> [16+umagic16(c).s-2])))
+(Div16u x (Const16 [c])) && umagicOK16(c) && config.RegSize == 4 && config.useAvg =>
+ (Trunc32to16
+ (Rsh32Ux64 <typ.UInt32>
+ (Avg32u
+ (Lsh32x64 <typ.UInt32> (ZeroExt16to32 x) (Const64 <typ.UInt64> [16]))
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(umagic16(c).m)])
+ (ZeroExt16to32 x)))
+ (Const64 <typ.UInt64> [16+umagic16(c).s-1])))
+
+// For 32-bit divides on 32-bit machines
+(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 4 && umagic32(c).m&1 == 0 && config.useHmul =>
+ (Rsh32Ux64 <typ.UInt32>
+ (Hmul32u <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(1<<31+umagic32(c).m/2)])
+ x)
+ (Const64 <typ.UInt64> [umagic32(c).s-1]))
+(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 4 && c&1 == 0 && config.useHmul =>
+ (Rsh32Ux64 <typ.UInt32>
+ (Hmul32u <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(1<<31+(umagic32(c).m+1)/2)])
+ (Rsh32Ux64 <typ.UInt32> x (Const64 <typ.UInt64> [1])))
+ (Const64 <typ.UInt64> [umagic32(c).s-2]))
+(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 4 && config.useAvg && config.useHmul =>
+ (Rsh32Ux64 <typ.UInt32>
+ (Avg32u
+ x
+ (Hmul32u <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(umagic32(c).m)])
+ x))
+ (Const64 <typ.UInt64> [umagic32(c).s-1]))
+
+// For 32-bit divides on 64-bit machines
+// We'll use a regular (non-hi) multiply for this case.
+(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 8 && umagic32(c).m&1 == 0 =>
+ (Trunc64to32
+ (Rsh64Ux64 <typ.UInt64>
+ (Mul64 <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(1<<31+umagic32(c).m/2)])
+ (ZeroExt32to64 x))
+ (Const64 <typ.UInt64> [32+umagic32(c).s-1])))
+(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 8 && c&1 == 0 =>
+ (Trunc64to32
+ (Rsh64Ux64 <typ.UInt64>
+ (Mul64 <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(1<<31+(umagic32(c).m+1)/2)])
+ (Rsh64Ux64 <typ.UInt64> (ZeroExt32to64 x) (Const64 <typ.UInt64> [1])))
+ (Const64 <typ.UInt64> [32+umagic32(c).s-2])))
+(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 8 && config.useAvg =>
+ (Trunc64to32
+ (Rsh64Ux64 <typ.UInt64>
+ (Avg64u
+ (Lsh64x64 <typ.UInt64> (ZeroExt32to64 x) (Const64 <typ.UInt64> [32]))
+ (Mul64 <typ.UInt64>
+ (Const64 <typ.UInt32> [int64(umagic32(c).m)])
+ (ZeroExt32to64 x)))
+ (Const64 <typ.UInt64> [32+umagic32(c).s-1])))
+
+// For unsigned 64-bit divides on 32-bit machines,
+// if the constant fits in 16 bits (so that the last term
+// fits in 32 bits), convert to three 32-bit divides by a constant.
+//
+// If 1<<32 = Q * c + R
+// and x = hi << 32 + lo
+//
+// Then x = (hi/c*c + hi%c) << 32 + lo
+// = hi/c*c<<32 + hi%c<<32 + lo
+// = hi/c*c<<32 + (hi%c)*(Q*c+R) + lo/c*c + lo%c
+// = hi/c*c<<32 + (hi%c)*Q*c + lo/c*c + (hi%c*R+lo%c)
+// and x / c = (hi/c)<<32 + (hi%c)*Q + lo/c + (hi%c*R+lo%c)/c
+(Div64u x (Const64 [c])) && c > 0 && c <= 0xFFFF && umagicOK32(int32(c)) && config.RegSize == 4 && config.useHmul =>
+ (Add64
+ (Add64 <typ.UInt64>
+ (Add64 <typ.UInt64>
+ (Lsh64x64 <typ.UInt64>
+ (ZeroExt32to64
+ (Div32u <typ.UInt32>
+ (Trunc64to32 <typ.UInt32> (Rsh64Ux64 <typ.UInt64> x (Const64 <typ.UInt64> [32])))
+ (Const32 <typ.UInt32> [int32(c)])))
+ (Const64 <typ.UInt64> [32]))
+ (ZeroExt32to64 (Div32u <typ.UInt32> (Trunc64to32 <typ.UInt32> x) (Const32 <typ.UInt32> [int32(c)]))))
+ (Mul64 <typ.UInt64>
+ (ZeroExt32to64 <typ.UInt64>
+ (Mod32u <typ.UInt32>
+ (Trunc64to32 <typ.UInt32> (Rsh64Ux64 <typ.UInt64> x (Const64 <typ.UInt64> [32])))
+ (Const32 <typ.UInt32> [int32(c)])))
+ (Const64 <typ.UInt64> [int64((1<<32)/c)])))
+ (ZeroExt32to64
+ (Div32u <typ.UInt32>
+ (Add32 <typ.UInt32>
+ (Mod32u <typ.UInt32> (Trunc64to32 <typ.UInt32> x) (Const32 <typ.UInt32> [int32(c)]))
+ (Mul32 <typ.UInt32>
+ (Mod32u <typ.UInt32>
+ (Trunc64to32 <typ.UInt32> (Rsh64Ux64 <typ.UInt64> x (Const64 <typ.UInt64> [32])))
+ (Const32 <typ.UInt32> [int32(c)]))
+ (Const32 <typ.UInt32> [int32((1<<32)%c)])))
+ (Const32 <typ.UInt32> [int32(c)]))))
+
+// For 64-bit divides on 64-bit machines
+// (64-bit divides on 32-bit machines are lowered to a runtime call by the walk pass.)
+(Div64u x (Const64 [c])) && umagicOK64(c) && config.RegSize == 8 && umagic64(c).m&1 == 0 && config.useHmul =>
+ (Rsh64Ux64 <typ.UInt64>
+ (Hmul64u <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(1<<63+umagic64(c).m/2)])
+ x)
+ (Const64 <typ.UInt64> [umagic64(c).s-1]))
+(Div64u x (Const64 [c])) && umagicOK64(c) && config.RegSize == 8 && c&1 == 0 && config.useHmul =>
+ (Rsh64Ux64 <typ.UInt64>
+ (Hmul64u <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(1<<63+(umagic64(c).m+1)/2)])
+ (Rsh64Ux64 <typ.UInt64> x (Const64 <typ.UInt64> [1])))
+ (Const64 <typ.UInt64> [umagic64(c).s-2]))
+(Div64u x (Const64 [c])) && umagicOK64(c) && config.RegSize == 8 && config.useAvg && config.useHmul =>
+ (Rsh64Ux64 <typ.UInt64>
+ (Avg64u
+ x
+ (Hmul64u <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(umagic64(c).m)])
+ x))
+ (Const64 <typ.UInt64> [umagic64(c).s-1]))
+
+// Signed divide by a negative constant. Rewrite to divide by a positive constant.
+(Div8 <t> n (Const8 [c])) && c < 0 && c != -1<<7 => (Neg8 (Div8 <t> n (Const8 <t> [-c])))
+(Div16 <t> n (Const16 [c])) && c < 0 && c != -1<<15 => (Neg16 (Div16 <t> n (Const16 <t> [-c])))
+(Div32 <t> n (Const32 [c])) && c < 0 && c != -1<<31 => (Neg32 (Div32 <t> n (Const32 <t> [-c])))
+(Div64 <t> n (Const64 [c])) && c < 0 && c != -1<<63 => (Neg64 (Div64 <t> n (Const64 <t> [-c])))
+
+// Dividing by the most-negative number. Result is always 0 except
+// if the input is also the most-negative number.
+// We can detect that using the sign bit of x & -x.
+(Div8 <t> x (Const8 [-1<<7 ])) => (Rsh8Ux64 (And8 <t> x (Neg8 <t> x)) (Const64 <typ.UInt64> [7 ]))
+(Div16 <t> x (Const16 [-1<<15])) => (Rsh16Ux64 (And16 <t> x (Neg16 <t> x)) (Const64 <typ.UInt64> [15]))
+(Div32 <t> x (Const32 [-1<<31])) => (Rsh32Ux64 (And32 <t> x (Neg32 <t> x)) (Const64 <typ.UInt64> [31]))
+(Div64 <t> x (Const64 [-1<<63])) => (Rsh64Ux64 (And64 <t> x (Neg64 <t> x)) (Const64 <typ.UInt64> [63]))
+
+// Signed divide by power of 2.
+// n / c = n >> log(c) if n >= 0
+// = (n+c-1) >> log(c) if n < 0
+// We conditionally add c-1 by adding n>>63>>(64-log(c)) (first shift signed, second shift unsigned).
+(Div8 <t> n (Const8 [c])) && isPowerOfTwo8(c) =>
+ (Rsh8x64
+ (Add8 <t> n (Rsh8Ux64 <t> (Rsh8x64 <t> n (Const64 <typ.UInt64> [ 7])) (Const64 <typ.UInt64> [int64( 8-log8(c))])))
+ (Const64 <typ.UInt64> [int64(log8(c))]))
+(Div16 <t> n (Const16 [c])) && isPowerOfTwo16(c) =>
+ (Rsh16x64
+ (Add16 <t> n (Rsh16Ux64 <t> (Rsh16x64 <t> n (Const64 <typ.UInt64> [15])) (Const64 <typ.UInt64> [int64(16-log16(c))])))
+ (Const64 <typ.UInt64> [int64(log16(c))]))
+(Div32 <t> n (Const32 [c])) && isPowerOfTwo32(c) =>
+ (Rsh32x64
+ (Add32 <t> n (Rsh32Ux64 <t> (Rsh32x64 <t> n (Const64 <typ.UInt64> [31])) (Const64 <typ.UInt64> [int64(32-log32(c))])))
+ (Const64 <typ.UInt64> [int64(log32(c))]))
+(Div64 <t> n (Const64 [c])) && isPowerOfTwo64(c) =>
+ (Rsh64x64
+ (Add64 <t> n (Rsh64Ux64 <t> (Rsh64x64 <t> n (Const64 <typ.UInt64> [63])) (Const64 <typ.UInt64> [int64(64-log64(c))])))
+ (Const64 <typ.UInt64> [int64(log64(c))]))
+
+// Signed divide, not a power of 2. Strength reduce to a multiply.
+(Div8 <t> x (Const8 [c])) && smagicOK8(c) =>
+ (Sub8 <t>
+ (Rsh32x64 <t>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(smagic8(c).m)])
+ (SignExt8to32 x))
+ (Const64 <typ.UInt64> [8+smagic8(c).s]))
+ (Rsh32x64 <t>
+ (SignExt8to32 x)
+ (Const64 <typ.UInt64> [31])))
+(Div16 <t> x (Const16 [c])) && smagicOK16(c) =>
+ (Sub16 <t>
+ (Rsh32x64 <t>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(smagic16(c).m)])
+ (SignExt16to32 x))
+ (Const64 <typ.UInt64> [16+smagic16(c).s]))
+ (Rsh32x64 <t>
+ (SignExt16to32 x)
+ (Const64 <typ.UInt64> [31])))
+(Div32 <t> x (Const32 [c])) && smagicOK32(c) && config.RegSize == 8 =>
+ (Sub32 <t>
+ (Rsh64x64 <t>
+ (Mul64 <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(smagic32(c).m)])
+ (SignExt32to64 x))
+ (Const64 <typ.UInt64> [32+smagic32(c).s]))
+ (Rsh64x64 <t>
+ (SignExt32to64 x)
+ (Const64 <typ.UInt64> [63])))
+(Div32 <t> x (Const32 [c])) && smagicOK32(c) && config.RegSize == 4 && smagic32(c).m&1 == 0 && config.useHmul =>
+ (Sub32 <t>
+ (Rsh32x64 <t>
+ (Hmul32 <t>
+ (Const32 <typ.UInt32> [int32(smagic32(c).m/2)])
+ x)
+ (Const64 <typ.UInt64> [smagic32(c).s-1]))
+ (Rsh32x64 <t>
+ x
+ (Const64 <typ.UInt64> [31])))
+(Div32 <t> x (Const32 [c])) && smagicOK32(c) && config.RegSize == 4 && smagic32(c).m&1 != 0 && config.useHmul =>
+ (Sub32 <t>
+ (Rsh32x64 <t>
+ (Add32 <t>
+ (Hmul32 <t>
+ (Const32 <typ.UInt32> [int32(smagic32(c).m)])
+ x)
+ x)
+ (Const64 <typ.UInt64> [smagic32(c).s]))
+ (Rsh32x64 <t>
+ x
+ (Const64 <typ.UInt64> [31])))
+(Div64 <t> x (Const64 [c])) && smagicOK64(c) && smagic64(c).m&1 == 0 && config.useHmul =>
+ (Sub64 <t>
+ (Rsh64x64 <t>
+ (Hmul64 <t>
+ (Const64 <typ.UInt64> [int64(smagic64(c).m/2)])
+ x)
+ (Const64 <typ.UInt64> [smagic64(c).s-1]))
+ (Rsh64x64 <t>
+ x
+ (Const64 <typ.UInt64> [63])))
+(Div64 <t> x (Const64 [c])) && smagicOK64(c) && smagic64(c).m&1 != 0 && config.useHmul =>
+ (Sub64 <t>
+ (Rsh64x64 <t>
+ (Add64 <t>
+ (Hmul64 <t>
+ (Const64 <typ.UInt64> [int64(smagic64(c).m)])
+ x)
+ x)
+ (Const64 <typ.UInt64> [smagic64(c).s]))
+ (Rsh64x64 <t>
+ x
+ (Const64 <typ.UInt64> [63])))
+
+// Unsigned mod by power of 2 constant.
+(Mod8u <t> n (Const8 [c])) && isPowerOfTwo8(c) => (And8 n (Const8 <t> [c-1]))
+(Mod16u <t> n (Const16 [c])) && isPowerOfTwo16(c) => (And16 n (Const16 <t> [c-1]))
+(Mod32u <t> n (Const32 [c])) && isPowerOfTwo32(c) => (And32 n (Const32 <t> [c-1]))
+(Mod64u <t> n (Const64 [c])) && isPowerOfTwo64(c) => (And64 n (Const64 <t> [c-1]))
+(Mod64u <t> n (Const64 [-1<<63])) => (And64 n (Const64 <t> [1<<63-1]))
+
+// Signed non-negative mod by power of 2 constant.
+(Mod8 <t> n (Const8 [c])) && isNonNegative(n) && isPowerOfTwo8(c) => (And8 n (Const8 <t> [c-1]))
+(Mod16 <t> n (Const16 [c])) && isNonNegative(n) && isPowerOfTwo16(c) => (And16 n (Const16 <t> [c-1]))
+(Mod32 <t> n (Const32 [c])) && isNonNegative(n) && isPowerOfTwo32(c) => (And32 n (Const32 <t> [c-1]))
+(Mod64 <t> n (Const64 [c])) && isNonNegative(n) && isPowerOfTwo64(c) => (And64 n (Const64 <t> [c-1]))
+(Mod64 n (Const64 [-1<<63])) && isNonNegative(n) => n
+
+// Signed mod by negative constant.
+(Mod8 <t> n (Const8 [c])) && c < 0 && c != -1<<7 => (Mod8 <t> n (Const8 <t> [-c]))
+(Mod16 <t> n (Const16 [c])) && c < 0 && c != -1<<15 => (Mod16 <t> n (Const16 <t> [-c]))
+(Mod32 <t> n (Const32 [c])) && c < 0 && c != -1<<31 => (Mod32 <t> n (Const32 <t> [-c]))
+(Mod64 <t> n (Const64 [c])) && c < 0 && c != -1<<63 => (Mod64 <t> n (Const64 <t> [-c]))
+
+// All other mods by constants, do A%B = A-(A/B*B).
+// This implements % with two * and a bunch of ancillary ops.
+// One of the * is free if the user's code also computes A/B.
+(Mod8 <t> x (Const8 [c])) && x.Op != OpConst8 && (c > 0 || c == -1<<7)
+ => (Sub8 x (Mul8 <t> (Div8 <t> x (Const8 <t> [c])) (Const8 <t> [c])))
+(Mod16 <t> x (Const16 [c])) && x.Op != OpConst16 && (c > 0 || c == -1<<15)
+ => (Sub16 x (Mul16 <t> (Div16 <t> x (Const16 <t> [c])) (Const16 <t> [c])))
+(Mod32 <t> x (Const32 [c])) && x.Op != OpConst32 && (c > 0 || c == -1<<31)
+ => (Sub32 x (Mul32 <t> (Div32 <t> x (Const32 <t> [c])) (Const32 <t> [c])))
+(Mod64 <t> x (Const64 [c])) && x.Op != OpConst64 && (c > 0 || c == -1<<63)
+ => (Sub64 x (Mul64 <t> (Div64 <t> x (Const64 <t> [c])) (Const64 <t> [c])))
+(Mod8u <t> x (Const8 [c])) && x.Op != OpConst8 && c > 0 && umagicOK8( c)
+ => (Sub8 x (Mul8 <t> (Div8u <t> x (Const8 <t> [c])) (Const8 <t> [c])))
+(Mod16u <t> x (Const16 [c])) && x.Op != OpConst16 && c > 0 && umagicOK16(c)
+ => (Sub16 x (Mul16 <t> (Div16u <t> x (Const16 <t> [c])) (Const16 <t> [c])))
+(Mod32u <t> x (Const32 [c])) && x.Op != OpConst32 && c > 0 && umagicOK32(c)
+ => (Sub32 x (Mul32 <t> (Div32u <t> x (Const32 <t> [c])) (Const32 <t> [c])))
+(Mod64u <t> x (Const64 [c])) && x.Op != OpConst64 && c > 0 && umagicOK64(c)
+ => (Sub64 x (Mul64 <t> (Div64u <t> x (Const64 <t> [c])) (Const64 <t> [c])))
+
+// For architectures without rotates on less than 32-bits, promote these checks to 32-bit.
+(Eq8 (Mod8u x (Const8 [c])) (Const8 [0])) && x.Op != OpConst8 && udivisibleOK8(c) && !hasSmallRotate(config) =>
+ (Eq32 (Mod32u <typ.UInt32> (ZeroExt8to32 <typ.UInt32> x) (Const32 <typ.UInt32> [int32(uint8(c))])) (Const32 <typ.UInt32> [0]))
+(Eq16 (Mod16u x (Const16 [c])) (Const16 [0])) && x.Op != OpConst16 && udivisibleOK16(c) && !hasSmallRotate(config) =>
+ (Eq32 (Mod32u <typ.UInt32> (ZeroExt16to32 <typ.UInt32> x) (Const32 <typ.UInt32> [int32(uint16(c))])) (Const32 <typ.UInt32> [0]))
+(Eq8 (Mod8 x (Const8 [c])) (Const8 [0])) && x.Op != OpConst8 && sdivisibleOK8(c) && !hasSmallRotate(config) =>
+ (Eq32 (Mod32 <typ.Int32> (SignExt8to32 <typ.Int32> x) (Const32 <typ.Int32> [int32(c)])) (Const32 <typ.Int32> [0]))
+(Eq16 (Mod16 x (Const16 [c])) (Const16 [0])) && x.Op != OpConst16 && sdivisibleOK16(c) && !hasSmallRotate(config) =>
+ (Eq32 (Mod32 <typ.Int32> (SignExt16to32 <typ.Int32> x) (Const32 <typ.Int32> [int32(c)])) (Const32 <typ.Int32> [0]))
+
+// Divisibility checks x%c == 0 convert to multiply and rotate.
+// Note, x%c == 0 is rewritten as x == c*(x/c) during the opt pass
+// where (x/c) is performed using multiplication with magic constants.
+// To rewrite x%c == 0 requires pattern matching the rewritten expression
+// and checking that the division by the same constant wasn't already calculated.
+// This check is made by counting uses of the magic constant multiplication.
+// Note that if there were an intermediate opt pass, this rule could be applied
+// directly on the Div op and magic division rewrites could be delayed to late opt.
+
+// Unsigned divisibility checks convert to multiply and rotate.
+(Eq8 x (Mul8 (Const8 [c])
+ (Trunc32to8
+ (Rsh32Ux64
+ mul:(Mul32
+ (Const32 [m])
+ (ZeroExt8to32 x))
+ (Const64 [s])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(1<<8+umagic8(c).m) && s == 8+umagic8(c).s
+ && x.Op != OpConst8 && udivisibleOK8(c)
+ => (Leq8U
+ (RotateLeft8 <typ.UInt8>
+ (Mul8 <typ.UInt8>
+ (Const8 <typ.UInt8> [int8(udivisible8(c).m)])
+ x)
+ (Const8 <typ.UInt8> [int8(8-udivisible8(c).k)])
+ )
+ (Const8 <typ.UInt8> [int8(udivisible8(c).max)])
+ )
+
+(Eq16 x (Mul16 (Const16 [c])
+ (Trunc64to16
+ (Rsh64Ux64
+ mul:(Mul64
+ (Const64 [m])
+ (ZeroExt16to64 x))
+ (Const64 [s])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int64(1<<16+umagic16(c).m) && s == 16+umagic16(c).s
+ && x.Op != OpConst16 && udivisibleOK16(c)
+ => (Leq16U
+ (RotateLeft16 <typ.UInt16>
+ (Mul16 <typ.UInt16>
+ (Const16 <typ.UInt16> [int16(udivisible16(c).m)])
+ x)
+ (Const16 <typ.UInt16> [int16(16-udivisible16(c).k)])
+ )
+ (Const16 <typ.UInt16> [int16(udivisible16(c).max)])
+ )
+
+(Eq16 x (Mul16 (Const16 [c])
+ (Trunc32to16
+ (Rsh32Ux64
+ mul:(Mul32
+ (Const32 [m])
+ (ZeroExt16to32 x))
+ (Const64 [s])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(1<<15+umagic16(c).m/2) && s == 16+umagic16(c).s-1
+ && x.Op != OpConst16 && udivisibleOK16(c)
+ => (Leq16U
+ (RotateLeft16 <typ.UInt16>
+ (Mul16 <typ.UInt16>
+ (Const16 <typ.UInt16> [int16(udivisible16(c).m)])
+ x)
+ (Const16 <typ.UInt16> [int16(16-udivisible16(c).k)])
+ )
+ (Const16 <typ.UInt16> [int16(udivisible16(c).max)])
+ )
+
+(Eq16 x (Mul16 (Const16 [c])
+ (Trunc32to16
+ (Rsh32Ux64
+ mul:(Mul32
+ (Const32 [m])
+ (Rsh32Ux64 (ZeroExt16to32 x) (Const64 [1])))
+ (Const64 [s])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(1<<15+(umagic16(c).m+1)/2) && s == 16+umagic16(c).s-2
+ && x.Op != OpConst16 && udivisibleOK16(c)
+ => (Leq16U
+ (RotateLeft16 <typ.UInt16>
+ (Mul16 <typ.UInt16>
+ (Const16 <typ.UInt16> [int16(udivisible16(c).m)])
+ x)
+ (Const16 <typ.UInt16> [int16(16-udivisible16(c).k)])
+ )
+ (Const16 <typ.UInt16> [int16(udivisible16(c).max)])
+ )
+
+(Eq16 x (Mul16 (Const16 [c])
+ (Trunc32to16
+ (Rsh32Ux64
+ (Avg32u
+ (Lsh32x64 (ZeroExt16to32 x) (Const64 [16]))
+ mul:(Mul32
+ (Const32 [m])
+ (ZeroExt16to32 x)))
+ (Const64 [s])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(umagic16(c).m) && s == 16+umagic16(c).s-1
+ && x.Op != OpConst16 && udivisibleOK16(c)
+ => (Leq16U
+ (RotateLeft16 <typ.UInt16>
+ (Mul16 <typ.UInt16>
+ (Const16 <typ.UInt16> [int16(udivisible16(c).m)])
+ x)
+ (Const16 <typ.UInt16> [int16(16-udivisible16(c).k)])
+ )
+ (Const16 <typ.UInt16> [int16(udivisible16(c).max)])
+ )
+
+(Eq32 x (Mul32 (Const32 [c])
+ (Rsh32Ux64
+ mul:(Hmul32u
+ (Const32 [m])
+ x)
+ (Const64 [s]))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(1<<31+umagic32(c).m/2) && s == umagic32(c).s-1
+ && x.Op != OpConst32 && udivisibleOK32(c)
+ => (Leq32U
+ (RotateLeft32 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(udivisible32(c).m)])
+ x)
+ (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
+ )
+ (Const32 <typ.UInt32> [int32(udivisible32(c).max)])
+ )
+
+(Eq32 x (Mul32 (Const32 [c])
+ (Rsh32Ux64
+ mul:(Hmul32u
+ (Const32 <typ.UInt32> [m])
+ (Rsh32Ux64 x (Const64 [1])))
+ (Const64 [s]))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(1<<31+(umagic32(c).m+1)/2) && s == umagic32(c).s-2
+ && x.Op != OpConst32 && udivisibleOK32(c)
+ => (Leq32U
+ (RotateLeft32 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(udivisible32(c).m)])
+ x)
+ (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
+ )
+ (Const32 <typ.UInt32> [int32(udivisible32(c).max)])
+ )
+
+(Eq32 x (Mul32 (Const32 [c])
+ (Rsh32Ux64
+ (Avg32u
+ x
+ mul:(Hmul32u
+ (Const32 [m])
+ x))
+ (Const64 [s]))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(umagic32(c).m) && s == umagic32(c).s-1
+ && x.Op != OpConst32 && udivisibleOK32(c)
+ => (Leq32U
+ (RotateLeft32 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(udivisible32(c).m)])
+ x)
+ (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
+ )
+ (Const32 <typ.UInt32> [int32(udivisible32(c).max)])
+ )
+
+(Eq32 x (Mul32 (Const32 [c])
+ (Trunc64to32
+ (Rsh64Ux64
+ mul:(Mul64
+ (Const64 [m])
+ (ZeroExt32to64 x))
+ (Const64 [s])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int64(1<<31+umagic32(c).m/2) && s == 32+umagic32(c).s-1
+ && x.Op != OpConst32 && udivisibleOK32(c)
+ => (Leq32U
+ (RotateLeft32 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(udivisible32(c).m)])
+ x)
+ (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
+ )
+ (Const32 <typ.UInt32> [int32(udivisible32(c).max)])
+ )
+
+(Eq32 x (Mul32 (Const32 [c])
+ (Trunc64to32
+ (Rsh64Ux64
+ mul:(Mul64
+ (Const64 [m])
+ (Rsh64Ux64 (ZeroExt32to64 x) (Const64 [1])))
+ (Const64 [s])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int64(1<<31+(umagic32(c).m+1)/2) && s == 32+umagic32(c).s-2
+ && x.Op != OpConst32 && udivisibleOK32(c)
+ => (Leq32U
+ (RotateLeft32 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(udivisible32(c).m)])
+ x)
+ (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
+ )
+ (Const32 <typ.UInt32> [int32(udivisible32(c).max)])
+ )
+
+(Eq32 x (Mul32 (Const32 [c])
+ (Trunc64to32
+ (Rsh64Ux64
+ (Avg64u
+ (Lsh64x64 (ZeroExt32to64 x) (Const64 [32]))
+ mul:(Mul64
+ (Const64 [m])
+ (ZeroExt32to64 x)))
+ (Const64 [s])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int64(umagic32(c).m) && s == 32+umagic32(c).s-1
+ && x.Op != OpConst32 && udivisibleOK32(c)
+ => (Leq32U
+ (RotateLeft32 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(udivisible32(c).m)])
+ x)
+ (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
+ )
+ (Const32 <typ.UInt32> [int32(udivisible32(c).max)])
+ )
+
+(Eq64 x (Mul64 (Const64 [c])
+ (Rsh64Ux64
+ mul:(Hmul64u
+ (Const64 [m])
+ x)
+ (Const64 [s]))
+ )
+) && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int64(1<<63+umagic64(c).m/2) && s == umagic64(c).s-1
+ && x.Op != OpConst64 && udivisibleOK64(c)
+ => (Leq64U
+ (RotateLeft64 <typ.UInt64>
+ (Mul64 <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(udivisible64(c).m)])
+ x)
+ (Const64 <typ.UInt64> [64-udivisible64(c).k])
+ )
+ (Const64 <typ.UInt64> [int64(udivisible64(c).max)])
+ )
+(Eq64 x (Mul64 (Const64 [c])
+ (Rsh64Ux64
+ mul:(Hmul64u
+ (Const64 [m])
+ (Rsh64Ux64 x (Const64 [1])))
+ (Const64 [s]))
+ )
+) && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int64(1<<63+(umagic64(c).m+1)/2) && s == umagic64(c).s-2
+ && x.Op != OpConst64 && udivisibleOK64(c)
+ => (Leq64U
+ (RotateLeft64 <typ.UInt64>
+ (Mul64 <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(udivisible64(c).m)])
+ x)
+ (Const64 <typ.UInt64> [64-udivisible64(c).k])
+ )
+ (Const64 <typ.UInt64> [int64(udivisible64(c).max)])
+ )
+(Eq64 x (Mul64 (Const64 [c])
+ (Rsh64Ux64
+ (Avg64u
+ x
+ mul:(Hmul64u
+ (Const64 [m])
+ x))
+ (Const64 [s]))
+ )
+) && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int64(umagic64(c).m) && s == umagic64(c).s-1
+ && x.Op != OpConst64 && udivisibleOK64(c)
+ => (Leq64U
+ (RotateLeft64 <typ.UInt64>
+ (Mul64 <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(udivisible64(c).m)])
+ x)
+ (Const64 <typ.UInt64> [64-udivisible64(c).k])
+ )
+ (Const64 <typ.UInt64> [int64(udivisible64(c).max)])
+ )
+
+// Signed divisibility checks convert to multiply, add and rotate.
+(Eq8 x (Mul8 (Const8 [c])
+ (Sub8
+ (Rsh32x64
+ mul:(Mul32
+ (Const32 [m])
+ (SignExt8to32 x))
+ (Const64 [s]))
+ (Rsh32x64
+ (SignExt8to32 x)
+ (Const64 [31])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(smagic8(c).m) && s == 8+smagic8(c).s
+ && x.Op != OpConst8 && sdivisibleOK8(c)
+ => (Leq8U
+ (RotateLeft8 <typ.UInt8>
+ (Add8 <typ.UInt8>
+ (Mul8 <typ.UInt8>
+ (Const8 <typ.UInt8> [int8(sdivisible8(c).m)])
+ x)
+ (Const8 <typ.UInt8> [int8(sdivisible8(c).a)])
+ )
+ (Const8 <typ.UInt8> [int8(8-sdivisible8(c).k)])
+ )
+ (Const8 <typ.UInt8> [int8(sdivisible8(c).max)])
+ )
+
+(Eq16 x (Mul16 (Const16 [c])
+ (Sub16
+ (Rsh32x64
+ mul:(Mul32
+ (Const32 [m])
+ (SignExt16to32 x))
+ (Const64 [s]))
+ (Rsh32x64
+ (SignExt16to32 x)
+ (Const64 [31])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(smagic16(c).m) && s == 16+smagic16(c).s
+ && x.Op != OpConst16 && sdivisibleOK16(c)
+ => (Leq16U
+ (RotateLeft16 <typ.UInt16>
+ (Add16 <typ.UInt16>
+ (Mul16 <typ.UInt16>
+ (Const16 <typ.UInt16> [int16(sdivisible16(c).m)])
+ x)
+ (Const16 <typ.UInt16> [int16(sdivisible16(c).a)])
+ )
+ (Const16 <typ.UInt16> [int16(16-sdivisible16(c).k)])
+ )
+ (Const16 <typ.UInt16> [int16(sdivisible16(c).max)])
+ )
+
+(Eq32 x (Mul32 (Const32 [c])
+ (Sub32
+ (Rsh64x64
+ mul:(Mul64
+ (Const64 [m])
+ (SignExt32to64 x))
+ (Const64 [s]))
+ (Rsh64x64
+ (SignExt32to64 x)
+ (Const64 [63])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int64(smagic32(c).m) && s == 32+smagic32(c).s
+ && x.Op != OpConst32 && sdivisibleOK32(c)
+ => (Leq32U
+ (RotateLeft32 <typ.UInt32>
+ (Add32 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(sdivisible32(c).m)])
+ x)
+ (Const32 <typ.UInt32> [int32(sdivisible32(c).a)])
+ )
+ (Const32 <typ.UInt32> [int32(32-sdivisible32(c).k)])
+ )
+ (Const32 <typ.UInt32> [int32(sdivisible32(c).max)])
+ )
+
+(Eq32 x (Mul32 (Const32 [c])
+ (Sub32
+ (Rsh32x64
+ mul:(Hmul32
+ (Const32 [m])
+ x)
+ (Const64 [s]))
+ (Rsh32x64
+ x
+ (Const64 [31])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(smagic32(c).m/2) && s == smagic32(c).s-1
+ && x.Op != OpConst32 && sdivisibleOK32(c)
+ => (Leq32U
+ (RotateLeft32 <typ.UInt32>
+ (Add32 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(sdivisible32(c).m)])
+ x)
+ (Const32 <typ.UInt32> [int32(sdivisible32(c).a)])
+ )
+ (Const32 <typ.UInt32> [int32(32-sdivisible32(c).k)])
+ )
+ (Const32 <typ.UInt32> [int32(sdivisible32(c).max)])
+ )
+
+(Eq32 x (Mul32 (Const32 [c])
+ (Sub32
+ (Rsh32x64
+ (Add32
+ mul:(Hmul32
+ (Const32 [m])
+ x)
+ x)
+ (Const64 [s]))
+ (Rsh32x64
+ x
+ (Const64 [31])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int32(smagic32(c).m) && s == smagic32(c).s
+ && x.Op != OpConst32 && sdivisibleOK32(c)
+ => (Leq32U
+ (RotateLeft32 <typ.UInt32>
+ (Add32 <typ.UInt32>
+ (Mul32 <typ.UInt32>
+ (Const32 <typ.UInt32> [int32(sdivisible32(c).m)])
+ x)
+ (Const32 <typ.UInt32> [int32(sdivisible32(c).a)])
+ )
+ (Const32 <typ.UInt32> [int32(32-sdivisible32(c).k)])
+ )
+ (Const32 <typ.UInt32> [int32(sdivisible32(c).max)])
+ )
+
+(Eq64 x (Mul64 (Const64 [c])
+ (Sub64
+ (Rsh64x64
+ mul:(Hmul64
+ (Const64 [m])
+ x)
+ (Const64 [s]))
+ (Rsh64x64
+ x
+ (Const64 [63])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int64(smagic64(c).m/2) && s == smagic64(c).s-1
+ && x.Op != OpConst64 && sdivisibleOK64(c)
+ => (Leq64U
+ (RotateLeft64 <typ.UInt64>
+ (Add64 <typ.UInt64>
+ (Mul64 <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(sdivisible64(c).m)])
+ x)
+ (Const64 <typ.UInt64> [int64(sdivisible64(c).a)])
+ )
+ (Const64 <typ.UInt64> [64-sdivisible64(c).k])
+ )
+ (Const64 <typ.UInt64> [int64(sdivisible64(c).max)])
+ )
+
+(Eq64 x (Mul64 (Const64 [c])
+ (Sub64
+ (Rsh64x64
+ (Add64
+ mul:(Hmul64
+ (Const64 [m])
+ x)
+ x)
+ (Const64 [s]))
+ (Rsh64x64
+ x
+ (Const64 [63])))
+ )
+)
+ && v.Block.Func.pass.name != "opt" && mul.Uses == 1
+ && m == int64(smagic64(c).m) && s == smagic64(c).s
+ && x.Op != OpConst64 && sdivisibleOK64(c)
+ => (Leq64U
+ (RotateLeft64 <typ.UInt64>
+ (Add64 <typ.UInt64>
+ (Mul64 <typ.UInt64>
+ (Const64 <typ.UInt64> [int64(sdivisible64(c).m)])
+ x)
+ (Const64 <typ.UInt64> [int64(sdivisible64(c).a)])
+ )
+ (Const64 <typ.UInt64> [64-sdivisible64(c).k])
+ )
+ (Const64 <typ.UInt64> [int64(sdivisible64(c).max)])
+ )
+
+// Divisibility check for signed integers for power of two constant are simple mask.
+// However, we must match against the rewritten n%c == 0 -> n - c*(n/c) == 0 -> n == c*(n/c)
+// where n/c contains fixup code to handle signed n.
+((Eq8|Neq8) n (Lsh8x64
+ (Rsh8x64
+ (Add8 <t> n (Rsh8Ux64 <t> (Rsh8x64 <t> n (Const64 <typ.UInt64> [ 7])) (Const64 <typ.UInt64> [kbar])))
+ (Const64 <typ.UInt64> [k]))
+ (Const64 <typ.UInt64> [k]))
+) && k > 0 && k < 7 && kbar == 8 - k
+ => ((Eq8|Neq8) (And8 <t> n (Const8 <t> [1<<uint(k)-1])) (Const8 <t> [0]))
+
+((Eq16|Neq16) n (Lsh16x64
+ (Rsh16x64
+ (Add16 <t> n (Rsh16Ux64 <t> (Rsh16x64 <t> n (Const64 <typ.UInt64> [15])) (Const64 <typ.UInt64> [kbar])))
+ (Const64 <typ.UInt64> [k]))
+ (Const64 <typ.UInt64> [k]))
+) && k > 0 && k < 15 && kbar == 16 - k
+ => ((Eq16|Neq16) (And16 <t> n (Const16 <t> [1<<uint(k)-1])) (Const16 <t> [0]))
+
+((Eq32|Neq32) n (Lsh32x64
+ (Rsh32x64
+ (Add32 <t> n (Rsh32Ux64 <t> (Rsh32x64 <t> n (Const64 <typ.UInt64> [31])) (Const64 <typ.UInt64> [kbar])))
+ (Const64 <typ.UInt64> [k]))
+ (Const64 <typ.UInt64> [k]))
+) && k > 0 && k < 31 && kbar == 32 - k
+ => ((Eq32|Neq32) (And32 <t> n (Const32 <t> [1<<uint(k)-1])) (Const32 <t> [0]))
+
+((Eq64|Neq64) n (Lsh64x64
+ (Rsh64x64
+ (Add64 <t> n (Rsh64Ux64 <t> (Rsh64x64 <t> n (Const64 <typ.UInt64> [63])) (Const64 <typ.UInt64> [kbar])))
+ (Const64 <typ.UInt64> [k]))
+ (Const64 <typ.UInt64> [k]))
+) && k > 0 && k < 63 && kbar == 64 - k
+ => ((Eq64|Neq64) (And64 <t> n (Const64 <t> [1<<uint(k)-1])) (Const64 <t> [0]))
+
+(Eq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 => (Eq(8|16|32|64) x y)
+(Neq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 => (Neq(8|16|32|64) x y)
+
+// Optimize bitsets
+(Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y])) && oneBit8(y)
+ => (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
+(Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y])) && oneBit16(y)
+ => (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
+(Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y])) && oneBit32(y)
+ => (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
+(Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y])) && oneBit64(y)
+ => (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
+(Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y])) && oneBit8(y)
+ => (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
+(Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y])) && oneBit16(y)
+ => (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
+(Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y])) && oneBit32(y)
+ => (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
+(Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y])) && oneBit64(y)
+ => (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
+
+// Reassociate expressions involving
+// constants such that constants come first,
+// exposing obvious constant-folding opportunities.
+// Reassociate (op (op y C) x) to (op C (op x y)) or similar, where C
+// is constant, which pushes constants to the outside
+// of the expression. At that point, any constant-folding
+// opportunities should be obvious.
+// Note: don't include AddPtr here! In order to maintain the
+// invariant that pointers must stay within the pointed-to object,
+// we can't pull part of a pointer computation above the AddPtr.
+// See issue 37881.
+// Note: we don't need to handle any (x-C) cases because we already rewrite
+// (x-C) to (x+(-C)).
+
+// x + (C + z) -> C + (x + z)
+(Add64 (Add64 i:(Const64 <t>) z) x) && (z.Op != OpConst64 && x.Op != OpConst64) => (Add64 i (Add64 <t> z x))
+(Add32 (Add32 i:(Const32 <t>) z) x) && (z.Op != OpConst32 && x.Op != OpConst32) => (Add32 i (Add32 <t> z x))
+(Add16 (Add16 i:(Const16 <t>) z) x) && (z.Op != OpConst16 && x.Op != OpConst16) => (Add16 i (Add16 <t> z x))
+(Add8 (Add8 i:(Const8 <t>) z) x) && (z.Op != OpConst8 && x.Op != OpConst8) => (Add8 i (Add8 <t> z x))
+
+// x + (C - z) -> C + (x - z)
+(Add64 (Sub64 i:(Const64 <t>) z) x) && (z.Op != OpConst64 && x.Op != OpConst64) => (Add64 i (Sub64 <t> x z))
+(Add32 (Sub32 i:(Const32 <t>) z) x) && (z.Op != OpConst32 && x.Op != OpConst32) => (Add32 i (Sub32 <t> x z))
+(Add16 (Sub16 i:(Const16 <t>) z) x) && (z.Op != OpConst16 && x.Op != OpConst16) => (Add16 i (Sub16 <t> x z))
+(Add8 (Sub8 i:(Const8 <t>) z) x) && (z.Op != OpConst8 && x.Op != OpConst8) => (Add8 i (Sub8 <t> x z))
+
+// x - (C - z) -> x + (z - C) -> (x + z) - C
+(Sub64 x (Sub64 i:(Const64 <t>) z)) && (z.Op != OpConst64 && x.Op != OpConst64) => (Sub64 (Add64 <t> x z) i)
+(Sub32 x (Sub32 i:(Const32 <t>) z)) && (z.Op != OpConst32 && x.Op != OpConst32) => (Sub32 (Add32 <t> x z) i)
+(Sub16 x (Sub16 i:(Const16 <t>) z)) && (z.Op != OpConst16 && x.Op != OpConst16) => (Sub16 (Add16 <t> x z) i)
+(Sub8 x (Sub8 i:(Const8 <t>) z)) && (z.Op != OpConst8 && x.Op != OpConst8) => (Sub8 (Add8 <t> x z) i)
+
+// x - (z + C) -> x + (-z - C) -> (x - z) - C
+(Sub64 x (Add64 z i:(Const64 <t>))) && (z.Op != OpConst64 && x.Op != OpConst64) => (Sub64 (Sub64 <t> x z) i)
+(Sub32 x (Add32 z i:(Const32 <t>))) && (z.Op != OpConst32 && x.Op != OpConst32) => (Sub32 (Sub32 <t> x z) i)
+(Sub16 x (Add16 z i:(Const16 <t>))) && (z.Op != OpConst16 && x.Op != OpConst16) => (Sub16 (Sub16 <t> x z) i)
+(Sub8 x (Add8 z i:(Const8 <t>))) && (z.Op != OpConst8 && x.Op != OpConst8) => (Sub8 (Sub8 <t> x z) i)
+
+// (C - z) - x -> C - (z + x)
+(Sub64 (Sub64 i:(Const64 <t>) z) x) && (z.Op != OpConst64 && x.Op != OpConst64) => (Sub64 i (Add64 <t> z x))
+(Sub32 (Sub32 i:(Const32 <t>) z) x) && (z.Op != OpConst32 && x.Op != OpConst32) => (Sub32 i (Add32 <t> z x))
+(Sub16 (Sub16 i:(Const16 <t>) z) x) && (z.Op != OpConst16 && x.Op != OpConst16) => (Sub16 i (Add16 <t> z x))
+(Sub8 (Sub8 i:(Const8 <t>) z) x) && (z.Op != OpConst8 && x.Op != OpConst8) => (Sub8 i (Add8 <t> z x))
+
+// (z + C) -x -> C + (z - x)
+(Sub64 (Add64 z i:(Const64 <t>)) x) && (z.Op != OpConst64 && x.Op != OpConst64) => (Add64 i (Sub64 <t> z x))
+(Sub32 (Add32 z i:(Const32 <t>)) x) && (z.Op != OpConst32 && x.Op != OpConst32) => (Add32 i (Sub32 <t> z x))
+(Sub16 (Add16 z i:(Const16 <t>)) x) && (z.Op != OpConst16 && x.Op != OpConst16) => (Add16 i (Sub16 <t> z x))
+(Sub8 (Add8 z i:(Const8 <t>)) x) && (z.Op != OpConst8 && x.Op != OpConst8) => (Add8 i (Sub8 <t> z x))
+
+// x & (C & z) -> C & (x & z)
+(And64 (And64 i:(Const64 <t>) z) x) && (z.Op != OpConst64 && x.Op != OpConst64) => (And64 i (And64 <t> z x))
+(And32 (And32 i:(Const32 <t>) z) x) && (z.Op != OpConst32 && x.Op != OpConst32) => (And32 i (And32 <t> z x))
+(And16 (And16 i:(Const16 <t>) z) x) && (z.Op != OpConst16 && x.Op != OpConst16) => (And16 i (And16 <t> z x))
+(And8 (And8 i:(Const8 <t>) z) x) && (z.Op != OpConst8 && x.Op != OpConst8) => (And8 i (And8 <t> z x))
+
+// x | (C | z) -> C | (x | z)
+(Or64 (Or64 i:(Const64 <t>) z) x) && (z.Op != OpConst64 && x.Op != OpConst64) => (Or64 i (Or64 <t> z x))
+(Or32 (Or32 i:(Const32 <t>) z) x) && (z.Op != OpConst32 && x.Op != OpConst32) => (Or32 i (Or32 <t> z x))
+(Or16 (Or16 i:(Const16 <t>) z) x) && (z.Op != OpConst16 && x.Op != OpConst16) => (Or16 i (Or16 <t> z x))
+(Or8 (Or8 i:(Const8 <t>) z) x) && (z.Op != OpConst8 && x.Op != OpConst8) => (Or8 i (Or8 <t> z x))
+
+// x ^ (C ^ z) -> C ^ (x ^ z)
+(Xor64 (Xor64 i:(Const64 <t>) z) x) && (z.Op != OpConst64 && x.Op != OpConst64) => (Xor64 i (Xor64 <t> z x))
+(Xor32 (Xor32 i:(Const32 <t>) z) x) && (z.Op != OpConst32 && x.Op != OpConst32) => (Xor32 i (Xor32 <t> z x))
+(Xor16 (Xor16 i:(Const16 <t>) z) x) && (z.Op != OpConst16 && x.Op != OpConst16) => (Xor16 i (Xor16 <t> z x))
+(Xor8 (Xor8 i:(Const8 <t>) z) x) && (z.Op != OpConst8 && x.Op != OpConst8) => (Xor8 i (Xor8 <t> z x))
+
+// x * (D * z) = D * (x * z)
+(Mul64 (Mul64 i:(Const64 <t>) z) x) && (z.Op != OpConst64 && x.Op != OpConst64) => (Mul64 i (Mul64 <t> x z))
+(Mul32 (Mul32 i:(Const32 <t>) z) x) && (z.Op != OpConst32 && x.Op != OpConst32) => (Mul32 i (Mul32 <t> x z))
+(Mul16 (Mul16 i:(Const16 <t>) z) x) && (z.Op != OpConst16 && x.Op != OpConst16) => (Mul16 i (Mul16 <t> x z))
+(Mul8 (Mul8 i:(Const8 <t>) z) x) && (z.Op != OpConst8 && x.Op != OpConst8) => (Mul8 i (Mul8 <t> x z))
+
+// C + (D + x) -> (C + D) + x
+(Add64 (Const64 <t> [c]) (Add64 (Const64 <t> [d]) x)) => (Add64 (Const64 <t> [c+d]) x)
+(Add32 (Const32 <t> [c]) (Add32 (Const32 <t> [d]) x)) => (Add32 (Const32 <t> [c+d]) x)
+(Add16 (Const16 <t> [c]) (Add16 (Const16 <t> [d]) x)) => (Add16 (Const16 <t> [c+d]) x)
+(Add8 (Const8 <t> [c]) (Add8 (Const8 <t> [d]) x)) => (Add8 (Const8 <t> [c+d]) x)
+
+// C + (D - x) -> (C + D) - x
+(Add64 (Const64 <t> [c]) (Sub64 (Const64 <t> [d]) x)) => (Sub64 (Const64 <t> [c+d]) x)
+(Add32 (Const32 <t> [c]) (Sub32 (Const32 <t> [d]) x)) => (Sub32 (Const32 <t> [c+d]) x)
+(Add16 (Const16 <t> [c]) (Sub16 (Const16 <t> [d]) x)) => (Sub16 (Const16 <t> [c+d]) x)
+(Add8 (Const8 <t> [c]) (Sub8 (Const8 <t> [d]) x)) => (Sub8 (Const8 <t> [c+d]) x)
+
+// C - (D - x) -> (C - D) + x
+(Sub64 (Const64 <t> [c]) (Sub64 (Const64 <t> [d]) x)) => (Add64 (Const64 <t> [c-d]) x)
+(Sub32 (Const32 <t> [c]) (Sub32 (Const32 <t> [d]) x)) => (Add32 (Const32 <t> [c-d]) x)
+(Sub16 (Const16 <t> [c]) (Sub16 (Const16 <t> [d]) x)) => (Add16 (Const16 <t> [c-d]) x)
+(Sub8 (Const8 <t> [c]) (Sub8 (Const8 <t> [d]) x)) => (Add8 (Const8 <t> [c-d]) x)
+
+// C - (D + x) -> (C - D) - x
+(Sub64 (Const64 <t> [c]) (Add64 (Const64 <t> [d]) x)) => (Sub64 (Const64 <t> [c-d]) x)
+(Sub32 (Const32 <t> [c]) (Add32 (Const32 <t> [d]) x)) => (Sub32 (Const32 <t> [c-d]) x)
+(Sub16 (Const16 <t> [c]) (Add16 (Const16 <t> [d]) x)) => (Sub16 (Const16 <t> [c-d]) x)
+(Sub8 (Const8 <t> [c]) (Add8 (Const8 <t> [d]) x)) => (Sub8 (Const8 <t> [c-d]) x)
+
+// C & (D & x) -> (C & D) & x
+(And64 (Const64 <t> [c]) (And64 (Const64 <t> [d]) x)) => (And64 (Const64 <t> [c&d]) x)
+(And32 (Const32 <t> [c]) (And32 (Const32 <t> [d]) x)) => (And32 (Const32 <t> [c&d]) x)
+(And16 (Const16 <t> [c]) (And16 (Const16 <t> [d]) x)) => (And16 (Const16 <t> [c&d]) x)
+(And8 (Const8 <t> [c]) (And8 (Const8 <t> [d]) x)) => (And8 (Const8 <t> [c&d]) x)
+
+// C | (D | x) -> (C | D) | x
+(Or64 (Const64 <t> [c]) (Or64 (Const64 <t> [d]) x)) => (Or64 (Const64 <t> [c|d]) x)
+(Or32 (Const32 <t> [c]) (Or32 (Const32 <t> [d]) x)) => (Or32 (Const32 <t> [c|d]) x)
+(Or16 (Const16 <t> [c]) (Or16 (Const16 <t> [d]) x)) => (Or16 (Const16 <t> [c|d]) x)
+(Or8 (Const8 <t> [c]) (Or8 (Const8 <t> [d]) x)) => (Or8 (Const8 <t> [c|d]) x)
+
+// C ^ (D ^ x) -> (C ^ D) ^ x
+(Xor64 (Const64 <t> [c]) (Xor64 (Const64 <t> [d]) x)) => (Xor64 (Const64 <t> [c^d]) x)
+(Xor32 (Const32 <t> [c]) (Xor32 (Const32 <t> [d]) x)) => (Xor32 (Const32 <t> [c^d]) x)
+(Xor16 (Const16 <t> [c]) (Xor16 (Const16 <t> [d]) x)) => (Xor16 (Const16 <t> [c^d]) x)
+(Xor8 (Const8 <t> [c]) (Xor8 (Const8 <t> [d]) x)) => (Xor8 (Const8 <t> [c^d]) x)
+
+// C * (D * x) = (C * D) * x
+(Mul64 (Const64 <t> [c]) (Mul64 (Const64 <t> [d]) x)) => (Mul64 (Const64 <t> [c*d]) x)
+(Mul32 (Const32 <t> [c]) (Mul32 (Const32 <t> [d]) x)) => (Mul32 (Const32 <t> [c*d]) x)
+(Mul16 (Const16 <t> [c]) (Mul16 (Const16 <t> [d]) x)) => (Mul16 (Const16 <t> [c*d]) x)
+(Mul8 (Const8 <t> [c]) (Mul8 (Const8 <t> [d]) x)) => (Mul8 (Const8 <t> [c*d]) x)
+
+// floating point optimizations
+(Mul(32|64)F x (Const(32|64)F [1])) => x
+(Mul32F x (Const32F [-1])) => (Neg32F x)
+(Mul64F x (Const64F [-1])) => (Neg64F x)
+(Mul32F x (Const32F [2])) => (Add32F x x)
+(Mul64F x (Const64F [2])) => (Add64F x x)
+
+(Div32F x (Const32F <t> [c])) && reciprocalExact32(c) => (Mul32F x (Const32F <t> [1/c]))
+(Div64F x (Const64F <t> [c])) && reciprocalExact64(c) => (Mul64F x (Const64F <t> [1/c]))
+
+(Sqrt (Const64F [c])) && !math.IsNaN(math.Sqrt(c)) => (Const64F [math.Sqrt(c)])
+
+// recognize runtime.newobject and don't Zero/Nilcheck it
+(Zero (Load (OffPtr [c] (SP)) mem) mem)
+ && mem.Op == OpStaticCall
+ && isSameCall(mem.Aux, "runtime.newobject")
+ && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value
+ => mem
+(Store (Load (OffPtr [c] (SP)) mem) x mem)
+ && isConstZero(x)
+ && mem.Op == OpStaticCall
+ && isSameCall(mem.Aux, "runtime.newobject")
+ && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value
+ => mem
+(Store (OffPtr (Load (OffPtr [c] (SP)) mem)) x mem)
+ && isConstZero(x)
+ && mem.Op == OpStaticCall
+ && isSameCall(mem.Aux, "runtime.newobject")
+ && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value
+ => mem
+// nil checks just need to rewrite to something useless.
+// they will be deadcode eliminated soon afterwards.
+(NilCheck (Load (OffPtr [c] (SP)) (StaticCall {sym} _)) _)
+ && isSameCall(sym, "runtime.newobject")
+ && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value
+ && warnRule(fe.Debug_checknil(), v, "removed nil check")
+ => (Invalid)
+(NilCheck (OffPtr (Load (OffPtr [c] (SP)) (StaticCall {sym} _))) _)
+ && isSameCall(sym, "runtime.newobject")
+ && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value
+ && warnRule(fe.Debug_checknil(), v, "removed nil check")
+ => (Invalid)
+
+// for rewriting results of some late-expanded rewrites (below)
+(SelectN [0] (MakeResult a ___)) => a
+(SelectN [1] (MakeResult a b ___)) => b
+(SelectN [2] (MakeResult a b c ___)) => c
+
+// for late-expanded calls, recognize newobject and remove zeroing and nilchecks
+(Zero (SelectN [0] call:(StaticLECall _ _)) mem:(SelectN [1] call))
+ && isSameCall(call.Aux, "runtime.newobject")
+ => mem
+
+(Store (SelectN [0] call:(StaticLECall _ _)) x mem:(SelectN [1] call))
+ && isConstZero(x)
+ && isSameCall(call.Aux, "runtime.newobject")
+ => mem
+
+(Store (OffPtr (SelectN [0] call:(StaticLECall _ _))) x mem:(SelectN [1] call))
+ && isConstZero(x)
+ && isSameCall(call.Aux, "runtime.newobject")
+ => mem
+
+(NilCheck (SelectN [0] call:(StaticLECall _ _)) (SelectN [1] call))
+ && isSameCall(call.Aux, "runtime.newobject")
+ && warnRule(fe.Debug_checknil(), v, "removed nil check")
+ => (Invalid)
+
+(NilCheck (OffPtr (SelectN [0] call:(StaticLECall _ _))) (SelectN [1] call))
+ && isSameCall(call.Aux, "runtime.newobject")
+ && warnRule(fe.Debug_checknil(), v, "removed nil check")
+ => (Invalid)
+
+// for late-expanded calls, recognize memequal applied to a single constant byte
+// TODO figure out breakeven number of bytes for this optimization.
+(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [1]) mem)
+ && isSameCall(callAux, "runtime.memequal")
+ && symIsRO(scon)
+ => (MakeResult (Eq8 (Load <typ.Int8> sptr mem) (Const8 <typ.Int8> [int8(read8(scon,0))])) mem)
+
+// Evaluate constant address comparisons.
+(EqPtr x x) => (ConstBool [true])
+(NeqPtr x x) => (ConstBool [false])
+(EqPtr (Addr {a} _) (Addr {b} _)) => (ConstBool [a == b])
+(EqPtr (Addr {a} _) (OffPtr [o] (Addr {b} _))) => (ConstBool [a == b && o == 0])
+(EqPtr (OffPtr [o1] (Addr {a} _)) (OffPtr [o2] (Addr {b} _))) => (ConstBool [a == b && o1 == o2])
+(NeqPtr (Addr {a} _) (Addr {b} _)) => (ConstBool [a != b])
+(NeqPtr (Addr {a} _) (OffPtr [o] (Addr {b} _))) => (ConstBool [a != b || o != 0])
+(NeqPtr (OffPtr [o1] (Addr {a} _)) (OffPtr [o2] (Addr {b} _))) => (ConstBool [a != b || o1 != o2])
+(EqPtr (LocalAddr {a} _ _) (LocalAddr {b} _ _)) => (ConstBool [a == b])
+(EqPtr (LocalAddr {a} _ _) (OffPtr [o] (LocalAddr {b} _ _))) => (ConstBool [a == b && o == 0])
+(EqPtr (OffPtr [o1] (LocalAddr {a} _ _)) (OffPtr [o2] (LocalAddr {b} _ _))) => (ConstBool [a == b && o1 == o2])
+(NeqPtr (LocalAddr {a} _ _) (LocalAddr {b} _ _)) => (ConstBool [a != b])
+(NeqPtr (LocalAddr {a} _ _) (OffPtr [o] (LocalAddr {b} _ _))) => (ConstBool [a != b || o != 0])
+(NeqPtr (OffPtr [o1] (LocalAddr {a} _ _)) (OffPtr [o2] (LocalAddr {b} _ _))) => (ConstBool [a != b || o1 != o2])
+(EqPtr (OffPtr [o1] p1) p2) && isSamePtr(p1, p2) => (ConstBool [o1 == 0])
+(NeqPtr (OffPtr [o1] p1) p2) && isSamePtr(p1, p2) => (ConstBool [o1 != 0])
+(EqPtr (OffPtr [o1] p1) (OffPtr [o2] p2)) && isSamePtr(p1, p2) => (ConstBool [o1 == o2])
+(NeqPtr (OffPtr [o1] p1) (OffPtr [o2] p2)) && isSamePtr(p1, p2) => (ConstBool [o1 != o2])
+(EqPtr (Const(32|64) [c]) (Const(32|64) [d])) => (ConstBool [c == d])
+(NeqPtr (Const(32|64) [c]) (Const(32|64) [d])) => (ConstBool [c != d])
+
+(EqPtr (LocalAddr _ _) (Addr _)) => (ConstBool [false])
+(EqPtr (OffPtr (LocalAddr _ _)) (Addr _)) => (ConstBool [false])
+(EqPtr (LocalAddr _ _) (OffPtr (Addr _))) => (ConstBool [false])
+(EqPtr (OffPtr (LocalAddr _ _)) (OffPtr (Addr _))) => (ConstBool [false])
+(NeqPtr (LocalAddr _ _) (Addr _)) => (ConstBool [true])
+(NeqPtr (OffPtr (LocalAddr _ _)) (Addr _)) => (ConstBool [true])
+(NeqPtr (LocalAddr _ _) (OffPtr (Addr _))) => (ConstBool [true])
+(NeqPtr (OffPtr (LocalAddr _ _)) (OffPtr (Addr _))) => (ConstBool [true])
+
+// Simplify address comparisons.
+(EqPtr (AddPtr p1 o1) p2) && isSamePtr(p1, p2) => (Not (IsNonNil o1))
+(NeqPtr (AddPtr p1 o1) p2) && isSamePtr(p1, p2) => (IsNonNil o1)
+(EqPtr (Const(32|64) [0]) p) => (Not (IsNonNil p))
+(NeqPtr (Const(32|64) [0]) p) => (IsNonNil p)
+(EqPtr (ConstNil) p) => (Not (IsNonNil p))
+(NeqPtr (ConstNil) p) => (IsNonNil p)
+
+// Evaluate constant user nil checks.
+(IsNonNil (ConstNil)) => (ConstBool [false])
+(IsNonNil (Const(32|64) [c])) => (ConstBool [c != 0])
+(IsNonNil (Addr _)) => (ConstBool [true])
+(IsNonNil (LocalAddr _ _)) => (ConstBool [true])
+
+// Inline small or disjoint runtime.memmove calls with constant length.
+// See the comment in op Move in genericOps.go for discussion of the type.
+(StaticCall {sym} s1:(Store _ (Const(64|32) [sz]) s2:(Store _ src s3:(Store {t} _ dst mem))))
+ && sz >= 0
+ && isSameCall(sym, "runtime.memmove")
+ && t.IsPtr() // avoids TUINTPTR, see issue 30061
+ && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1
+ && isInlinableMemmove(dst, src, int64(sz), config)
+ && clobber(s1, s2, s3)
+ => (Move {t.Elem()} [int64(sz)] dst src mem)
+
+// Inline small or disjoint runtime.memmove calls with constant length.
+// See the comment in op Move in genericOps.go for discussion of the type.
+(SelectN [0] call:(StaticLECall {sym} dst src (Const(64|32) [sz]) mem))
+ && sz >= 0
+ && call.Uses == 1 // this will exclude all calls with results
+ && isSameCall(sym, "runtime.memmove")
+ && dst.Type.IsPtr() // avoids TUINTPTR, see issue 30061
+ && isInlinableMemmove(dst, src, int64(sz), config)
+ && clobber(call)
+ => (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
+
+// De-virtualize interface calls into static calls.
+// Note that (ITab (IMake)) doesn't get
+// rewritten until after the first opt pass,
+// so this rule should trigger reliably.
+(InterCall [argsize] {auxCall} (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) mem) && devirt(v, auxCall, itab, off) != nil =>
+ (StaticCall [int32(argsize)] {devirt(v, auxCall, itab, off)} mem)
+
+// De-virtualize late-expanded interface calls into late-expanded static calls.
+// Note that (ITab (IMake)) doesn't get rewritten until after the first opt pass,
+// so this rule should trigger reliably.
+// devirtLECall removes the first argument, adds the devirtualized symbol to the AuxCall, and changes the opcode
+(InterLECall [argsize] {auxCall} (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) ___) && devirtLESym(v, auxCall, itab, off) !=
+ nil => devirtLECall(v, devirtLESym(v, auxCall, itab, off))
+
+// Move and Zero optimizations.
+// Move source and destination may overlap.
+
+// Convert Moves into Zeros when the source is known to be zeros.
+(Move {t} [n] dst1 src mem:(Zero {t} [n] dst2 _)) && isSamePtr(src, dst2)
+ => (Zero {t} [n] dst1 mem)
+(Move {t} [n] dst1 src mem:(VarDef (Zero {t} [n] dst0 _))) && isSamePtr(src, dst0)
+ => (Zero {t} [n] dst1 mem)
+(Move {t} [n] dst (Addr {sym} (SB)) mem) && symIsROZero(sym) => (Zero {t} [n] dst mem)
+
+// Don't Store to variables that are about to be overwritten by Move/Zero.
+(Zero {t1} [n] p1 store:(Store {t2} (OffPtr [o2] p2) _ mem))
+ && isSamePtr(p1, p2) && store.Uses == 1
+ && n >= o2 + t2.Size()
+ && clobber(store)
+ => (Zero {t1} [n] p1 mem)
+(Move {t1} [n] dst1 src1 store:(Store {t2} op:(OffPtr [o2] dst2) _ mem))
+ && isSamePtr(dst1, dst2) && store.Uses == 1
+ && n >= o2 + t2.Size()
+ && disjoint(src1, n, op, t2.Size())
+ && clobber(store)
+ => (Move {t1} [n] dst1 src1 mem)
+
+// Don't Move to variables that are immediately completely overwritten.
+(Zero {t} [n] dst1 move:(Move {t} [n] dst2 _ mem))
+ && move.Uses == 1
+ && isSamePtr(dst1, dst2)
+ && clobber(move)
+ => (Zero {t} [n] dst1 mem)
+(Move {t} [n] dst1 src1 move:(Move {t} [n] dst2 _ mem))
+ && move.Uses == 1
+ && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n)
+ && clobber(move)
+ => (Move {t} [n] dst1 src1 mem)
+(Zero {t} [n] dst1 vardef:(VarDef {x} move:(Move {t} [n] dst2 _ mem)))
+ && move.Uses == 1 && vardef.Uses == 1
+ && isSamePtr(dst1, dst2)
+ && clobber(move, vardef)
+ => (Zero {t} [n] dst1 (VarDef {x} mem))
+(Move {t} [n] dst1 src1 vardef:(VarDef {x} move:(Move {t} [n] dst2 _ mem)))
+ && move.Uses == 1 && vardef.Uses == 1
+ && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n)
+ && clobber(move, vardef)
+ => (Move {t} [n] dst1 src1 (VarDef {x} mem))
+(Store {t1} op1:(OffPtr [o1] p1) d1
+ m2:(Store {t2} op2:(OffPtr [0] p2) d2
+ m3:(Move [n] p3 _ mem)))
+ && m2.Uses == 1 && m3.Uses == 1
+ && o1 == t2.Size()
+ && n == t2.Size() + t1.Size()
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3)
+ && clobber(m2, m3)
+ => (Store {t1} op1 d1 (Store {t2} op2 d2 mem))
+(Store {t1} op1:(OffPtr [o1] p1) d1
+ m2:(Store {t2} op2:(OffPtr [o2] p2) d2
+ m3:(Store {t3} op3:(OffPtr [0] p3) d3
+ m4:(Move [n] p4 _ mem))))
+ && m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1
+ && o2 == t3.Size()
+ && o1-o2 == t2.Size()
+ && n == t3.Size() + t2.Size() + t1.Size()
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
+ && clobber(m2, m3, m4)
+ => (Store {t1} op1 d1 (Store {t2} op2 d2 (Store {t3} op3 d3 mem)))
+(Store {t1} op1:(OffPtr [o1] p1) d1
+ m2:(Store {t2} op2:(OffPtr [o2] p2) d2
+ m3:(Store {t3} op3:(OffPtr [o3] p3) d3
+ m4:(Store {t4} op4:(OffPtr [0] p4) d4
+ m5:(Move [n] p5 _ mem)))))
+ && m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1 && m5.Uses == 1
+ && o3 == t4.Size()
+ && o2-o3 == t3.Size()
+ && o1-o2 == t2.Size()
+ && n == t4.Size() + t3.Size() + t2.Size() + t1.Size()
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
+ && clobber(m2, m3, m4, m5)
+ => (Store {t1} op1 d1 (Store {t2} op2 d2 (Store {t3} op3 d3 (Store {t4} op4 d4 mem))))
+
+// Don't Zero variables that are immediately completely overwritten
+// before being accessed.
+(Move {t} [n] dst1 src1 zero:(Zero {t} [n] dst2 mem))
+ && zero.Uses == 1
+ && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n)
+ && clobber(zero)
+ => (Move {t} [n] dst1 src1 mem)
+(Move {t} [n] dst1 src1 vardef:(VarDef {x} zero:(Zero {t} [n] dst2 mem)))
+ && zero.Uses == 1 && vardef.Uses == 1
+ && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n)
+ && clobber(zero, vardef)
+ => (Move {t} [n] dst1 src1 (VarDef {x} mem))
+(Store {t1} op1:(OffPtr [o1] p1) d1
+ m2:(Store {t2} op2:(OffPtr [0] p2) d2
+ m3:(Zero [n] p3 mem)))
+ && m2.Uses == 1 && m3.Uses == 1
+ && o1 == t2.Size()
+ && n == t2.Size() + t1.Size()
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3)
+ && clobber(m2, m3)
+ => (Store {t1} op1 d1 (Store {t2} op2 d2 mem))
+(Store {t1} op1:(OffPtr [o1] p1) d1
+ m2:(Store {t2} op2:(OffPtr [o2] p2) d2
+ m3:(Store {t3} op3:(OffPtr [0] p3) d3
+ m4:(Zero [n] p4 mem))))
+ && m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1
+ && o2 == t3.Size()
+ && o1-o2 == t2.Size()
+ && n == t3.Size() + t2.Size() + t1.Size()
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
+ && clobber(m2, m3, m4)
+ => (Store {t1} op1 d1 (Store {t2} op2 d2 (Store {t3} op3 d3 mem)))
+(Store {t1} op1:(OffPtr [o1] p1) d1
+ m2:(Store {t2} op2:(OffPtr [o2] p2) d2
+ m3:(Store {t3} op3:(OffPtr [o3] p3) d3
+ m4:(Store {t4} op4:(OffPtr [0] p4) d4
+ m5:(Zero [n] p5 mem)))))
+ && m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1 && m5.Uses == 1
+ && o3 == t4.Size()
+ && o2-o3 == t3.Size()
+ && o1-o2 == t2.Size()
+ && n == t4.Size() + t3.Size() + t2.Size() + t1.Size()
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
+ && clobber(m2, m3, m4, m5)
+ => (Store {t1} op1 d1 (Store {t2} op2 d2 (Store {t3} op3 d3 (Store {t4} op4 d4 mem))))
+
+// Don't Move from memory if the values are likely to already be
+// in registers.
+(Move {t1} [n] dst p1
+ mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _)))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && o2 == t3.Size()
+ && n == t2.Size() + t3.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
+(Move {t1} [n] dst p1
+ mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+ (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && t4.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && registerizable(b, t4)
+ && o3 == t4.Size()
+ && o2-o3 == t3.Size()
+ && n == t2.Size() + t3.Size() + t4.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
+(Move {t1} [n] dst p1
+ mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+ (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3
+ (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _)))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && t4.Alignment() <= t1.Alignment()
+ && t5.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && registerizable(b, t4)
+ && registerizable(b, t5)
+ && o4 == t5.Size()
+ && o3-o4 == t4.Size()
+ && o2-o3 == t3.Size()
+ && n == t2.Size() + t3.Size() + t4.Size() + t5.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [o4] dst) d3
+ (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
+
+// Same thing but with VarDef in the middle.
+(Move {t1} [n] dst p1
+ mem:(VarDef
+ (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && o2 == t3.Size()
+ && n == t2.Size() + t3.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
+(Move {t1} [n] dst p1
+ mem:(VarDef
+ (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+ (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _)))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && t4.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && registerizable(b, t4)
+ && o3 == t4.Size()
+ && o2-o3 == t3.Size()
+ && n == t2.Size() + t3.Size() + t4.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
+(Move {t1} [n] dst p1
+ mem:(VarDef
+ (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+ (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3
+ (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _))))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && t4.Alignment() <= t1.Alignment()
+ && t5.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && registerizable(b, t4)
+ && registerizable(b, t5)
+ && o4 == t5.Size()
+ && o3-o4 == t4.Size()
+ && o2-o3 == t3.Size()
+ && n == t2.Size() + t3.Size() + t4.Size() + t5.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [o4] dst) d3
+ (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
+
+// Prefer to Zero and Store than to Move.
+(Move {t1} [n] dst p1
+ mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Zero {t3} [n] p3 _)))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && n >= o2 + t2.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Zero {t1} [n] dst mem))
+(Move {t1} [n] dst p1
+ mem:(Store {t2} (OffPtr <tt2> [o2] p2) d1
+ (Store {t3} (OffPtr <tt3> [o3] p3) d2
+ (Zero {t4} [n] p4 _))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && t4.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && n >= o2 + t2.Size()
+ && n >= o3 + t3.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Zero {t1} [n] dst mem)))
+(Move {t1} [n] dst p1
+ mem:(Store {t2} (OffPtr <tt2> [o2] p2) d1
+ (Store {t3} (OffPtr <tt3> [o3] p3) d2
+ (Store {t4} (OffPtr <tt4> [o4] p4) d3
+ (Zero {t5} [n] p5 _)))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && t4.Alignment() <= t1.Alignment()
+ && t5.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && registerizable(b, t4)
+ && n >= o2 + t2.Size()
+ && n >= o3 + t3.Size()
+ && n >= o4 + t4.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [o4] dst) d3
+ (Zero {t1} [n] dst mem))))
+(Move {t1} [n] dst p1
+ mem:(Store {t2} (OffPtr <tt2> [o2] p2) d1
+ (Store {t3} (OffPtr <tt3> [o3] p3) d2
+ (Store {t4} (OffPtr <tt4> [o4] p4) d3
+ (Store {t5} (OffPtr <tt5> [o5] p5) d4
+ (Zero {t6} [n] p6 _))))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && isSamePtr(p5, p6)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && t4.Alignment() <= t1.Alignment()
+ && t5.Alignment() <= t1.Alignment()
+ && t6.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && registerizable(b, t4)
+ && registerizable(b, t5)
+ && n >= o2 + t2.Size()
+ && n >= o3 + t3.Size()
+ && n >= o4 + t4.Size()
+ && n >= o5 + t5.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [o4] dst) d3
+ (Store {t5} (OffPtr <tt5> [o5] dst) d4
+ (Zero {t1} [n] dst mem)))))
+(Move {t1} [n] dst p1
+ mem:(VarDef
+ (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Zero {t3} [n] p3 _))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && n >= o2 + t2.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Zero {t1} [n] dst mem))
+(Move {t1} [n] dst p1
+ mem:(VarDef
+ (Store {t2} (OffPtr <tt2> [o2] p2) d1
+ (Store {t3} (OffPtr <tt3> [o3] p3) d2
+ (Zero {t4} [n] p4 _)))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && t4.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && n >= o2 + t2.Size()
+ && n >= o3 + t3.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Zero {t1} [n] dst mem)))
+(Move {t1} [n] dst p1
+ mem:(VarDef
+ (Store {t2} (OffPtr <tt2> [o2] p2) d1
+ (Store {t3} (OffPtr <tt3> [o3] p3) d2
+ (Store {t4} (OffPtr <tt4> [o4] p4) d3
+ (Zero {t5} [n] p5 _))))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && t4.Alignment() <= t1.Alignment()
+ && t5.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && registerizable(b, t4)
+ && n >= o2 + t2.Size()
+ && n >= o3 + t3.Size()
+ && n >= o4 + t4.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [o4] dst) d3
+ (Zero {t1} [n] dst mem))))
+(Move {t1} [n] dst p1
+ mem:(VarDef
+ (Store {t2} (OffPtr <tt2> [o2] p2) d1
+ (Store {t3} (OffPtr <tt3> [o3] p3) d2
+ (Store {t4} (OffPtr <tt4> [o4] p4) d3
+ (Store {t5} (OffPtr <tt5> [o5] p5) d4
+ (Zero {t6} [n] p6 _)))))))
+ && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && isSamePtr(p5, p6)
+ && t2.Alignment() <= t1.Alignment()
+ && t3.Alignment() <= t1.Alignment()
+ && t4.Alignment() <= t1.Alignment()
+ && t5.Alignment() <= t1.Alignment()
+ && t6.Alignment() <= t1.Alignment()
+ && registerizable(b, t2)
+ && registerizable(b, t3)
+ && registerizable(b, t4)
+ && registerizable(b, t5)
+ && n >= o2 + t2.Size()
+ && n >= o3 + t3.Size()
+ && n >= o4 + t4.Size()
+ && n >= o5 + t5.Size()
+ => (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [o4] dst) d3
+ (Store {t5} (OffPtr <tt5> [o5] dst) d4
+ (Zero {t1} [n] dst mem)))))
+
+// TODO this does not fire before call expansion; is that acceptable?
+(StaticCall {sym} x) && needRaceCleanup(sym, v) => x
+
+// Collapse moving A -> B -> C into just A -> C.
+// Later passes (deadstore, elim unread auto) will remove the A -> B move, if possible.
+// This happens most commonly when B is an autotmp inserted earlier
+// during compilation to ensure correctness.
+// Take care that overlapping moves are preserved.
+// Restrict this optimization to the stack, to avoid duplicating loads from the heap;
+// see CL 145208 for discussion.
+(Move {t1} [s] dst tmp1 midmem:(Move {t2} [s] tmp2 src _))
+ && t1.Compare(t2) == types.CMPeq
+ && isSamePtr(tmp1, tmp2)
+ && isStackPtr(src) && !isVolatile(src)
+ && disjoint(src, s, tmp2, s)
+ && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))
+ => (Move {t1} [s] dst src midmem)
+
+// Same, but for large types that require VarDefs.
+(Move {t1} [s] dst tmp1 midmem:(VarDef (Move {t2} [s] tmp2 src _)))
+ && t1.Compare(t2) == types.CMPeq
+ && isSamePtr(tmp1, tmp2)
+ && isStackPtr(src) && !isVolatile(src)
+ && disjoint(src, s, tmp2, s)
+ && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))
+ => (Move {t1} [s] dst src midmem)
+
+// Don't zero the same bits twice.
+(Zero {t} [s] dst1 zero:(Zero {t} [s] dst2 _)) && isSamePtr(dst1, dst2) => zero
+(Zero {t} [s] dst1 vardef:(VarDef (Zero {t} [s] dst2 _))) && isSamePtr(dst1, dst2) => vardef
+
+// Elide self-moves. This only happens rarely (e.g test/fixedbugs/bug277.go).
+// However, this rule is needed to prevent the previous rule from looping forever in such cases.
+(Move dst src mem) && isSamePtr(dst, src) => mem
diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go
new file mode 100644
index 0000000..0a7d5dd
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/genericOps.go
@@ -0,0 +1,620 @@
+// 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.
+
+// +build ignore
+
+package main
+
+// Generic opcodes typically specify a width. The inputs and outputs
+// of that op are the given number of bits wide. There is no notion of
+// "sign", so Add32 can be used both for signed and unsigned 32-bit
+// addition.
+
+// Signed/unsigned is explicit with the extension ops
+// (SignExt*/ZeroExt*) and implicit as the arg to some opcodes
+// (e.g. the second argument to shifts is unsigned). If not mentioned,
+// all args take signed inputs, or don't care whether their inputs
+// are signed or unsigned.
+
+var genericOps = []opData{
+ // 2-input arithmetic
+ // Types must be consistent with Go typing. Add, for example, must take two values
+ // of the same type and produces that same type.
+ {name: "Add8", argLength: 2, commutative: true}, // arg0 + arg1
+ {name: "Add16", argLength: 2, commutative: true},
+ {name: "Add32", argLength: 2, commutative: true},
+ {name: "Add64", argLength: 2, commutative: true},
+ {name: "AddPtr", argLength: 2}, // For address calculations. arg0 is a pointer and arg1 is an int.
+ {name: "Add32F", argLength: 2, commutative: true},
+ {name: "Add64F", argLength: 2, commutative: true},
+
+ {name: "Sub8", argLength: 2}, // arg0 - arg1
+ {name: "Sub16", argLength: 2},
+ {name: "Sub32", argLength: 2},
+ {name: "Sub64", argLength: 2},
+ {name: "SubPtr", argLength: 2},
+ {name: "Sub32F", argLength: 2},
+ {name: "Sub64F", argLength: 2},
+
+ {name: "Mul8", argLength: 2, commutative: true}, // arg0 * arg1
+ {name: "Mul16", argLength: 2, commutative: true},
+ {name: "Mul32", argLength: 2, commutative: true},
+ {name: "Mul64", argLength: 2, commutative: true},
+ {name: "Mul32F", argLength: 2, commutative: true},
+ {name: "Mul64F", argLength: 2, commutative: true},
+
+ {name: "Div32F", argLength: 2}, // arg0 / arg1
+ {name: "Div64F", argLength: 2},
+
+ {name: "Hmul32", argLength: 2, commutative: true},
+ {name: "Hmul32u", argLength: 2, commutative: true},
+ {name: "Hmul64", argLength: 2, commutative: true},
+ {name: "Hmul64u", argLength: 2, commutative: true},
+
+ {name: "Mul32uhilo", argLength: 2, typ: "(UInt32,UInt32)", commutative: true}, // arg0 * arg1, returns (hi, lo)
+ {name: "Mul64uhilo", argLength: 2, typ: "(UInt64,UInt64)", commutative: true}, // arg0 * arg1, returns (hi, lo)
+
+ {name: "Mul32uover", argLength: 2, typ: "(UInt32,Bool)", commutative: true}, // Let x = arg0*arg1 (full 32x32-> 64 unsigned multiply), returns (uint32(x), (uint32(x) != x))
+ {name: "Mul64uover", argLength: 2, typ: "(UInt64,Bool)", commutative: true}, // Let x = arg0*arg1 (full 64x64->128 unsigned multiply), returns (uint64(x), (uint64(x) != x))
+
+ // Weird special instructions for use in the strength reduction of divides.
+ // These ops compute unsigned (arg0 + arg1) / 2, correct to all
+ // 32/64 bits, even when the intermediate result of the add has 33/65 bits.
+ // These ops can assume arg0 >= arg1.
+ // Note: these ops aren't commutative!
+ {name: "Avg32u", argLength: 2, typ: "UInt32"}, // 32-bit platforms only
+ {name: "Avg64u", argLength: 2, typ: "UInt64"}, // 64-bit platforms only
+
+ // For Div16, Div32 and Div64, AuxInt non-zero means that the divisor has been proved to be not -1
+ // or that the dividend is not the most negative value.
+ {name: "Div8", argLength: 2}, // arg0 / arg1, signed
+ {name: "Div8u", argLength: 2}, // arg0 / arg1, unsigned
+ {name: "Div16", argLength: 2, aux: "Bool"},
+ {name: "Div16u", argLength: 2},
+ {name: "Div32", argLength: 2, aux: "Bool"},
+ {name: "Div32u", argLength: 2},
+ {name: "Div64", argLength: 2, aux: "Bool"},
+ {name: "Div64u", argLength: 2},
+ {name: "Div128u", argLength: 3}, // arg0:arg1 / arg2 (128-bit divided by 64-bit), returns (q, r)
+
+ // For Mod16, Mod32 and Mod64, AuxInt non-zero means that the divisor has been proved to be not -1.
+ {name: "Mod8", argLength: 2}, // arg0 % arg1, signed
+ {name: "Mod8u", argLength: 2}, // arg0 % arg1, unsigned
+ {name: "Mod16", argLength: 2, aux: "Bool"},
+ {name: "Mod16u", argLength: 2},
+ {name: "Mod32", argLength: 2, aux: "Bool"},
+ {name: "Mod32u", argLength: 2},
+ {name: "Mod64", argLength: 2, aux: "Bool"},
+ {name: "Mod64u", argLength: 2},
+
+ {name: "And8", argLength: 2, commutative: true}, // arg0 & arg1
+ {name: "And16", argLength: 2, commutative: true},
+ {name: "And32", argLength: 2, commutative: true},
+ {name: "And64", argLength: 2, commutative: true},
+
+ {name: "Or8", argLength: 2, commutative: true}, // arg0 | arg1
+ {name: "Or16", argLength: 2, commutative: true},
+ {name: "Or32", argLength: 2, commutative: true},
+ {name: "Or64", argLength: 2, commutative: true},
+
+ {name: "Xor8", argLength: 2, commutative: true}, // arg0 ^ arg1
+ {name: "Xor16", argLength: 2, commutative: true},
+ {name: "Xor32", argLength: 2, commutative: true},
+ {name: "Xor64", argLength: 2, commutative: true},
+
+ // For shifts, AxB means the shifted value has A bits and the shift amount has B bits.
+ // Shift amounts are considered unsigned.
+ // If arg1 is known to be nonnegative and less than the number of bits in arg0,
+ // then auxInt may be set to 1.
+ // This enables better code generation on some platforms.
+ {name: "Lsh8x8", argLength: 2, aux: "Bool"}, // arg0 << arg1
+ {name: "Lsh8x16", argLength: 2, aux: "Bool"},
+ {name: "Lsh8x32", argLength: 2, aux: "Bool"},
+ {name: "Lsh8x64", argLength: 2, aux: "Bool"},
+ {name: "Lsh16x8", argLength: 2, aux: "Bool"},
+ {name: "Lsh16x16", argLength: 2, aux: "Bool"},
+ {name: "Lsh16x32", argLength: 2, aux: "Bool"},
+ {name: "Lsh16x64", argLength: 2, aux: "Bool"},
+ {name: "Lsh32x8", argLength: 2, aux: "Bool"},
+ {name: "Lsh32x16", argLength: 2, aux: "Bool"},
+ {name: "Lsh32x32", argLength: 2, aux: "Bool"},
+ {name: "Lsh32x64", argLength: 2, aux: "Bool"},
+ {name: "Lsh64x8", argLength: 2, aux: "Bool"},
+ {name: "Lsh64x16", argLength: 2, aux: "Bool"},
+ {name: "Lsh64x32", argLength: 2, aux: "Bool"},
+ {name: "Lsh64x64", argLength: 2, aux: "Bool"},
+
+ {name: "Rsh8x8", argLength: 2, aux: "Bool"}, // arg0 >> arg1, signed
+ {name: "Rsh8x16", argLength: 2, aux: "Bool"},
+ {name: "Rsh8x32", argLength: 2, aux: "Bool"},
+ {name: "Rsh8x64", argLength: 2, aux: "Bool"},
+ {name: "Rsh16x8", argLength: 2, aux: "Bool"},
+ {name: "Rsh16x16", argLength: 2, aux: "Bool"},
+ {name: "Rsh16x32", argLength: 2, aux: "Bool"},
+ {name: "Rsh16x64", argLength: 2, aux: "Bool"},
+ {name: "Rsh32x8", argLength: 2, aux: "Bool"},
+ {name: "Rsh32x16", argLength: 2, aux: "Bool"},
+ {name: "Rsh32x32", argLength: 2, aux: "Bool"},
+ {name: "Rsh32x64", argLength: 2, aux: "Bool"},
+ {name: "Rsh64x8", argLength: 2, aux: "Bool"},
+ {name: "Rsh64x16", argLength: 2, aux: "Bool"},
+ {name: "Rsh64x32", argLength: 2, aux: "Bool"},
+ {name: "Rsh64x64", argLength: 2, aux: "Bool"},
+
+ {name: "Rsh8Ux8", argLength: 2, aux: "Bool"}, // arg0 >> arg1, unsigned
+ {name: "Rsh8Ux16", argLength: 2, aux: "Bool"},
+ {name: "Rsh8Ux32", argLength: 2, aux: "Bool"},
+ {name: "Rsh8Ux64", argLength: 2, aux: "Bool"},
+ {name: "Rsh16Ux8", argLength: 2, aux: "Bool"},
+ {name: "Rsh16Ux16", argLength: 2, aux: "Bool"},
+ {name: "Rsh16Ux32", argLength: 2, aux: "Bool"},
+ {name: "Rsh16Ux64", argLength: 2, aux: "Bool"},
+ {name: "Rsh32Ux8", argLength: 2, aux: "Bool"},
+ {name: "Rsh32Ux16", argLength: 2, aux: "Bool"},
+ {name: "Rsh32Ux32", argLength: 2, aux: "Bool"},
+ {name: "Rsh32Ux64", argLength: 2, aux: "Bool"},
+ {name: "Rsh64Ux8", argLength: 2, aux: "Bool"},
+ {name: "Rsh64Ux16", argLength: 2, aux: "Bool"},
+ {name: "Rsh64Ux32", argLength: 2, aux: "Bool"},
+ {name: "Rsh64Ux64", argLength: 2, aux: "Bool"},
+
+ // 2-input comparisons
+ {name: "Eq8", argLength: 2, commutative: true, typ: "Bool"}, // arg0 == arg1
+ {name: "Eq16", argLength: 2, commutative: true, typ: "Bool"},
+ {name: "Eq32", argLength: 2, commutative: true, typ: "Bool"},
+ {name: "Eq64", argLength: 2, commutative: true, typ: "Bool"},
+ {name: "EqPtr", argLength: 2, commutative: true, typ: "Bool"},
+ {name: "EqInter", argLength: 2, typ: "Bool"}, // arg0 or arg1 is nil; other cases handled by frontend
+ {name: "EqSlice", argLength: 2, typ: "Bool"}, // arg0 or arg1 is nil; other cases handled by frontend
+ {name: "Eq32F", argLength: 2, commutative: true, typ: "Bool"},
+ {name: "Eq64F", argLength: 2, commutative: true, typ: "Bool"},
+
+ {name: "Neq8", argLength: 2, commutative: true, typ: "Bool"}, // arg0 != arg1
+ {name: "Neq16", argLength: 2, commutative: true, typ: "Bool"},
+ {name: "Neq32", argLength: 2, commutative: true, typ: "Bool"},
+ {name: "Neq64", argLength: 2, commutative: true, typ: "Bool"},
+ {name: "NeqPtr", argLength: 2, commutative: true, typ: "Bool"},
+ {name: "NeqInter", argLength: 2, typ: "Bool"}, // arg0 or arg1 is nil; other cases handled by frontend
+ {name: "NeqSlice", argLength: 2, typ: "Bool"}, // arg0 or arg1 is nil; other cases handled by frontend
+ {name: "Neq32F", argLength: 2, commutative: true, typ: "Bool"},
+ {name: "Neq64F", argLength: 2, commutative: true, typ: "Bool"},
+
+ {name: "Less8", argLength: 2, typ: "Bool"}, // arg0 < arg1, signed
+ {name: "Less8U", argLength: 2, typ: "Bool"}, // arg0 < arg1, unsigned
+ {name: "Less16", argLength: 2, typ: "Bool"},
+ {name: "Less16U", argLength: 2, typ: "Bool"},
+ {name: "Less32", argLength: 2, typ: "Bool"},
+ {name: "Less32U", argLength: 2, typ: "Bool"},
+ {name: "Less64", argLength: 2, typ: "Bool"},
+ {name: "Less64U", argLength: 2, typ: "Bool"},
+ {name: "Less32F", argLength: 2, typ: "Bool"},
+ {name: "Less64F", argLength: 2, typ: "Bool"},
+
+ {name: "Leq8", argLength: 2, typ: "Bool"}, // arg0 <= arg1, signed
+ {name: "Leq8U", argLength: 2, typ: "Bool"}, // arg0 <= arg1, unsigned
+ {name: "Leq16", argLength: 2, typ: "Bool"},
+ {name: "Leq16U", argLength: 2, typ: "Bool"},
+ {name: "Leq32", argLength: 2, typ: "Bool"},
+ {name: "Leq32U", argLength: 2, typ: "Bool"},
+ {name: "Leq64", argLength: 2, typ: "Bool"},
+ {name: "Leq64U", argLength: 2, typ: "Bool"},
+ {name: "Leq32F", argLength: 2, typ: "Bool"},
+ {name: "Leq64F", argLength: 2, typ: "Bool"},
+
+ // the type of a CondSelect is the same as the type of its first
+ // two arguments, which should be register-width scalars; the third
+ // argument should be a boolean
+ {name: "CondSelect", argLength: 3}, // arg2 ? arg0 : arg1
+
+ // boolean ops
+ {name: "AndB", argLength: 2, commutative: true, typ: "Bool"}, // arg0 && arg1 (not shortcircuited)
+ {name: "OrB", argLength: 2, commutative: true, typ: "Bool"}, // arg0 || arg1 (not shortcircuited)
+ {name: "EqB", argLength: 2, commutative: true, typ: "Bool"}, // arg0 == arg1
+ {name: "NeqB", argLength: 2, commutative: true, typ: "Bool"}, // arg0 != arg1
+ {name: "Not", argLength: 1, typ: "Bool"}, // !arg0, boolean
+
+ // 1-input ops
+ {name: "Neg8", argLength: 1}, // -arg0
+ {name: "Neg16", argLength: 1},
+ {name: "Neg32", argLength: 1},
+ {name: "Neg64", argLength: 1},
+ {name: "Neg32F", argLength: 1},
+ {name: "Neg64F", argLength: 1},
+
+ {name: "Com8", argLength: 1}, // ^arg0
+ {name: "Com16", argLength: 1},
+ {name: "Com32", argLength: 1},
+ {name: "Com64", argLength: 1},
+
+ {name: "Ctz8", argLength: 1}, // Count trailing (low order) zeroes (returns 0-8)
+ {name: "Ctz16", argLength: 1}, // Count trailing (low order) zeroes (returns 0-16)
+ {name: "Ctz32", argLength: 1}, // Count trailing (low order) zeroes (returns 0-32)
+ {name: "Ctz64", argLength: 1}, // Count trailing (low order) zeroes (returns 0-64)
+ {name: "Ctz8NonZero", argLength: 1}, // same as above, but arg[0] known to be non-zero, returns 0-7
+ {name: "Ctz16NonZero", argLength: 1}, // same as above, but arg[0] known to be non-zero, returns 0-15
+ {name: "Ctz32NonZero", argLength: 1}, // same as above, but arg[0] known to be non-zero, returns 0-31
+ {name: "Ctz64NonZero", argLength: 1}, // same as above, but arg[0] known to be non-zero, returns 0-63
+ {name: "BitLen8", argLength: 1}, // Number of bits in arg[0] (returns 0-8)
+ {name: "BitLen16", argLength: 1}, // Number of bits in arg[0] (returns 0-16)
+ {name: "BitLen32", argLength: 1}, // Number of bits in arg[0] (returns 0-32)
+ {name: "BitLen64", argLength: 1}, // Number of bits in arg[0] (returns 0-64)
+
+ {name: "Bswap32", argLength: 1}, // Swap bytes
+ {name: "Bswap64", argLength: 1}, // Swap bytes
+
+ {name: "BitRev8", argLength: 1}, // Reverse the bits in arg[0]
+ {name: "BitRev16", argLength: 1}, // Reverse the bits in arg[0]
+ {name: "BitRev32", argLength: 1}, // Reverse the bits in arg[0]
+ {name: "BitRev64", argLength: 1}, // Reverse the bits in arg[0]
+
+ {name: "PopCount8", argLength: 1}, // Count bits in arg[0]
+ {name: "PopCount16", argLength: 1}, // Count bits in arg[0]
+ {name: "PopCount32", argLength: 1}, // Count bits in arg[0]
+ {name: "PopCount64", argLength: 1}, // Count bits in arg[0]
+ {name: "RotateLeft8", argLength: 2}, // Rotate bits in arg[0] left by arg[1]
+ {name: "RotateLeft16", argLength: 2}, // Rotate bits in arg[0] left by arg[1]
+ {name: "RotateLeft32", argLength: 2}, // Rotate bits in arg[0] left by arg[1]
+ {name: "RotateLeft64", argLength: 2}, // Rotate bits in arg[0] left by arg[1]
+
+ // Square root, float64 only.
+ // Special cases:
+ // +∞ → +∞
+ // ±0 → ±0 (sign preserved)
+ // x<0 → NaN
+ // NaN → NaN
+ {name: "Sqrt", argLength: 1}, // √arg0
+
+ // Round to integer, float64 only.
+ // Special cases:
+ // ±∞ → ±∞ (sign preserved)
+ // ±0 → ±0 (sign preserved)
+ // NaN → NaN
+ {name: "Floor", argLength: 1}, // round arg0 toward -∞
+ {name: "Ceil", argLength: 1}, // round arg0 toward +∞
+ {name: "Trunc", argLength: 1}, // round arg0 toward 0
+ {name: "Round", argLength: 1}, // round arg0 to nearest, ties away from 0
+ {name: "RoundToEven", argLength: 1}, // round arg0 to nearest, ties to even
+
+ // Modify the sign bit
+ {name: "Abs", argLength: 1}, // absolute value arg0
+ {name: "Copysign", argLength: 2}, // copy sign from arg0 to arg1
+
+ // 3-input opcode.
+ // Fused-multiply-add, float64 only.
+ // When a*b+c is exactly zero (before rounding), then the result is +0 or -0.
+ // The 0's sign is determined according to the standard rules for the
+ // addition (-0 if both a*b and c are -0, +0 otherwise).
+ //
+ // Otherwise, when a*b+c rounds to zero, then the resulting 0's sign is
+ // determined by the sign of the exact result a*b+c.
+ // See section 6.3 in ieee754.
+ //
+ // When the multiply is an infinity times a zero, the result is NaN.
+ // See section 7.2 in ieee754.
+ {name: "FMA", argLength: 3}, // compute (a*b)+c without intermediate rounding
+
+ // Data movement. Max argument length for Phi is indefinite.
+ {name: "Phi", argLength: -1, zeroWidth: true}, // select an argument based on which predecessor block we came from
+ {name: "Copy", argLength: 1}, // output = arg0
+ // Convert converts between pointers and integers.
+ // We have a special op for this so as to not confuse GC
+ // (particularly stack maps). It takes a memory arg so it
+ // gets correctly ordered with respect to GC safepoints.
+ // It gets compiled to nothing, so its result must in the same
+ // register as its argument. regalloc knows it can use any
+ // allocatable integer register for OpConvert.
+ // arg0=ptr/int arg1=mem, output=int/ptr
+ {name: "Convert", argLength: 2, zeroWidth: true, resultInArg0: true},
+
+ // constants. Constant values are stored in the aux or
+ // auxint fields.
+ {name: "ConstBool", aux: "Bool"}, // auxint is 0 for false and 1 for true
+ {name: "ConstString", aux: "String"}, // value is aux.(string)
+ {name: "ConstNil", typ: "BytePtr"}, // nil pointer
+ {name: "Const8", aux: "Int8"}, // auxint is sign-extended 8 bits
+ {name: "Const16", aux: "Int16"}, // auxint is sign-extended 16 bits
+ {name: "Const32", aux: "Int32"}, // auxint is sign-extended 32 bits
+ // Note: ConstX are sign-extended even when the type of the value is unsigned.
+ // For instance, uint8(0xaa) is stored as auxint=0xffffffffffffffaa.
+ {name: "Const64", aux: "Int64"}, // value is auxint
+ // Note: for both Const32F and Const64F, we disallow encoding NaNs.
+ // Signaling NaNs are tricky because if you do anything with them, they become quiet.
+ // Particularly, converting a 32 bit sNaN to 64 bit and back converts it to a qNaN.
+ // See issue 36399 and 36400.
+ // Encodings of +inf, -inf, and -0 are fine.
+ {name: "Const32F", aux: "Float32"}, // value is math.Float64frombits(uint64(auxint)) and is exactly representable as float 32
+ {name: "Const64F", aux: "Float64"}, // value is math.Float64frombits(uint64(auxint))
+ {name: "ConstInterface"}, // nil interface
+ {name: "ConstSlice"}, // nil slice
+
+ // Constant-like things
+ {name: "InitMem", zeroWidth: true}, // memory input to the function.
+ {name: "Arg", aux: "SymOff", symEffect: "Read", zeroWidth: true}, // argument to the function. aux=GCNode of arg, off = offset in that arg.
+
+ // The address of a variable. arg0 is the base pointer.
+ // If the variable is a global, the base pointer will be SB and
+ // the Aux field will be a *obj.LSym.
+ // If the variable is a local, the base pointer will be SP and
+ // the Aux field will be a *gc.Node.
+ {name: "Addr", argLength: 1, aux: "Sym", symEffect: "Addr"}, // Address of a variable. Arg0=SB. Aux identifies the variable.
+ {name: "LocalAddr", argLength: 2, aux: "Sym", symEffect: "Addr"}, // Address of a variable. Arg0=SP. Arg1=mem. Aux identifies the variable.
+
+ {name: "SP", zeroWidth: true}, // stack pointer
+ {name: "SB", typ: "Uintptr", zeroWidth: true}, // static base pointer (a.k.a. globals pointer)
+ {name: "Invalid"}, // unused value
+
+ // Memory operations
+ {name: "Load", argLength: 2}, // Load from arg0. arg1=memory
+ {name: "Dereference", argLength: 2}, // Load from arg0. arg1=memory. Helper op for arg/result passing, result is an otherwise not-SSA-able "value".
+ {name: "Store", argLength: 3, typ: "Mem", aux: "Typ"}, // Store arg1 to arg0. arg2=memory, aux=type. Returns memory.
+ // The source and destination of Move may overlap in some cases. See e.g.
+ // memmove inlining in generic.rules. When inlineablememmovesize (in ../rewrite.go)
+ // returns true, we must do all loads before all stores, when lowering Move.
+ // The type of Move is used for the write barrier pass to insert write barriers
+ // and for alignment on some architectures.
+ // For pointerless types, it is possible for the type to be inaccurate.
+ // For type alignment and pointer information, use the type in Aux;
+ // for type size, use the size in AuxInt.
+ // The "inline runtime.memmove" rewrite rule generates Moves with inaccurate types,
+ // such as type byte instead of the more accurate type [8]byte.
+ {name: "Move", argLength: 3, typ: "Mem", aux: "TypSize"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size, aux=type. Returns memory.
+ {name: "Zero", argLength: 2, typ: "Mem", aux: "TypSize"}, // arg0=destptr, arg1=mem, auxint=size, aux=type. Returns memory.
+
+ // Memory operations with write barriers.
+ // Expand to runtime calls. Write barrier will be removed if write on stack.
+ {name: "StoreWB", argLength: 3, typ: "Mem", aux: "Typ"}, // Store arg1 to arg0. arg2=memory, aux=type. Returns memory.
+ {name: "MoveWB", argLength: 3, typ: "Mem", aux: "TypSize"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size, aux=type. Returns memory.
+ {name: "ZeroWB", argLength: 2, typ: "Mem", aux: "TypSize"}, // arg0=destptr, arg1=mem, auxint=size, aux=type. Returns memory.
+
+ // WB invokes runtime.gcWriteBarrier. This is not a normal
+ // call: it takes arguments in registers, doesn't clobber
+ // general-purpose registers (the exact clobber set is
+ // arch-dependent), and is not a safe-point.
+ {name: "WB", argLength: 3, typ: "Mem", aux: "Sym", symEffect: "None"}, // arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
+
+ {name: "HasCPUFeature", argLength: 0, typ: "bool", aux: "Sym", symEffect: "None"}, // aux=place that this feature flag can be loaded from
+
+ // PanicBounds and PanicExtend generate a runtime panic.
+ // Their arguments provide index values to use in panic messages.
+ // Both PanicBounds and PanicExtend have an AuxInt value from the BoundsKind type (in ../op.go).
+ // PanicBounds' index is int sized.
+ // PanicExtend's index is int64 sized. (PanicExtend is only used on 32-bit archs.)
+ {name: "PanicBounds", argLength: 3, aux: "Int64", typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory.
+ {name: "PanicExtend", argLength: 4, aux: "Int64", typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory.
+
+ // Function calls. Arguments to the call have already been written to the stack.
+ // Return values appear on the stack. The method receiver, if any, is treated
+ // as a phantom first argument.
+ // TODO(josharian): ClosureCall and InterCall should have Int32 aux
+ // to match StaticCall's 32 bit arg size limit.
+ // TODO(drchase,josharian): could the arg size limit be bundled into the rules for CallOff?
+ {name: "ClosureCall", argLength: 3, aux: "CallOff", call: true}, // arg0=code pointer, arg1=context ptr, arg2=memory. auxint=arg size. Returns memory.
+ {name: "StaticCall", argLength: 1, aux: "CallOff", call: true}, // call function aux.(*obj.LSym), arg0=memory. auxint=arg size. Returns memory.
+ {name: "InterCall", argLength: 2, aux: "CallOff", call: true}, // interface call. arg0=code pointer, arg1=memory, auxint=arg size. Returns memory.
+ {name: "ClosureLECall", argLength: -1, aux: "CallOff", call: true}, // late-expanded closure call. arg0=code pointer, arg1=context ptr, arg2..argN-1 are inputs, argN is mem. auxint = arg size. Result is tuple of result(s), plus mem.
+ {name: "StaticLECall", argLength: -1, aux: "CallOff", call: true}, // late-expanded static call function aux.(*ssa.AuxCall.Fn). arg0..argN-1 are inputs, argN is mem. auxint = arg size. Result is tuple of result(s), plus mem.
+ {name: "InterLECall", argLength: -1, aux: "CallOff", call: true}, // late-expanded interface call. arg0=code pointer, arg1..argN-1 are inputs, argN is mem. auxint = arg size. Result is tuple of result(s), plus mem.
+
+ // Conversions: signed extensions, zero (unsigned) extensions, truncations
+ {name: "SignExt8to16", argLength: 1, typ: "Int16"},
+ {name: "SignExt8to32", argLength: 1, typ: "Int32"},
+ {name: "SignExt8to64", argLength: 1, typ: "Int64"},
+ {name: "SignExt16to32", argLength: 1, typ: "Int32"},
+ {name: "SignExt16to64", argLength: 1, typ: "Int64"},
+ {name: "SignExt32to64", argLength: 1, typ: "Int64"},
+ {name: "ZeroExt8to16", argLength: 1, typ: "UInt16"},
+ {name: "ZeroExt8to32", argLength: 1, typ: "UInt32"},
+ {name: "ZeroExt8to64", argLength: 1, typ: "UInt64"},
+ {name: "ZeroExt16to32", argLength: 1, typ: "UInt32"},
+ {name: "ZeroExt16to64", argLength: 1, typ: "UInt64"},
+ {name: "ZeroExt32to64", argLength: 1, typ: "UInt64"},
+ {name: "Trunc16to8", argLength: 1},
+ {name: "Trunc32to8", argLength: 1},
+ {name: "Trunc32to16", argLength: 1},
+ {name: "Trunc64to8", argLength: 1},
+ {name: "Trunc64to16", argLength: 1},
+ {name: "Trunc64to32", argLength: 1},
+
+ {name: "Cvt32to32F", argLength: 1},
+ {name: "Cvt32to64F", argLength: 1},
+ {name: "Cvt64to32F", argLength: 1},
+ {name: "Cvt64to64F", argLength: 1},
+ {name: "Cvt32Fto32", argLength: 1},
+ {name: "Cvt32Fto64", argLength: 1},
+ {name: "Cvt64Fto32", argLength: 1},
+ {name: "Cvt64Fto64", argLength: 1},
+ {name: "Cvt32Fto64F", argLength: 1},
+ {name: "Cvt64Fto32F", argLength: 1},
+ {name: "CvtBoolToUint8", argLength: 1},
+
+ // Force rounding to precision of type.
+ {name: "Round32F", argLength: 1},
+ {name: "Round64F", argLength: 1},
+
+ // Automatically inserted safety checks
+ {name: "IsNonNil", argLength: 1, typ: "Bool"}, // arg0 != nil
+ {name: "IsInBounds", argLength: 2, typ: "Bool"}, // 0 <= arg0 < arg1. arg1 is guaranteed >= 0.
+ {name: "IsSliceInBounds", argLength: 2, typ: "Bool"}, // 0 <= arg0 <= arg1. arg1 is guaranteed >= 0.
+ {name: "NilCheck", argLength: 2, typ: "Void"}, // arg0=ptr, arg1=mem. Panics if arg0 is nil. Returns void.
+
+ // Pseudo-ops
+ {name: "GetG", argLength: 1, zeroWidth: true}, // runtime.getg() (read g pointer). arg0=mem
+ {name: "GetClosurePtr"}, // get closure pointer from dedicated register
+ {name: "GetCallerPC"}, // for getcallerpc intrinsic
+ {name: "GetCallerSP"}, // for getcallersp intrinsic
+
+ // Indexing operations
+ {name: "PtrIndex", argLength: 2}, // arg0=ptr, arg1=index. Computes ptr+sizeof(*v.type)*index, where index is extended to ptrwidth type
+ {name: "OffPtr", argLength: 1, aux: "Int64"}, // arg0 + auxint (arg0 and result are pointers)
+
+ // Slices
+ {name: "SliceMake", argLength: 3}, // arg0=ptr, arg1=len, arg2=cap
+ {name: "SlicePtr", argLength: 1, typ: "BytePtr"}, // ptr(arg0)
+ {name: "SliceLen", argLength: 1}, // len(arg0)
+ {name: "SliceCap", argLength: 1}, // cap(arg0)
+
+ // Complex (part/whole)
+ {name: "ComplexMake", argLength: 2}, // arg0=real, arg1=imag
+ {name: "ComplexReal", argLength: 1}, // real(arg0)
+ {name: "ComplexImag", argLength: 1}, // imag(arg0)
+
+ // Strings
+ {name: "StringMake", argLength: 2}, // arg0=ptr, arg1=len
+ {name: "StringPtr", argLength: 1, typ: "BytePtr"}, // ptr(arg0)
+ {name: "StringLen", argLength: 1, typ: "Int"}, // len(arg0)
+
+ // Interfaces
+ {name: "IMake", argLength: 2}, // arg0=itab, arg1=data
+ {name: "ITab", argLength: 1, typ: "Uintptr"}, // arg0=interface, returns itable field
+ {name: "IData", argLength: 1}, // arg0=interface, returns data field
+
+ // Structs
+ {name: "StructMake0"}, // Returns struct with 0 fields.
+ {name: "StructMake1", argLength: 1}, // arg0=field0. Returns struct.
+ {name: "StructMake2", argLength: 2}, // arg0,arg1=field0,field1. Returns struct.
+ {name: "StructMake3", argLength: 3}, // arg0..2=field0..2. Returns struct.
+ {name: "StructMake4", argLength: 4}, // arg0..3=field0..3. Returns struct.
+ {name: "StructSelect", argLength: 1, aux: "Int64"}, // arg0=struct, auxint=field index. Returns the auxint'th field.
+
+ // Arrays
+ {name: "ArrayMake0"}, // Returns array with 0 elements
+ {name: "ArrayMake1", argLength: 1}, // Returns array with 1 element
+ {name: "ArraySelect", argLength: 1, aux: "Int64"}, // arg0=array, auxint=index. Returns a[i].
+
+ // Spill&restore ops for the register allocator. These are
+ // semantically identical to OpCopy; they do not take/return
+ // stores like regular memory ops do. We can get away without memory
+ // args because we know there is no aliasing of spill slots on the stack.
+ {name: "StoreReg", argLength: 1},
+ {name: "LoadReg", argLength: 1},
+
+ // Used during ssa construction. Like Copy, but the arg has not been specified yet.
+ {name: "FwdRef", aux: "Sym", symEffect: "None"},
+
+ // Unknown value. Used for Values whose values don't matter because they are dead code.
+ {name: "Unknown"},
+
+ {name: "VarDef", argLength: 1, aux: "Sym", typ: "Mem", symEffect: "None", zeroWidth: true}, // aux is a *gc.Node of a variable that is about to be initialized. arg0=mem, returns mem
+ {name: "VarKill", argLength: 1, aux: "Sym", symEffect: "None"}, // aux is a *gc.Node of a variable that is known to be dead. arg0=mem, returns mem
+ // TODO: what's the difference between VarLive and KeepAlive?
+ {name: "VarLive", argLength: 1, aux: "Sym", symEffect: "Read", zeroWidth: true}, // aux is a *gc.Node of a variable that must be kept live. arg0=mem, returns mem
+ {name: "KeepAlive", argLength: 2, typ: "Mem", zeroWidth: true}, // arg[0] is a value that must be kept alive until this mark. arg[1]=mem, returns mem
+
+ // InlMark marks the start of an inlined function body. Its AuxInt field
+ // distinguishes which entry in the local inline tree it is marking.
+ {name: "InlMark", argLength: 1, aux: "Int32", typ: "Void"}, // arg[0]=mem, returns void.
+
+ // Ops for breaking 64-bit operations on 32-bit architectures
+ {name: "Int64Make", argLength: 2, typ: "UInt64"}, // arg0=hi, arg1=lo
+ {name: "Int64Hi", argLength: 1, typ: "UInt32"}, // high 32-bit of arg0
+ {name: "Int64Lo", argLength: 1, typ: "UInt32"}, // low 32-bit of arg0
+
+ {name: "Add32carry", argLength: 2, commutative: true, typ: "(UInt32,Flags)"}, // arg0 + arg1, returns (value, carry)
+ {name: "Add32withcarry", argLength: 3, commutative: true}, // arg0 + arg1 + arg2, arg2=carry (0 or 1)
+
+ {name: "Sub32carry", argLength: 2, typ: "(UInt32,Flags)"}, // arg0 - arg1, returns (value, carry)
+ {name: "Sub32withcarry", argLength: 3}, // arg0 - arg1 - arg2, arg2=carry (0 or 1)
+
+ {name: "Add64carry", argLength: 3, commutative: true, typ: "(UInt64,UInt64)"}, // arg0 + arg1 + arg2, arg2 must be 0 or 1. returns (value, value>>64)
+ {name: "Sub64borrow", argLength: 3, typ: "(UInt64,UInt64)"}, // arg0 - (arg1 + arg2), arg2 must be 0 or 1. returns (value, value>>64&1)
+
+ {name: "Signmask", argLength: 1, typ: "Int32"}, // 0 if arg0 >= 0, -1 if arg0 < 0
+ {name: "Zeromask", argLength: 1, typ: "UInt32"}, // 0 if arg0 == 0, 0xffffffff if arg0 != 0
+ {name: "Slicemask", argLength: 1}, // 0 if arg0 == 0, -1 if arg0 > 0, undef if arg0<0. Type is native int size.
+
+ {name: "SpectreIndex", argLength: 2}, // arg0 if 0 <= arg0 < arg1, 0 otherwise. Type is native int size.
+ {name: "SpectreSliceIndex", argLength: 2}, // arg0 if 0 <= arg0 <= arg1, 0 otherwise. Type is native int size.
+
+ {name: "Cvt32Uto32F", argLength: 1}, // uint32 -> float32, only used on 32-bit arch
+ {name: "Cvt32Uto64F", argLength: 1}, // uint32 -> float64, only used on 32-bit arch
+ {name: "Cvt32Fto32U", argLength: 1}, // float32 -> uint32, only used on 32-bit arch
+ {name: "Cvt64Fto32U", argLength: 1}, // float64 -> uint32, only used on 32-bit arch
+ {name: "Cvt64Uto32F", argLength: 1}, // uint64 -> float32, only used on archs that has the instruction
+ {name: "Cvt64Uto64F", argLength: 1}, // uint64 -> float64, only used on archs that has the instruction
+ {name: "Cvt32Fto64U", argLength: 1}, // float32 -> uint64, only used on archs that has the instruction
+ {name: "Cvt64Fto64U", argLength: 1}, // float64 -> uint64, only used on archs that has the instruction
+
+ // pseudo-ops for breaking Tuple
+ {name: "Select0", argLength: 1, zeroWidth: true}, // the first component of a tuple
+ {name: "Select1", argLength: 1, zeroWidth: true}, // the second component of a tuple
+ {name: "SelectN", argLength: 1, aux: "Int64"}, // arg0=result, auxint=field index. Returns the auxint'th member.
+ {name: "SelectNAddr", argLength: 1, aux: "Int64"}, // arg0=result, auxint=field index. Returns the address of auxint'th member. Used for un-SSA-able result types.
+ {name: "MakeResult", argLength: -1}, // arg0 .. are components of a "Result" (like the result from a Call). The last arg should be memory (like the result from a call).
+
+ // Atomic operations used for semantically inlining sync/atomic and
+ // runtime/internal/atomic. Atomic loads return a new memory so that
+ // the loads are properly ordered with respect to other loads and
+ // stores.
+ {name: "AtomicLoad8", argLength: 2, typ: "(UInt8,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
+ {name: "AtomicLoad32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
+ {name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
+ {name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
+ {name: "AtomicLoadAcq32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Lock acquisition, returns loaded value and new memory.
+ {name: "AtomicLoadAcq64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Lock acquisition, returns loaded value and new memory.
+ {name: "AtomicStore8", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
+ {name: "AtomicStore32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
+ {name: "AtomicStore64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
+ {name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
+ {name: "AtomicStoreRel32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Lock release, returns memory.
+ {name: "AtomicStoreRel64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Lock release, returns memory.
+ {name: "AtomicExchange32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
+ {name: "AtomicExchange64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
+ {name: "AtomicAdd32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
+ {name: "AtomicAdd64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
+ {name: "AtomicCompareAndSwap32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory.
+ {name: "AtomicCompareAndSwap64", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory.
+ {name: "AtomicCompareAndSwapRel32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Lock release, reports whether store happens and new memory.
+ {name: "AtomicAnd8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
+ {name: "AtomicAnd32", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
+ {name: "AtomicOr8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
+ {name: "AtomicOr32", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
+
+ // Atomic operation variants
+ // These variants have the same semantics as above atomic operations.
+ // But they are used for generating more efficient code on certain modern machines, with run-time CPU feature detection.
+ // Currently, they are used on ARM64 only.
+ {name: "AtomicAdd32Variant", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
+ {name: "AtomicAdd64Variant", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
+ {name: "AtomicExchange32Variant", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
+ {name: "AtomicExchange64Variant", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
+ {name: "AtomicCompareAndSwap32Variant", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory.
+ {name: "AtomicCompareAndSwap64Variant", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory.
+ {name: "AtomicAnd8Variant", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
+ {name: "AtomicAnd32Variant", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
+ {name: "AtomicOr8Variant", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
+ {name: "AtomicOr32Variant", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
+
+ // Clobber experiment op
+ {name: "Clobber", argLength: 0, typ: "Void", aux: "SymOff", symEffect: "None"}, // write an invalid pointer value to the given pointer slot of a stack variable
+}
+
+// kind controls successors implicit exit
+// ----------------------------------------------------------
+// Exit [return mem] [] yes
+// Ret [return mem] [] yes
+// RetJmp [return mem] [] yes
+// Plain [] [next]
+// If [boolean Value] [then, else]
+// First [] [always, never]
+
+var genericBlocks = []blockData{
+ {name: "Plain"}, // a single successor
+ {name: "If", controls: 1}, // if Controls[0] goto Succs[0] else goto Succs[1]
+ {name: "Defer", controls: 1}, // Succs[0]=defer queued, Succs[1]=defer recovered. Controls[0] is call op (of memory type)
+ {name: "Ret", controls: 1}, // no successors, Controls[0] value is memory result
+ {name: "RetJmp", controls: 1}, // no successors, Controls[0] value is memory result, jumps to b.Aux.(*gc.Sym)
+ {name: "Exit", controls: 1}, // no successors, Controls[0] value generates a panic
+
+ // transient block state used for dead code removal
+ {name: "First"}, // 2 successors, always takes the first one (second is dead)
+}
+
+func init() {
+ archs = append(archs, arch{
+ name: "generic",
+ ops: genericOps,
+ blocks: genericBlocks,
+ generic: true,
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/gen/main.go b/src/cmd/compile/internal/ssa/gen/main.go
new file mode 100644
index 0000000..dfa146a
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/main.go
@@ -0,0 +1,541 @@
+// 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.
+
+// +build ignore
+
+// The gen command generates Go code (in the parent directory) for all
+// the architecture-specific opcodes, blocks, and rewrites.
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "io/ioutil"
+ "log"
+ "os"
+ "path"
+ "regexp"
+ "runtime"
+ "runtime/pprof"
+ "runtime/trace"
+ "sort"
+ "strings"
+ "sync"
+)
+
+// TODO: capitalize these types, so that we can more easily tell variable names
+// apart from type names, and avoid awkward func parameters like "arch arch".
+
+type arch struct {
+ name string
+ pkg string // obj package to import for this arch.
+ genfile string // source file containing opcode code generation.
+ ops []opData
+ blocks []blockData
+ regnames []string
+ gpregmask regMask
+ fpregmask regMask
+ fp32regmask regMask
+ fp64regmask regMask
+ specialregmask regMask
+ framepointerreg int8
+ linkreg int8
+ generic bool
+ imports []string
+}
+
+type opData struct {
+ name string
+ reg regInfo
+ asm string
+ typ string // default result type
+ aux string
+ rematerializeable bool
+ argLength int32 // number of arguments, if -1, then this operation has a variable number of arguments
+ commutative bool // this operation is commutative on its first 2 arguments (e.g. addition)
+ resultInArg0 bool // (first, if a tuple) output of v and v.Args[0] must be allocated to the same register
+ resultNotInArgs bool // outputs must not be allocated to the same registers as inputs
+ clobberFlags bool // this op clobbers flags register
+ call bool // is a function call
+ nilCheck bool // this op is a nil check on arg0
+ faultOnNilArg0 bool // this op will fault if arg0 is nil (and aux encodes a small offset)
+ faultOnNilArg1 bool // this op will fault if arg1 is nil (and aux encodes a small offset)
+ usesScratch bool // this op requires scratch memory space
+ hasSideEffects bool // for "reasons", not to be eliminated. E.g., atomic store, #19182.
+ zeroWidth bool // op never translates into any machine code. example: copy, which may sometimes translate to machine code, is not zero-width.
+ unsafePoint bool // this op is an unsafe point, i.e. not safe for async preemption
+ symEffect string // effect this op has on symbol in aux
+ scale uint8 // amd64/386 indexed load scale
+}
+
+type blockData struct {
+ name string // the suffix for this block ("EQ", "LT", etc.)
+ controls int // the number of control values this type of block requires
+ aux string // the type of the Aux/AuxInt value, if any
+}
+
+type regInfo struct {
+ // inputs[i] encodes the set of registers allowed for the i'th input.
+ // Inputs that don't use registers (flags, memory, etc.) should be 0.
+ inputs []regMask
+ // clobbers encodes the set of registers that are overwritten by
+ // the instruction (other than the output registers).
+ clobbers regMask
+ // outputs[i] encodes the set of registers allowed for the i'th output.
+ outputs []regMask
+}
+
+type regMask uint64
+
+func (a arch) regMaskComment(r regMask) string {
+ var buf bytes.Buffer
+ for i := uint64(0); r != 0; i++ {
+ if r&1 != 0 {
+ if buf.Len() == 0 {
+ buf.WriteString(" //")
+ }
+ buf.WriteString(" ")
+ buf.WriteString(a.regnames[i])
+ }
+ r >>= 1
+ }
+ return buf.String()
+}
+
+var archs []arch
+
+var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
+var memprofile = flag.String("memprofile", "", "write memory profile to `file`")
+var tracefile = flag.String("trace", "", "write trace to `file`")
+
+func main() {
+ flag.Parse()
+ if *cpuprofile != "" {
+ f, err := os.Create(*cpuprofile)
+ if err != nil {
+ log.Fatal("could not create CPU profile: ", err)
+ }
+ defer f.Close()
+ if err := pprof.StartCPUProfile(f); err != nil {
+ log.Fatal("could not start CPU profile: ", err)
+ }
+ defer pprof.StopCPUProfile()
+ }
+ if *tracefile != "" {
+ f, err := os.Create(*tracefile)
+ if err != nil {
+ log.Fatalf("failed to create trace output file: %v", err)
+ }
+ defer func() {
+ if err := f.Close(); err != nil {
+ log.Fatalf("failed to close trace file: %v", err)
+ }
+ }()
+
+ if err := trace.Start(f); err != nil {
+ log.Fatalf("failed to start trace: %v", err)
+ }
+ defer trace.Stop()
+ }
+
+ sort.Sort(ArchsByName(archs))
+
+ // The generate tasks are run concurrently, since they are CPU-intensive
+ // that can easily make use of many cores on a machine.
+ //
+ // Note that there is no limit on the concurrency at the moment. On a
+ // four-core laptop at the time of writing, peak RSS usually reaches
+ // ~200MiB, which seems doable by practically any machine nowadays. If
+ // that stops being the case, we can cap this func to a fixed number of
+ // architectures being generated at once.
+
+ tasks := []func(){
+ genOp,
+ }
+ for _, a := range archs {
+ a := a // the funcs are ran concurrently at a later time
+ tasks = append(tasks, func() {
+ genRules(a)
+ genSplitLoadRules(a)
+ })
+ }
+ var wg sync.WaitGroup
+ for _, task := range tasks {
+ task := task
+ wg.Add(1)
+ go func() {
+ task()
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+
+ if *memprofile != "" {
+ f, err := os.Create(*memprofile)
+ if err != nil {
+ log.Fatal("could not create memory profile: ", err)
+ }
+ defer f.Close()
+ runtime.GC() // get up-to-date statistics
+ if err := pprof.WriteHeapProfile(f); err != nil {
+ log.Fatal("could not write memory profile: ", err)
+ }
+ }
+}
+
+func genOp() {
+ w := new(bytes.Buffer)
+ fmt.Fprintf(w, "// Code generated from gen/*Ops.go; DO NOT EDIT.\n")
+ fmt.Fprintln(w)
+ fmt.Fprintln(w, "package ssa")
+
+ fmt.Fprintln(w, "import (")
+ fmt.Fprintln(w, "\"cmd/internal/obj\"")
+ for _, a := range archs {
+ if a.pkg != "" {
+ fmt.Fprintf(w, "%q\n", a.pkg)
+ }
+ }
+ fmt.Fprintln(w, ")")
+
+ // generate Block* declarations
+ fmt.Fprintln(w, "const (")
+ fmt.Fprintln(w, "BlockInvalid BlockKind = iota")
+ for _, a := range archs {
+ fmt.Fprintln(w)
+ for _, d := range a.blocks {
+ fmt.Fprintf(w, "Block%s%s\n", a.Name(), d.name)
+ }
+ }
+ fmt.Fprintln(w, ")")
+
+ // generate block kind string method
+ fmt.Fprintln(w, "var blockString = [...]string{")
+ fmt.Fprintln(w, "BlockInvalid:\"BlockInvalid\",")
+ for _, a := range archs {
+ fmt.Fprintln(w)
+ for _, b := range a.blocks {
+ fmt.Fprintf(w, "Block%s%s:\"%s\",\n", a.Name(), b.name, b.name)
+ }
+ }
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w, "func (k BlockKind) String() string {return blockString[k]}")
+
+ // generate block kind auxint method
+ fmt.Fprintln(w, "func (k BlockKind) AuxIntType() string {")
+ fmt.Fprintln(w, "switch k {")
+ for _, a := range archs {
+ for _, b := range a.blocks {
+ if b.auxIntType() == "invalid" {
+ continue
+ }
+ fmt.Fprintf(w, "case Block%s%s: return \"%s\"\n", a.Name(), b.name, b.auxIntType())
+ }
+ }
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w, "return \"\"")
+ fmt.Fprintln(w, "}")
+
+ // generate Op* declarations
+ fmt.Fprintln(w, "const (")
+ fmt.Fprintln(w, "OpInvalid Op = iota") // make sure OpInvalid is 0.
+ for _, a := range archs {
+ fmt.Fprintln(w)
+ for _, v := range a.ops {
+ if v.name == "Invalid" {
+ continue
+ }
+ fmt.Fprintf(w, "Op%s%s\n", a.Name(), v.name)
+ }
+ }
+ fmt.Fprintln(w, ")")
+
+ // generate OpInfo table
+ fmt.Fprintln(w, "var opcodeTable = [...]opInfo{")
+ fmt.Fprintln(w, " { name: \"OpInvalid\" },")
+ for _, a := range archs {
+ fmt.Fprintln(w)
+
+ pkg := path.Base(a.pkg)
+ for _, v := range a.ops {
+ if v.name == "Invalid" {
+ continue
+ }
+ fmt.Fprintln(w, "{")
+ fmt.Fprintf(w, "name:\"%s\",\n", v.name)
+
+ // flags
+ if v.aux != "" {
+ fmt.Fprintf(w, "auxType: aux%s,\n", v.aux)
+ }
+ fmt.Fprintf(w, "argLen: %d,\n", v.argLength)
+
+ if v.rematerializeable {
+ if v.reg.clobbers != 0 {
+ log.Fatalf("%s is rematerializeable and clobbers registers", v.name)
+ }
+ if v.clobberFlags {
+ log.Fatalf("%s is rematerializeable and clobbers flags", v.name)
+ }
+ fmt.Fprintln(w, "rematerializeable: true,")
+ }
+ if v.commutative {
+ fmt.Fprintln(w, "commutative: true,")
+ }
+ if v.resultInArg0 {
+ fmt.Fprintln(w, "resultInArg0: true,")
+ // OpConvert's register mask is selected dynamically,
+ // so don't try to check it in the static table.
+ if v.name != "Convert" && v.reg.inputs[0] != v.reg.outputs[0] {
+ log.Fatalf("%s: input[0] and output[0] must use the same registers for %s", a.name, v.name)
+ }
+ if v.name != "Convert" && v.commutative && v.reg.inputs[1] != v.reg.outputs[0] {
+ log.Fatalf("%s: input[1] and output[0] must use the same registers for %s", a.name, v.name)
+ }
+ }
+ if v.resultNotInArgs {
+ fmt.Fprintln(w, "resultNotInArgs: true,")
+ }
+ if v.clobberFlags {
+ fmt.Fprintln(w, "clobberFlags: true,")
+ }
+ if v.call {
+ fmt.Fprintln(w, "call: true,")
+ }
+ if v.nilCheck {
+ fmt.Fprintln(w, "nilCheck: true,")
+ }
+ if v.faultOnNilArg0 {
+ fmt.Fprintln(w, "faultOnNilArg0: true,")
+ if v.aux != "Sym" && v.aux != "SymOff" && v.aux != "SymValAndOff" && v.aux != "Int64" && v.aux != "Int32" && v.aux != "" {
+ log.Fatalf("faultOnNilArg0 with aux %s not allowed", v.aux)
+ }
+ }
+ if v.faultOnNilArg1 {
+ fmt.Fprintln(w, "faultOnNilArg1: true,")
+ if v.aux != "Sym" && v.aux != "SymOff" && v.aux != "SymValAndOff" && v.aux != "Int64" && v.aux != "Int32" && v.aux != "" {
+ log.Fatalf("faultOnNilArg1 with aux %s not allowed", v.aux)
+ }
+ }
+ if v.usesScratch {
+ fmt.Fprintln(w, "usesScratch: true,")
+ }
+ if v.hasSideEffects {
+ fmt.Fprintln(w, "hasSideEffects: true,")
+ }
+ if v.zeroWidth {
+ fmt.Fprintln(w, "zeroWidth: true,")
+ }
+ if v.unsafePoint {
+ fmt.Fprintln(w, "unsafePoint: true,")
+ }
+ needEffect := strings.HasPrefix(v.aux, "Sym")
+ if v.symEffect != "" {
+ if !needEffect {
+ log.Fatalf("symEffect with aux %s not allowed", v.aux)
+ }
+ fmt.Fprintf(w, "symEffect: Sym%s,\n", strings.Replace(v.symEffect, ",", "|Sym", -1))
+ } else if needEffect {
+ log.Fatalf("symEffect needed for aux %s", v.aux)
+ }
+ if a.name == "generic" {
+ fmt.Fprintln(w, "generic:true,")
+ fmt.Fprintln(w, "},") // close op
+ // generic ops have no reg info or asm
+ continue
+ }
+ if v.asm != "" {
+ fmt.Fprintf(w, "asm: %s.A%s,\n", pkg, v.asm)
+ }
+ if v.scale != 0 {
+ fmt.Fprintf(w, "scale: %d,\n", v.scale)
+ }
+ fmt.Fprintln(w, "reg:regInfo{")
+
+ // Compute input allocation order. We allocate from the
+ // most to the least constrained input. This order guarantees
+ // that we will always be able to find a register.
+ var s []intPair
+ for i, r := range v.reg.inputs {
+ if r != 0 {
+ s = append(s, intPair{countRegs(r), i})
+ }
+ }
+ if len(s) > 0 {
+ sort.Sort(byKey(s))
+ fmt.Fprintln(w, "inputs: []inputInfo{")
+ for _, p := range s {
+ r := v.reg.inputs[p.val]
+ fmt.Fprintf(w, "{%d,%d},%s\n", p.val, r, a.regMaskComment(r))
+ }
+ fmt.Fprintln(w, "},")
+ }
+
+ if v.reg.clobbers > 0 {
+ fmt.Fprintf(w, "clobbers: %d,%s\n", v.reg.clobbers, a.regMaskComment(v.reg.clobbers))
+ }
+
+ // reg outputs
+ s = s[:0]
+ for i, r := range v.reg.outputs {
+ s = append(s, intPair{countRegs(r), i})
+ }
+ if len(s) > 0 {
+ sort.Sort(byKey(s))
+ fmt.Fprintln(w, "outputs: []outputInfo{")
+ for _, p := range s {
+ r := v.reg.outputs[p.val]
+ fmt.Fprintf(w, "{%d,%d},%s\n", p.val, r, a.regMaskComment(r))
+ }
+ fmt.Fprintln(w, "},")
+ }
+ fmt.Fprintln(w, "},") // close reg info
+ fmt.Fprintln(w, "},") // close op
+ }
+ }
+ fmt.Fprintln(w, "}")
+
+ fmt.Fprintln(w, "func (o Op) Asm() obj.As {return opcodeTable[o].asm}")
+ fmt.Fprintln(w, "func (o Op) Scale() int16 {return int16(opcodeTable[o].scale)}")
+
+ // generate op string method
+ fmt.Fprintln(w, "func (o Op) String() string {return opcodeTable[o].name }")
+
+ fmt.Fprintln(w, "func (o Op) UsesScratch() bool { return opcodeTable[o].usesScratch }")
+
+ fmt.Fprintln(w, "func (o Op) SymEffect() SymEffect { return opcodeTable[o].symEffect }")
+ fmt.Fprintln(w, "func (o Op) IsCall() bool { return opcodeTable[o].call }")
+ fmt.Fprintln(w, "func (o Op) HasSideEffects() bool { return opcodeTable[o].hasSideEffects }")
+ fmt.Fprintln(w, "func (o Op) UnsafePoint() bool { return opcodeTable[o].unsafePoint }")
+
+ // generate registers
+ for _, a := range archs {
+ if a.generic {
+ continue
+ }
+ fmt.Fprintf(w, "var registers%s = [...]Register {\n", a.name)
+ var gcRegN int
+ for i, r := range a.regnames {
+ pkg := a.pkg[len("cmd/internal/obj/"):]
+ var objname string // name in cmd/internal/obj/$ARCH
+ switch r {
+ case "SB":
+ // SB isn't a real register. cmd/internal/obj expects 0 in this case.
+ objname = "0"
+ case "SP":
+ objname = pkg + ".REGSP"
+ case "g":
+ objname = pkg + ".REGG"
+ default:
+ objname = pkg + ".REG_" + r
+ }
+ // Assign a GC register map index to registers
+ // that may contain pointers.
+ gcRegIdx := -1
+ if a.gpregmask&(1<<uint(i)) != 0 {
+ gcRegIdx = gcRegN
+ gcRegN++
+ }
+ fmt.Fprintf(w, " {%d, %s, %d, \"%s\"},\n", i, objname, gcRegIdx, r)
+ }
+ if gcRegN > 32 {
+ // Won't fit in a uint32 mask.
+ log.Fatalf("too many GC registers (%d > 32) on %s", gcRegN, a.name)
+ }
+ fmt.Fprintln(w, "}")
+ fmt.Fprintf(w, "var gpRegMask%s = regMask(%d)\n", a.name, a.gpregmask)
+ fmt.Fprintf(w, "var fpRegMask%s = regMask(%d)\n", a.name, a.fpregmask)
+ if a.fp32regmask != 0 {
+ fmt.Fprintf(w, "var fp32RegMask%s = regMask(%d)\n", a.name, a.fp32regmask)
+ }
+ if a.fp64regmask != 0 {
+ fmt.Fprintf(w, "var fp64RegMask%s = regMask(%d)\n", a.name, a.fp64regmask)
+ }
+ fmt.Fprintf(w, "var specialRegMask%s = regMask(%d)\n", a.name, a.specialregmask)
+ fmt.Fprintf(w, "var framepointerReg%s = int8(%d)\n", a.name, a.framepointerreg)
+ fmt.Fprintf(w, "var linkReg%s = int8(%d)\n", a.name, a.linkreg)
+ }
+
+ // gofmt result
+ b := w.Bytes()
+ var err error
+ b, err = format.Source(b)
+ if err != nil {
+ fmt.Printf("%s\n", w.Bytes())
+ panic(err)
+ }
+
+ if err := ioutil.WriteFile("../opGen.go", b, 0666); err != nil {
+ log.Fatalf("can't write output: %v\n", err)
+ }
+
+ // Check that the arch genfile handles all the arch-specific opcodes.
+ // This is very much a hack, but it is better than nothing.
+ //
+ // Do a single regexp pass to record all ops being handled in a map, and
+ // then compare that with the ops list. This is much faster than one
+ // regexp pass per opcode.
+ for _, a := range archs {
+ if a.genfile == "" {
+ continue
+ }
+
+ pattern := fmt.Sprintf(`\Wssa\.Op%s([a-zA-Z0-9_]+)\W`, a.name)
+ rxOp, err := regexp.Compile(pattern)
+ if err != nil {
+ log.Fatalf("bad opcode regexp %s: %v", pattern, err)
+ }
+
+ src, err := ioutil.ReadFile(a.genfile)
+ if err != nil {
+ log.Fatalf("can't read %s: %v", a.genfile, err)
+ }
+ seen := make(map[string]bool, len(a.ops))
+ for _, m := range rxOp.FindAllSubmatch(src, -1) {
+ seen[string(m[1])] = true
+ }
+ for _, op := range a.ops {
+ if !seen[op.name] {
+ log.Fatalf("Op%s%s has no code generation in %s", a.name, op.name, a.genfile)
+ }
+ }
+ }
+}
+
+// Name returns the name of the architecture for use in Op* and Block* enumerations.
+func (a arch) Name() string {
+ s := a.name
+ if s == "generic" {
+ s = ""
+ }
+ return s
+}
+
+// countRegs returns the number of set bits in the register mask.
+func countRegs(r regMask) int {
+ n := 0
+ for r != 0 {
+ n += int(r & 1)
+ r >>= 1
+ }
+ return n
+}
+
+// for sorting a pair of integers by key
+type intPair struct {
+ key, val int
+}
+type byKey []intPair
+
+func (a byKey) Len() int { return len(a) }
+func (a byKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a byKey) Less(i, j int) bool { return a[i].key < a[j].key }
+
+type ArchsByName []arch
+
+func (x ArchsByName) Len() int { return len(x) }
+func (x ArchsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x ArchsByName) Less(i, j int) bool { return x[i].name < x[j].name }
diff --git a/src/cmd/compile/internal/ssa/gen/rulegen.go b/src/cmd/compile/internal/ssa/gen/rulegen.go
new file mode 100644
index 0000000..aaf9101
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/rulegen.go
@@ -0,0 +1,1856 @@
+// 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.
+
+// +build gen
+
+// This program generates Go code that applies rewrite rules to a Value.
+// The generated code implements a function of type func (v *Value) bool
+// which reports whether if did something.
+// Ideas stolen from Swift: http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-2000-2.html
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/format"
+ "go/parser"
+ "go/printer"
+ "go/token"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "path"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+
+ "golang.org/x/tools/go/ast/astutil"
+)
+
+// rule syntax:
+// sexpr [&& extra conditions] => [@block] sexpr
+//
+// sexpr are s-expressions (lisp-like parenthesized groupings)
+// sexpr ::= [variable:](opcode sexpr*)
+// | variable
+// | <type>
+// | [auxint]
+// | {aux}
+//
+// aux ::= variable | {code}
+// type ::= variable | {code}
+// variable ::= some token
+// opcode ::= one of the opcodes from the *Ops.go files
+
+// special rules: trailing ellipsis "..." (in the outermost sexpr?) must match on both sides of a rule.
+// trailing three underscore "___" in the outermost match sexpr indicate the presence of
+// extra ignored args that need not appear in the replacement
+
+// extra conditions is just a chunk of Go that evaluates to a boolean. It may use
+// variables declared in the matching tsexpr. The variable "v" is predefined to be
+// the value matched by the entire rule.
+
+// If multiple rules match, the first one in file order is selected.
+
+var (
+ genLog = flag.Bool("log", false, "generate code that logs; for debugging only")
+ addLine = flag.Bool("line", false, "add line number comment to generated rules; for debugging only")
+)
+
+type Rule struct {
+ Rule string
+ Loc string // file name & line number
+}
+
+func (r Rule) String() string {
+ return fmt.Sprintf("rule %q at %s", r.Rule, r.Loc)
+}
+
+func normalizeSpaces(s string) string {
+ return strings.Join(strings.Fields(strings.TrimSpace(s)), " ")
+}
+
+// parse returns the matching part of the rule, additional conditions, and the result.
+func (r Rule) parse() (match, cond, result string) {
+ s := strings.Split(r.Rule, "=>")
+ match = normalizeSpaces(s[0])
+ result = normalizeSpaces(s[1])
+ cond = ""
+ if i := strings.Index(match, "&&"); i >= 0 {
+ cond = normalizeSpaces(match[i+2:])
+ match = normalizeSpaces(match[:i])
+ }
+ return match, cond, result
+}
+
+func genRules(arch arch) { genRulesSuffix(arch, "") }
+func genSplitLoadRules(arch arch) { genRulesSuffix(arch, "splitload") }
+
+func genRulesSuffix(arch arch, suff string) {
+ // Open input file.
+ text, err := os.Open(arch.name + suff + ".rules")
+ if err != nil {
+ if suff == "" {
+ // All architectures must have a plain rules file.
+ log.Fatalf("can't read rule file: %v", err)
+ }
+ // Some architectures have bonus rules files that others don't share. That's fine.
+ return
+ }
+
+ // oprules contains a list of rules for each block and opcode
+ blockrules := map[string][]Rule{}
+ oprules := map[string][]Rule{}
+
+ // read rule file
+ scanner := bufio.NewScanner(text)
+ rule := ""
+ var lineno int
+ var ruleLineno int // line number of "=>"
+ for scanner.Scan() {
+ lineno++
+ line := scanner.Text()
+ if i := strings.Index(line, "//"); i >= 0 {
+ // Remove comments. Note that this isn't string safe, so
+ // it will truncate lines with // inside strings. Oh well.
+ line = line[:i]
+ }
+ rule += " " + line
+ rule = strings.TrimSpace(rule)
+ if rule == "" {
+ continue
+ }
+ if !strings.Contains(rule, "=>") {
+ continue
+ }
+ if ruleLineno == 0 {
+ ruleLineno = lineno
+ }
+ if strings.HasSuffix(rule, "=>") {
+ continue // continue on the next line
+ }
+ if n := balance(rule); n > 0 {
+ continue // open parentheses remain, continue on the next line
+ } else if n < 0 {
+ break // continuing the line can't help, and it will only make errors worse
+ }
+
+ loc := fmt.Sprintf("%s%s.rules:%d", arch.name, suff, ruleLineno)
+ for _, rule2 := range expandOr(rule) {
+ r := Rule{Rule: rule2, Loc: loc}
+ if rawop := strings.Split(rule2, " ")[0][1:]; isBlock(rawop, arch) {
+ blockrules[rawop] = append(blockrules[rawop], r)
+ continue
+ }
+ // Do fancier value op matching.
+ match, _, _ := r.parse()
+ op, oparch, _, _, _, _ := parseValue(match, arch, loc)
+ opname := fmt.Sprintf("Op%s%s", oparch, op.name)
+ oprules[opname] = append(oprules[opname], r)
+ }
+ rule = ""
+ ruleLineno = 0
+ }
+ if err := scanner.Err(); err != nil {
+ log.Fatalf("scanner failed: %v\n", err)
+ }
+ if balance(rule) != 0 {
+ log.Fatalf("%s.rules:%d: unbalanced rule: %v\n", arch.name, lineno, rule)
+ }
+
+ // Order all the ops.
+ var ops []string
+ for op := range oprules {
+ ops = append(ops, op)
+ }
+ sort.Strings(ops)
+
+ genFile := &File{Arch: arch, Suffix: suff}
+ // Main rewrite routine is a switch on v.Op.
+ fn := &Func{Kind: "Value", ArgLen: -1}
+
+ sw := &Switch{Expr: exprf("v.Op")}
+ for _, op := range ops {
+ eop, ok := parseEllipsisRules(oprules[op], arch)
+ if ok {
+ if strings.Contains(oprules[op][0].Rule, "=>") && opByName(arch, op).aux != opByName(arch, eop).aux {
+ panic(fmt.Sprintf("can't use ... for ops that have different aux types: %s and %s", op, eop))
+ }
+ swc := &Case{Expr: exprf("%s", op)}
+ swc.add(stmtf("v.Op = %s", eop))
+ swc.add(stmtf("return true"))
+ sw.add(swc)
+ continue
+ }
+
+ swc := &Case{Expr: exprf("%s", op)}
+ swc.add(stmtf("return rewriteValue%s%s_%s(v)", arch.name, suff, op))
+ sw.add(swc)
+ }
+ fn.add(sw)
+ fn.add(stmtf("return false"))
+ genFile.add(fn)
+
+ // Generate a routine per op. Note that we don't make one giant routine
+ // because it is too big for some compilers.
+ for _, op := range ops {
+ rules := oprules[op]
+ _, ok := parseEllipsisRules(oprules[op], arch)
+ if ok {
+ continue
+ }
+
+ // rr is kept between iterations, so that each rule can check
+ // that the previous rule wasn't unconditional.
+ var rr *RuleRewrite
+ fn := &Func{
+ Kind: "Value",
+ Suffix: fmt.Sprintf("_%s", op),
+ ArgLen: opByName(arch, op).argLength,
+ }
+ fn.add(declf("b", "v.Block"))
+ fn.add(declf("config", "b.Func.Config"))
+ fn.add(declf("fe", "b.Func.fe"))
+ fn.add(declf("typ", "&b.Func.Config.Types"))
+ for _, rule := range rules {
+ if rr != nil && !rr.CanFail {
+ log.Fatalf("unconditional rule %s is followed by other rules", rr.Match)
+ }
+ rr = &RuleRewrite{Loc: rule.Loc}
+ rr.Match, rr.Cond, rr.Result = rule.parse()
+ pos, _ := genMatch(rr, arch, rr.Match, fn.ArgLen >= 0)
+ if pos == "" {
+ pos = "v.Pos"
+ }
+ if rr.Cond != "" {
+ rr.add(breakf("!(%s)", rr.Cond))
+ }
+ genResult(rr, arch, rr.Result, pos)
+ if *genLog {
+ rr.add(stmtf("logRule(%q)", rule.Loc))
+ }
+ fn.add(rr)
+ }
+ if rr.CanFail {
+ fn.add(stmtf("return false"))
+ }
+ genFile.add(fn)
+ }
+
+ // Generate block rewrite function. There are only a few block types
+ // so we can make this one function with a switch.
+ fn = &Func{Kind: "Block"}
+ fn.add(declf("config", "b.Func.Config"))
+ fn.add(declf("typ", "&b.Func.Config.Types"))
+
+ sw = &Switch{Expr: exprf("b.Kind")}
+ ops = ops[:0]
+ for op := range blockrules {
+ ops = append(ops, op)
+ }
+ sort.Strings(ops)
+ for _, op := range ops {
+ name, data := getBlockInfo(op, arch)
+ swc := &Case{Expr: exprf("%s", name)}
+ for _, rule := range blockrules[op] {
+ swc.add(genBlockRewrite(rule, arch, data))
+ }
+ sw.add(swc)
+ }
+ fn.add(sw)
+ fn.add(stmtf("return false"))
+ genFile.add(fn)
+
+ // Remove unused imports and variables.
+ buf := new(bytes.Buffer)
+ fprint(buf, genFile)
+ fset := token.NewFileSet()
+ file, err := parser.ParseFile(fset, "", buf, parser.ParseComments)
+ if err != nil {
+ filename := fmt.Sprintf("%s_broken.go", arch.name)
+ if err := ioutil.WriteFile(filename, buf.Bytes(), 0644); err != nil {
+ log.Printf("failed to dump broken code to %s: %v", filename, err)
+ } else {
+ log.Printf("dumped broken code to %s", filename)
+ }
+ log.Fatalf("failed to parse generated code for arch %s: %v", arch.name, err)
+ }
+ tfile := fset.File(file.Pos())
+
+ // First, use unusedInspector to find the unused declarations by their
+ // start position.
+ u := unusedInspector{unused: make(map[token.Pos]bool)}
+ u.node(file)
+
+ // Then, delete said nodes via astutil.Apply.
+ pre := func(c *astutil.Cursor) bool {
+ node := c.Node()
+ if node == nil {
+ return true
+ }
+ if u.unused[node.Pos()] {
+ c.Delete()
+ // Unused imports and declarations use exactly
+ // one line. Prevent leaving an empty line.
+ tfile.MergeLine(tfile.Position(node.Pos()).Line)
+ return false
+ }
+ return true
+ }
+ post := func(c *astutil.Cursor) bool {
+ switch node := c.Node().(type) {
+ case *ast.GenDecl:
+ if len(node.Specs) == 0 {
+ // Don't leave a broken or empty GenDecl behind,
+ // such as "import ()".
+ c.Delete()
+ }
+ }
+ return true
+ }
+ file = astutil.Apply(file, pre, post).(*ast.File)
+
+ // Write the well-formatted source to file
+ f, err := os.Create("../rewrite" + arch.name + suff + ".go")
+ if err != nil {
+ log.Fatalf("can't write output: %v", err)
+ }
+ defer f.Close()
+ // gofmt result; use a buffered writer, as otherwise go/format spends
+ // far too much time in syscalls.
+ bw := bufio.NewWriter(f)
+ if err := format.Node(bw, fset, file); err != nil {
+ log.Fatalf("can't format output: %v", err)
+ }
+ if err := bw.Flush(); err != nil {
+ log.Fatalf("can't write output: %v", err)
+ }
+ if err := f.Close(); err != nil {
+ log.Fatalf("can't write output: %v", err)
+ }
+}
+
+// unusedInspector can be used to detect unused variables and imports in an
+// ast.Node via its node method. The result is available in the "unused" map.
+//
+// note that unusedInspector is lazy and best-effort; it only supports the node
+// types and patterns used by the rulegen program.
+type unusedInspector struct {
+ // scope is the current scope, which can never be nil when a declaration
+ // is encountered. That is, the unusedInspector.node entrypoint should
+ // generally be an entire file or block.
+ scope *scope
+
+ // unused is the resulting set of unused declared names, indexed by the
+ // starting position of the node that declared the name.
+ unused map[token.Pos]bool
+
+ // defining is the object currently being defined; this is useful so
+ // that if "foo := bar" is unused and removed, we can then detect if
+ // "bar" becomes unused as well.
+ defining *object
+}
+
+// scoped opens a new scope when called, and returns a function which closes
+// that same scope. When a scope is closed, unused variables are recorded.
+func (u *unusedInspector) scoped() func() {
+ outer := u.scope
+ u.scope = &scope{outer: outer, objects: map[string]*object{}}
+ return func() {
+ for anyUnused := true; anyUnused; {
+ anyUnused = false
+ for _, obj := range u.scope.objects {
+ if obj.numUses > 0 {
+ continue
+ }
+ u.unused[obj.pos] = true
+ for _, used := range obj.used {
+ if used.numUses--; used.numUses == 0 {
+ anyUnused = true
+ }
+ }
+ // We've decremented numUses for each of the
+ // objects in used. Zero this slice too, to keep
+ // everything consistent.
+ obj.used = nil
+ }
+ }
+ u.scope = outer
+ }
+}
+
+func (u *unusedInspector) exprs(list []ast.Expr) {
+ for _, x := range list {
+ u.node(x)
+ }
+}
+
+func (u *unusedInspector) node(node ast.Node) {
+ switch node := node.(type) {
+ case *ast.File:
+ defer u.scoped()()
+ for _, decl := range node.Decls {
+ u.node(decl)
+ }
+ case *ast.GenDecl:
+ for _, spec := range node.Specs {
+ u.node(spec)
+ }
+ case *ast.ImportSpec:
+ impPath, _ := strconv.Unquote(node.Path.Value)
+ name := path.Base(impPath)
+ u.scope.objects[name] = &object{
+ name: name,
+ pos: node.Pos(),
+ }
+ case *ast.FuncDecl:
+ u.node(node.Type)
+ if node.Body != nil {
+ u.node(node.Body)
+ }
+ case *ast.FuncType:
+ if node.Params != nil {
+ u.node(node.Params)
+ }
+ if node.Results != nil {
+ u.node(node.Results)
+ }
+ case *ast.FieldList:
+ for _, field := range node.List {
+ u.node(field)
+ }
+ case *ast.Field:
+ u.node(node.Type)
+
+ // statements
+
+ case *ast.BlockStmt:
+ defer u.scoped()()
+ for _, stmt := range node.List {
+ u.node(stmt)
+ }
+ case *ast.DeclStmt:
+ u.node(node.Decl)
+ case *ast.IfStmt:
+ if node.Init != nil {
+ u.node(node.Init)
+ }
+ u.node(node.Cond)
+ u.node(node.Body)
+ if node.Else != nil {
+ u.node(node.Else)
+ }
+ case *ast.ForStmt:
+ if node.Init != nil {
+ u.node(node.Init)
+ }
+ if node.Cond != nil {
+ u.node(node.Cond)
+ }
+ if node.Post != nil {
+ u.node(node.Post)
+ }
+ u.node(node.Body)
+ case *ast.SwitchStmt:
+ if node.Init != nil {
+ u.node(node.Init)
+ }
+ if node.Tag != nil {
+ u.node(node.Tag)
+ }
+ u.node(node.Body)
+ case *ast.CaseClause:
+ u.exprs(node.List)
+ defer u.scoped()()
+ for _, stmt := range node.Body {
+ u.node(stmt)
+ }
+ case *ast.BranchStmt:
+ case *ast.ExprStmt:
+ u.node(node.X)
+ case *ast.AssignStmt:
+ if node.Tok != token.DEFINE {
+ u.exprs(node.Rhs)
+ u.exprs(node.Lhs)
+ break
+ }
+ lhs := node.Lhs
+ if len(lhs) == 2 && lhs[1].(*ast.Ident).Name == "_" {
+ lhs = lhs[:1]
+ }
+ if len(lhs) != 1 {
+ panic("no support for := with multiple names")
+ }
+
+ name := lhs[0].(*ast.Ident)
+ obj := &object{
+ name: name.Name,
+ pos: name.NamePos,
+ }
+
+ old := u.defining
+ u.defining = obj
+ u.exprs(node.Rhs)
+ u.defining = old
+
+ u.scope.objects[name.Name] = obj
+ case *ast.ReturnStmt:
+ u.exprs(node.Results)
+ case *ast.IncDecStmt:
+ u.node(node.X)
+
+ // expressions
+
+ case *ast.CallExpr:
+ u.node(node.Fun)
+ u.exprs(node.Args)
+ case *ast.SelectorExpr:
+ u.node(node.X)
+ case *ast.UnaryExpr:
+ u.node(node.X)
+ case *ast.BinaryExpr:
+ u.node(node.X)
+ u.node(node.Y)
+ case *ast.StarExpr:
+ u.node(node.X)
+ case *ast.ParenExpr:
+ u.node(node.X)
+ case *ast.IndexExpr:
+ u.node(node.X)
+ u.node(node.Index)
+ case *ast.TypeAssertExpr:
+ u.node(node.X)
+ u.node(node.Type)
+ case *ast.Ident:
+ if obj := u.scope.Lookup(node.Name); obj != nil {
+ obj.numUses++
+ if u.defining != nil {
+ u.defining.used = append(u.defining.used, obj)
+ }
+ }
+ case *ast.BasicLit:
+ case *ast.ValueSpec:
+ u.exprs(node.Values)
+ default:
+ panic(fmt.Sprintf("unhandled node: %T", node))
+ }
+}
+
+// scope keeps track of a certain scope and its declared names, as well as the
+// outer (parent) scope.
+type scope struct {
+ outer *scope // can be nil, if this is the top-level scope
+ objects map[string]*object // indexed by each declared name
+}
+
+func (s *scope) Lookup(name string) *object {
+ if obj := s.objects[name]; obj != nil {
+ return obj
+ }
+ if s.outer == nil {
+ return nil
+ }
+ return s.outer.Lookup(name)
+}
+
+// object keeps track of a declared name, such as a variable or import.
+type object struct {
+ name string
+ pos token.Pos // start position of the node declaring the object
+
+ numUses int // number of times this object is used
+ used []*object // objects that its declaration makes use of
+}
+
+func fprint(w io.Writer, n Node) {
+ switch n := n.(type) {
+ case *File:
+ file := n
+ seenRewrite := make(map[[3]string]string)
+ fmt.Fprintf(w, "// Code generated from gen/%s%s.rules; DO NOT EDIT.\n", n.Arch.name, n.Suffix)
+ fmt.Fprintf(w, "// generated with: cd gen; go run *.go\n")
+ fmt.Fprintf(w, "\npackage ssa\n")
+ for _, path := range append([]string{
+ "fmt",
+ "math",
+ "cmd/internal/obj",
+ "cmd/internal/objabi",
+ "cmd/compile/internal/types",
+ }, n.Arch.imports...) {
+ fmt.Fprintf(w, "import %q\n", path)
+ }
+ for _, f := range n.List {
+ f := f.(*Func)
+ fmt.Fprintf(w, "func rewrite%s%s%s%s(", f.Kind, n.Arch.name, n.Suffix, f.Suffix)
+ fmt.Fprintf(w, "%c *%s) bool {\n", strings.ToLower(f.Kind)[0], f.Kind)
+ if f.Kind == "Value" && f.ArgLen > 0 {
+ for i := f.ArgLen - 1; i >= 0; i-- {
+ fmt.Fprintf(w, "v_%d := v.Args[%d]\n", i, i)
+ }
+ }
+ for _, n := range f.List {
+ fprint(w, n)
+
+ if rr, ok := n.(*RuleRewrite); ok {
+ k := [3]string{
+ normalizeMatch(rr.Match, file.Arch),
+ normalizeWhitespace(rr.Cond),
+ normalizeWhitespace(rr.Result),
+ }
+ if prev, ok := seenRewrite[k]; ok {
+ log.Fatalf("duplicate rule %s, previously seen at %s\n", rr.Loc, prev)
+ }
+ seenRewrite[k] = rr.Loc
+ }
+ }
+ fmt.Fprintf(w, "}\n")
+ }
+ case *Switch:
+ fmt.Fprintf(w, "switch ")
+ fprint(w, n.Expr)
+ fmt.Fprintf(w, " {\n")
+ for _, n := range n.List {
+ fprint(w, n)
+ }
+ fmt.Fprintf(w, "}\n")
+ case *Case:
+ fmt.Fprintf(w, "case ")
+ fprint(w, n.Expr)
+ fmt.Fprintf(w, ":\n")
+ for _, n := range n.List {
+ fprint(w, n)
+ }
+ case *RuleRewrite:
+ if *addLine {
+ fmt.Fprintf(w, "// %s\n", n.Loc)
+ }
+ fmt.Fprintf(w, "// match: %s\n", n.Match)
+ if n.Cond != "" {
+ fmt.Fprintf(w, "// cond: %s\n", n.Cond)
+ }
+ fmt.Fprintf(w, "// result: %s\n", n.Result)
+ fmt.Fprintf(w, "for %s {\n", n.Check)
+ nCommutative := 0
+ for _, n := range n.List {
+ if b, ok := n.(*CondBreak); ok {
+ b.InsideCommuteLoop = nCommutative > 0
+ }
+ fprint(w, n)
+ if loop, ok := n.(StartCommuteLoop); ok {
+ if nCommutative != loop.Depth {
+ panic("mismatch commute loop depth")
+ }
+ nCommutative++
+ }
+ }
+ fmt.Fprintf(w, "return true\n")
+ for i := 0; i < nCommutative; i++ {
+ fmt.Fprintln(w, "}")
+ }
+ if n.CommuteDepth > 0 && n.CanFail {
+ fmt.Fprint(w, "break\n")
+ }
+ fmt.Fprintf(w, "}\n")
+ case *Declare:
+ fmt.Fprintf(w, "%s := ", n.Name)
+ fprint(w, n.Value)
+ fmt.Fprintln(w)
+ case *CondBreak:
+ fmt.Fprintf(w, "if ")
+ fprint(w, n.Cond)
+ fmt.Fprintf(w, " {\n")
+ if n.InsideCommuteLoop {
+ fmt.Fprintf(w, "continue")
+ } else {
+ fmt.Fprintf(w, "break")
+ }
+ fmt.Fprintf(w, "\n}\n")
+ case ast.Node:
+ printConfig.Fprint(w, emptyFset, n)
+ if _, ok := n.(ast.Stmt); ok {
+ fmt.Fprintln(w)
+ }
+ case StartCommuteLoop:
+ fmt.Fprintf(w, "for _i%[1]d := 0; _i%[1]d <= 1; _i%[1]d, %[2]s_0, %[2]s_1 = _i%[1]d + 1, %[2]s_1, %[2]s_0 {\n", n.Depth, n.V)
+ default:
+ log.Fatalf("cannot print %T", n)
+ }
+}
+
+var printConfig = printer.Config{
+ Mode: printer.RawFormat, // we use go/format later, so skip work here
+}
+
+var emptyFset = token.NewFileSet()
+
+// Node can be a Statement or an ast.Expr.
+type Node interface{}
+
+// Statement can be one of our high-level statement struct types, or an
+// ast.Stmt under some limited circumstances.
+type Statement interface{}
+
+// BodyBase is shared by all of our statement pseudo-node types which can
+// contain other statements.
+type BodyBase struct {
+ List []Statement
+ CanFail bool
+}
+
+func (w *BodyBase) add(node Statement) {
+ var last Statement
+ if len(w.List) > 0 {
+ last = w.List[len(w.List)-1]
+ }
+ if node, ok := node.(*CondBreak); ok {
+ w.CanFail = true
+ if last, ok := last.(*CondBreak); ok {
+ // Add to the previous "if <cond> { break }" via a
+ // logical OR, which will save verbosity.
+ last.Cond = &ast.BinaryExpr{
+ Op: token.LOR,
+ X: last.Cond,
+ Y: node.Cond,
+ }
+ return
+ }
+ }
+
+ w.List = append(w.List, node)
+}
+
+// predeclared contains globally known tokens that should not be redefined.
+var predeclared = map[string]bool{
+ "nil": true,
+ "false": true,
+ "true": true,
+}
+
+// declared reports if the body contains a Declare with the given name.
+func (w *BodyBase) declared(name string) bool {
+ if predeclared[name] {
+ // Treat predeclared names as having already been declared.
+ // This lets us use nil to match an aux field or
+ // true and false to match an auxint field.
+ return true
+ }
+ for _, s := range w.List {
+ if decl, ok := s.(*Declare); ok && decl.Name == name {
+ return true
+ }
+ }
+ return false
+}
+
+// These types define some high-level statement struct types, which can be used
+// as a Statement. This allows us to keep some node structs simpler, and have
+// higher-level nodes such as an entire rule rewrite.
+//
+// Note that ast.Expr is always used as-is; we don't declare our own expression
+// nodes.
+type (
+ File struct {
+ BodyBase // []*Func
+ Arch arch
+ Suffix string
+ }
+ Func struct {
+ BodyBase
+ Kind string // "Value" or "Block"
+ Suffix string
+ ArgLen int32 // if kind == "Value", number of args for this op
+ }
+ Switch struct {
+ BodyBase // []*Case
+ Expr ast.Expr
+ }
+ Case struct {
+ BodyBase
+ Expr ast.Expr
+ }
+ RuleRewrite struct {
+ BodyBase
+ Match, Cond, Result string // top comments
+ Check string // top-level boolean expression
+
+ Alloc int // for unique var names
+ Loc string // file name & line number of the original rule
+ CommuteDepth int // used to track depth of commute loops
+ }
+ Declare struct {
+ Name string
+ Value ast.Expr
+ }
+ CondBreak struct {
+ Cond ast.Expr
+ InsideCommuteLoop bool
+ }
+ StartCommuteLoop struct {
+ Depth int
+ V string
+ }
+)
+
+// exprf parses a Go expression generated from fmt.Sprintf, panicking if an
+// error occurs.
+func exprf(format string, a ...interface{}) ast.Expr {
+ src := fmt.Sprintf(format, a...)
+ expr, err := parser.ParseExpr(src)
+ if err != nil {
+ log.Fatalf("expr parse error on %q: %v", src, err)
+ }
+ return expr
+}
+
+// stmtf parses a Go statement generated from fmt.Sprintf. This function is only
+// meant for simple statements that don't have a custom Statement node declared
+// in this package, such as ast.ReturnStmt or ast.ExprStmt.
+func stmtf(format string, a ...interface{}) Statement {
+ src := fmt.Sprintf(format, a...)
+ fsrc := "package p\nfunc _() {\n" + src + "\n}\n"
+ file, err := parser.ParseFile(token.NewFileSet(), "", fsrc, 0)
+ if err != nil {
+ log.Fatalf("stmt parse error on %q: %v", src, err)
+ }
+ return file.Decls[0].(*ast.FuncDecl).Body.List[0]
+}
+
+// declf constructs a simple "name := value" declaration, using exprf for its
+// value.
+func declf(name, format string, a ...interface{}) *Declare {
+ return &Declare{name, exprf(format, a...)}
+}
+
+// breakf constructs a simple "if cond { break }" statement, using exprf for its
+// condition.
+func breakf(format string, a ...interface{}) *CondBreak {
+ return &CondBreak{Cond: exprf(format, a...)}
+}
+
+func genBlockRewrite(rule Rule, arch arch, data blockData) *RuleRewrite {
+ rr := &RuleRewrite{Loc: rule.Loc}
+ rr.Match, rr.Cond, rr.Result = rule.parse()
+ _, _, auxint, aux, s := extract(rr.Match) // remove parens, then split
+
+ // check match of control values
+ if len(s) < data.controls {
+ log.Fatalf("incorrect number of arguments in %s, got %v wanted at least %v", rule, len(s), data.controls)
+ }
+ controls := s[:data.controls]
+ pos := make([]string, data.controls)
+ for i, arg := range controls {
+ cname := fmt.Sprintf("b.Controls[%v]", i)
+ if strings.Contains(arg, "(") {
+ vname, expr := splitNameExpr(arg)
+ if vname == "" {
+ vname = fmt.Sprintf("v_%v", i)
+ }
+ rr.add(declf(vname, cname))
+ p, op := genMatch0(rr, arch, expr, vname, nil, false) // TODO: pass non-nil cnt?
+ if op != "" {
+ check := fmt.Sprintf("%s.Op == %s", cname, op)
+ if rr.Check == "" {
+ rr.Check = check
+ } else {
+ rr.Check += " && " + check
+ }
+ }
+ if p == "" {
+ p = vname + ".Pos"
+ }
+ pos[i] = p
+ } else {
+ rr.add(declf(arg, cname))
+ pos[i] = arg + ".Pos"
+ }
+ }
+ for _, e := range []struct {
+ name, field, dclType string
+ }{
+ {auxint, "AuxInt", data.auxIntType()},
+ {aux, "Aux", data.auxType()},
+ } {
+ if e.name == "" {
+ continue
+ }
+
+ if e.dclType == "" {
+ log.Fatalf("op %s has no declared type for %s", data.name, e.field)
+ }
+ if !token.IsIdentifier(e.name) || rr.declared(e.name) {
+ rr.add(breakf("%sTo%s(b.%s) != %s", unTitle(e.field), title(e.dclType), e.field, e.name))
+ } else {
+ rr.add(declf(e.name, "%sTo%s(b.%s)", unTitle(e.field), title(e.dclType), e.field))
+ }
+ }
+ if rr.Cond != "" {
+ rr.add(breakf("!(%s)", rr.Cond))
+ }
+
+ // Rule matches. Generate result.
+ outop, _, auxint, aux, t := extract(rr.Result) // remove parens, then split
+ blockName, outdata := getBlockInfo(outop, arch)
+ if len(t) < outdata.controls {
+ log.Fatalf("incorrect number of output arguments in %s, got %v wanted at least %v", rule, len(s), outdata.controls)
+ }
+
+ // Check if newsuccs is the same set as succs.
+ succs := s[data.controls:]
+ newsuccs := t[outdata.controls:]
+ m := map[string]bool{}
+ for _, succ := range succs {
+ if m[succ] {
+ log.Fatalf("can't have a repeat successor name %s in %s", succ, rule)
+ }
+ m[succ] = true
+ }
+ for _, succ := range newsuccs {
+ if !m[succ] {
+ log.Fatalf("unknown successor %s in %s", succ, rule)
+ }
+ delete(m, succ)
+ }
+ if len(m) != 0 {
+ log.Fatalf("unmatched successors %v in %s", m, rule)
+ }
+
+ var genControls [2]string
+ for i, control := range t[:outdata.controls] {
+ // Select a source position for any new control values.
+ // TODO: does it always make sense to use the source position
+ // of the original control values or should we be using the
+ // block's source position in some cases?
+ newpos := "b.Pos" // default to block's source position
+ if i < len(pos) && pos[i] != "" {
+ // Use the previous control value's source position.
+ newpos = pos[i]
+ }
+
+ // Generate a new control value (or copy an existing value).
+ genControls[i] = genResult0(rr, arch, control, false, false, newpos, nil)
+ }
+ switch outdata.controls {
+ case 0:
+ rr.add(stmtf("b.Reset(%s)", blockName))
+ case 1:
+ rr.add(stmtf("b.resetWithControl(%s, %s)", blockName, genControls[0]))
+ case 2:
+ rr.add(stmtf("b.resetWithControl2(%s, %s, %s)", blockName, genControls[0], genControls[1]))
+ default:
+ log.Fatalf("too many controls: %d", outdata.controls)
+ }
+
+ if auxint != "" {
+ // Make sure auxint value has the right type.
+ rr.add(stmtf("b.AuxInt = %sToAuxInt(%s)", unTitle(outdata.auxIntType()), auxint))
+ }
+ if aux != "" {
+ // Make sure aux value has the right type.
+ rr.add(stmtf("b.Aux = %sToAux(%s)", unTitle(outdata.auxType()), aux))
+ }
+
+ succChanged := false
+ for i := 0; i < len(succs); i++ {
+ if succs[i] != newsuccs[i] {
+ succChanged = true
+ }
+ }
+ if succChanged {
+ if len(succs) != 2 {
+ log.Fatalf("changed successors, len!=2 in %s", rule)
+ }
+ if succs[0] != newsuccs[1] || succs[1] != newsuccs[0] {
+ log.Fatalf("can only handle swapped successors in %s", rule)
+ }
+ rr.add(stmtf("b.swapSuccessors()"))
+ }
+
+ if *genLog {
+ rr.add(stmtf("logRule(%q)", rule.Loc))
+ }
+ return rr
+}
+
+// genMatch returns the variable whose source position should be used for the
+// result (or "" if no opinion), and a boolean that reports whether the match can fail.
+func genMatch(rr *RuleRewrite, arch arch, match string, pregenTop bool) (pos, checkOp string) {
+ cnt := varCount(rr)
+ return genMatch0(rr, arch, match, "v", cnt, pregenTop)
+}
+
+func genMatch0(rr *RuleRewrite, arch arch, match, v string, cnt map[string]int, pregenTop bool) (pos, checkOp string) {
+ if match[0] != '(' || match[len(match)-1] != ')' {
+ log.Fatalf("%s: non-compound expr in genMatch0: %q", rr.Loc, match)
+ }
+ op, oparch, typ, auxint, aux, args := parseValue(match, arch, rr.Loc)
+
+ checkOp = fmt.Sprintf("Op%s%s", oparch, op.name)
+
+ if op.faultOnNilArg0 || op.faultOnNilArg1 {
+ // Prefer the position of an instruction which could fault.
+ pos = v + ".Pos"
+ }
+
+ // If the last argument is ___, it means "don't care about trailing arguments, really"
+ // The likely/intended use is for rewrites that are too tricky to express in the existing pattern language
+ // Do a length check early because long patterns fed short (ultimately not-matching) inputs will
+ // do an indexing error in pattern-matching.
+ if op.argLength == -1 {
+ l := len(args)
+ if l == 0 || args[l-1] != "___" {
+ rr.add(breakf("len(%s.Args) != %d", v, l))
+ } else if l > 1 && args[l-1] == "___" {
+ rr.add(breakf("len(%s.Args) < %d", v, l-1))
+ }
+ }
+
+ for _, e := range []struct {
+ name, field, dclType string
+ }{
+ {typ, "Type", "*types.Type"},
+ {auxint, "AuxInt", op.auxIntType()},
+ {aux, "Aux", op.auxType()},
+ } {
+ if e.name == "" {
+ continue
+ }
+
+ if e.dclType == "" {
+ log.Fatalf("op %s has no declared type for %s", op.name, e.field)
+ }
+ if !token.IsIdentifier(e.name) || rr.declared(e.name) {
+ switch e.field {
+ case "Aux":
+ rr.add(breakf("auxTo%s(%s.%s) != %s", title(e.dclType), v, e.field, e.name))
+ case "AuxInt":
+ rr.add(breakf("auxIntTo%s(%s.%s) != %s", title(e.dclType), v, e.field, e.name))
+ case "Type":
+ rr.add(breakf("%s.%s != %s", v, e.field, e.name))
+ }
+ } else {
+ switch e.field {
+ case "Aux":
+ rr.add(declf(e.name, "auxTo%s(%s.%s)", title(e.dclType), v, e.field))
+ case "AuxInt":
+ rr.add(declf(e.name, "auxIntTo%s(%s.%s)", title(e.dclType), v, e.field))
+ case "Type":
+ rr.add(declf(e.name, "%s.%s", v, e.field))
+ }
+ }
+ }
+
+ commutative := op.commutative
+ if commutative {
+ if args[0] == args[1] {
+ // When we have (Add x x), for any x,
+ // even if there are other uses of x besides these two,
+ // and even if x is not a variable,
+ // we can skip the commutative match.
+ commutative = false
+ }
+ if cnt[args[0]] == 1 && cnt[args[1]] == 1 {
+ // When we have (Add x y) with no other uses
+ // of x and y in the matching rule and condition,
+ // then we can skip the commutative match (Add y x).
+ commutative = false
+ }
+ }
+
+ if !pregenTop {
+ // Access last argument first to minimize bounds checks.
+ for n := len(args) - 1; n > 0; n-- {
+ a := args[n]
+ if a == "_" {
+ continue
+ }
+ if !rr.declared(a) && token.IsIdentifier(a) && !(commutative && len(args) == 2) {
+ rr.add(declf(a, "%s.Args[%d]", v, n))
+ // delete the last argument so it is not reprocessed
+ args = args[:n]
+ } else {
+ rr.add(stmtf("_ = %s.Args[%d]", v, n))
+ }
+ break
+ }
+ }
+ if commutative && !pregenTop {
+ for i := 0; i <= 1; i++ {
+ vname := fmt.Sprintf("%s_%d", v, i)
+ rr.add(declf(vname, "%s.Args[%d]", v, i))
+ }
+ }
+ if commutative {
+ rr.add(StartCommuteLoop{rr.CommuteDepth, v})
+ rr.CommuteDepth++
+ }
+ for i, arg := range args {
+ if arg == "_" {
+ continue
+ }
+ var rhs string
+ if (commutative && i < 2) || pregenTop {
+ rhs = fmt.Sprintf("%s_%d", v, i)
+ } else {
+ rhs = fmt.Sprintf("%s.Args[%d]", v, i)
+ }
+ if !strings.Contains(arg, "(") {
+ // leaf variable
+ if rr.declared(arg) {
+ // variable already has a definition. Check whether
+ // the old definition and the new definition match.
+ // For example, (add x x). Equality is just pointer equality
+ // on Values (so cse is important to do before lowering).
+ rr.add(breakf("%s != %s", arg, rhs))
+ } else {
+ if arg != rhs {
+ rr.add(declf(arg, "%s", rhs))
+ }
+ }
+ continue
+ }
+ // compound sexpr
+ argname, expr := splitNameExpr(arg)
+ if argname == "" {
+ argname = fmt.Sprintf("%s_%d", v, i)
+ }
+ if argname == "b" {
+ log.Fatalf("don't name args 'b', it is ambiguous with blocks")
+ }
+
+ if argname != rhs {
+ rr.add(declf(argname, "%s", rhs))
+ }
+ bexpr := exprf("%s.Op != addLater", argname)
+ rr.add(&CondBreak{Cond: bexpr})
+ argPos, argCheckOp := genMatch0(rr, arch, expr, argname, cnt, false)
+ bexpr.(*ast.BinaryExpr).Y.(*ast.Ident).Name = argCheckOp
+
+ if argPos != "" {
+ // Keep the argument in preference to the parent, as the
+ // argument is normally earlier in program flow.
+ // Keep the argument in preference to an earlier argument,
+ // as that prefers the memory argument which is also earlier
+ // in the program flow.
+ pos = argPos
+ }
+ }
+
+ return pos, checkOp
+}
+
+func genResult(rr *RuleRewrite, arch arch, result, pos string) {
+ move := result[0] == '@'
+ if move {
+ // parse @block directive
+ s := strings.SplitN(result[1:], " ", 2)
+ rr.add(stmtf("b = %s", s[0]))
+ result = s[1]
+ }
+ cse := make(map[string]string)
+ genResult0(rr, arch, result, true, move, pos, cse)
+}
+
+func genResult0(rr *RuleRewrite, arch arch, result string, top, move bool, pos string, cse map[string]string) string {
+ resname, expr := splitNameExpr(result)
+ result = expr
+ // TODO: when generating a constant result, use f.constVal to avoid
+ // introducing copies just to clean them up again.
+ if result[0] != '(' {
+ // variable
+ if top {
+ // It in not safe in general to move a variable between blocks
+ // (and particularly not a phi node).
+ // Introduce a copy.
+ rr.add(stmtf("v.copyOf(%s)", result))
+ }
+ return result
+ }
+
+ w := normalizeWhitespace(result)
+ if prev := cse[w]; prev != "" {
+ return prev
+ }
+
+ op, oparch, typ, auxint, aux, args := parseValue(result, arch, rr.Loc)
+
+ // Find the type of the variable.
+ typeOverride := typ != ""
+ if typ == "" && op.typ != "" {
+ typ = typeName(op.typ)
+ }
+
+ v := "v"
+ if top && !move {
+ rr.add(stmtf("v.reset(Op%s%s)", oparch, op.name))
+ if typeOverride {
+ rr.add(stmtf("v.Type = %s", typ))
+ }
+ } else {
+ if typ == "" {
+ log.Fatalf("sub-expression %s (op=Op%s%s) at %s must have a type", result, oparch, op.name, rr.Loc)
+ }
+ if resname == "" {
+ v = fmt.Sprintf("v%d", rr.Alloc)
+ } else {
+ v = resname
+ }
+ rr.Alloc++
+ rr.add(declf(v, "b.NewValue0(%s, Op%s%s, %s)", pos, oparch, op.name, typ))
+ if move && top {
+ // Rewrite original into a copy
+ rr.add(stmtf("v.copyOf(%s)", v))
+ }
+ }
+
+ if auxint != "" {
+ // Make sure auxint value has the right type.
+ rr.add(stmtf("%s.AuxInt = %sToAuxInt(%s)", v, unTitle(op.auxIntType()), auxint))
+ }
+ if aux != "" {
+ // Make sure aux value has the right type.
+ rr.add(stmtf("%s.Aux = %sToAux(%s)", v, unTitle(op.auxType()), aux))
+ }
+ all := new(strings.Builder)
+ for i, arg := range args {
+ x := genResult0(rr, arch, arg, false, move, pos, cse)
+ if i > 0 {
+ all.WriteString(", ")
+ }
+ all.WriteString(x)
+ }
+ switch len(args) {
+ case 0:
+ case 1:
+ rr.add(stmtf("%s.AddArg(%s)", v, all.String()))
+ default:
+ rr.add(stmtf("%s.AddArg%d(%s)", v, len(args), all.String()))
+ }
+
+ if cse != nil {
+ cse[w] = v
+ }
+ return v
+}
+
+func split(s string) []string {
+ var r []string
+
+outer:
+ for s != "" {
+ d := 0 // depth of ({[<
+ var open, close byte // opening and closing markers ({[< or )}]>
+ nonsp := false // found a non-space char so far
+ for i := 0; i < len(s); i++ {
+ switch {
+ case d == 0 && s[i] == '(':
+ open, close = '(', ')'
+ d++
+ case d == 0 && s[i] == '<':
+ open, close = '<', '>'
+ d++
+ case d == 0 && s[i] == '[':
+ open, close = '[', ']'
+ d++
+ case d == 0 && s[i] == '{':
+ open, close = '{', '}'
+ d++
+ case d == 0 && (s[i] == ' ' || s[i] == '\t'):
+ if nonsp {
+ r = append(r, strings.TrimSpace(s[:i]))
+ s = s[i:]
+ continue outer
+ }
+ case d > 0 && s[i] == open:
+ d++
+ case d > 0 && s[i] == close:
+ d--
+ default:
+ nonsp = true
+ }
+ }
+ if d != 0 {
+ log.Fatalf("imbalanced expression: %q", s)
+ }
+ if nonsp {
+ r = append(r, strings.TrimSpace(s))
+ }
+ break
+ }
+ return r
+}
+
+// isBlock reports whether this op is a block opcode.
+func isBlock(name string, arch arch) bool {
+ for _, b := range genericBlocks {
+ if b.name == name {
+ return true
+ }
+ }
+ for _, b := range arch.blocks {
+ if b.name == name {
+ return true
+ }
+ }
+ return false
+}
+
+func extract(val string) (op, typ, auxint, aux string, args []string) {
+ val = val[1 : len(val)-1] // remove ()
+
+ // Split val up into regions.
+ // Split by spaces/tabs, except those contained in (), {}, [], or <>.
+ s := split(val)
+
+ // Extract restrictions and args.
+ op = s[0]
+ for _, a := range s[1:] {
+ switch a[0] {
+ case '<':
+ typ = a[1 : len(a)-1] // remove <>
+ case '[':
+ auxint = a[1 : len(a)-1] // remove []
+ case '{':
+ aux = a[1 : len(a)-1] // remove {}
+ default:
+ args = append(args, a)
+ }
+ }
+ return
+}
+
+// parseValue parses a parenthesized value from a rule.
+// The value can be from the match or the result side.
+// It returns the op and unparsed strings for typ, auxint, and aux restrictions and for all args.
+// oparch is the architecture that op is located in, or "" for generic.
+func parseValue(val string, arch arch, loc string) (op opData, oparch, typ, auxint, aux string, args []string) {
+ // Resolve the op.
+ var s string
+ s, typ, auxint, aux, args = extract(val)
+
+ // match reports whether x is a good op to select.
+ // If strict is true, rule generation might succeed.
+ // If strict is false, rule generation has failed,
+ // but we're trying to generate a useful error.
+ // Doing strict=true then strict=false allows
+ // precise op matching while retaining good error messages.
+ match := func(x opData, strict bool, archname string) bool {
+ if x.name != s {
+ return false
+ }
+ if x.argLength != -1 && int(x.argLength) != len(args) && (len(args) != 1 || args[0] != "...") {
+ if strict {
+ return false
+ }
+ log.Printf("%s: op %s (%s) should have %d args, has %d", loc, s, archname, x.argLength, len(args))
+ }
+ return true
+ }
+
+ for _, x := range genericOps {
+ if match(x, true, "generic") {
+ op = x
+ break
+ }
+ }
+ for _, x := range arch.ops {
+ if arch.name != "generic" && match(x, true, arch.name) {
+ if op.name != "" {
+ log.Fatalf("%s: matches for op %s found in both generic and %s", loc, op.name, arch.name)
+ }
+ op = x
+ oparch = arch.name
+ break
+ }
+ }
+
+ if op.name == "" {
+ // Failed to find the op.
+ // Run through everything again with strict=false
+ // to generate useful diagnosic messages before failing.
+ for _, x := range genericOps {
+ match(x, false, "generic")
+ }
+ for _, x := range arch.ops {
+ match(x, false, arch.name)
+ }
+ log.Fatalf("%s: unknown op %s", loc, s)
+ }
+
+ // Sanity check aux, auxint.
+ if auxint != "" && !opHasAuxInt(op) {
+ log.Fatalf("%s: op %s %s can't have auxint", loc, op.name, op.aux)
+ }
+ if aux != "" && !opHasAux(op) {
+ log.Fatalf("%s: op %s %s can't have aux", loc, op.name, op.aux)
+ }
+ return
+}
+
+func opHasAuxInt(op opData) bool {
+ switch op.aux {
+ case "Bool", "Int8", "Int16", "Int32", "Int64", "Int128", "UInt8", "Float32", "Float64",
+ "SymOff", "CallOff", "SymValAndOff", "TypSize", "ARM64BitField", "FlagConstant", "CCop":
+ return true
+ }
+ return false
+}
+
+func opHasAux(op opData) bool {
+ switch op.aux {
+ case "String", "Sym", "SymOff", "Call", "CallOff", "SymValAndOff", "Typ", "TypSize",
+ "S390XCCMask", "S390XRotateParams":
+ return true
+ }
+ return false
+}
+
+// splitNameExpr splits s-expr arg, possibly prefixed by "name:",
+// into name and the unprefixed expression.
+// For example, "x:(Foo)" yields "x", "(Foo)",
+// and "(Foo)" yields "", "(Foo)".
+func splitNameExpr(arg string) (name, expr string) {
+ colon := strings.Index(arg, ":")
+ if colon < 0 {
+ return "", arg
+ }
+ openparen := strings.Index(arg, "(")
+ if openparen < 0 {
+ log.Fatalf("splitNameExpr(%q): colon but no open parens", arg)
+ }
+ if colon > openparen {
+ // colon is inside the parens, such as in "(Foo x:(Bar))".
+ return "", arg
+ }
+ return arg[:colon], arg[colon+1:]
+}
+
+func getBlockInfo(op string, arch arch) (name string, data blockData) {
+ for _, b := range genericBlocks {
+ if b.name == op {
+ return "Block" + op, b
+ }
+ }
+ for _, b := range arch.blocks {
+ if b.name == op {
+ return "Block" + arch.name + op, b
+ }
+ }
+ log.Fatalf("could not find block data for %s", op)
+ panic("unreachable")
+}
+
+// typeName returns the string to use to generate a type.
+func typeName(typ string) string {
+ if typ[0] == '(' {
+ ts := strings.Split(typ[1:len(typ)-1], ",")
+ if len(ts) != 2 {
+ log.Fatalf("Tuple expect 2 arguments")
+ }
+ return "types.NewTuple(" + typeName(ts[0]) + ", " + typeName(ts[1]) + ")"
+ }
+ switch typ {
+ case "Flags", "Mem", "Void", "Int128":
+ return "types.Type" + typ
+ default:
+ return "typ." + typ
+ }
+}
+
+// balance returns the number of unclosed '(' characters in s.
+// If a ')' appears without a corresponding '(', balance returns -1.
+func balance(s string) int {
+ balance := 0
+ for _, c := range s {
+ switch c {
+ case '(':
+ balance++
+ case ')':
+ balance--
+ if balance < 0 {
+ // don't allow ")(" to return 0
+ return -1
+ }
+ }
+ }
+ return balance
+}
+
+// findAllOpcode is a function to find the opcode portion of s-expressions.
+var findAllOpcode = regexp.MustCompile(`[(](\w+[|])+\w+[)]`).FindAllStringIndex
+
+// excludeFromExpansion reports whether the substring s[idx[0]:idx[1]] in a rule
+// should be disregarded as a candidate for | expansion.
+// It uses simple syntactic checks to see whether the substring
+// is inside an AuxInt expression or inside the && conditions.
+func excludeFromExpansion(s string, idx []int) bool {
+ left := s[:idx[0]]
+ if strings.LastIndexByte(left, '[') > strings.LastIndexByte(left, ']') {
+ // Inside an AuxInt expression.
+ return true
+ }
+ right := s[idx[1]:]
+ if strings.Contains(left, "&&") && strings.Contains(right, "=>") {
+ // Inside && conditions.
+ return true
+ }
+ return false
+}
+
+// expandOr converts a rule into multiple rules by expanding | ops.
+func expandOr(r string) []string {
+ // Find every occurrence of |-separated things.
+ // They look like MOV(B|W|L|Q|SS|SD)load or MOV(Q|L)loadidx(1|8).
+ // Generate rules selecting one case from each |-form.
+
+ // Count width of |-forms. They must match.
+ n := 1
+ for _, idx := range findAllOpcode(r, -1) {
+ if excludeFromExpansion(r, idx) {
+ continue
+ }
+ s := r[idx[0]:idx[1]]
+ c := strings.Count(s, "|") + 1
+ if c == 1 {
+ continue
+ }
+ if n > 1 && n != c {
+ log.Fatalf("'|' count doesn't match in %s: both %d and %d\n", r, n, c)
+ }
+ n = c
+ }
+ if n == 1 {
+ // No |-form in this rule.
+ return []string{r}
+ }
+ // Build each new rule.
+ res := make([]string, n)
+ for i := 0; i < n; i++ {
+ buf := new(strings.Builder)
+ x := 0
+ for _, idx := range findAllOpcode(r, -1) {
+ if excludeFromExpansion(r, idx) {
+ continue
+ }
+ buf.WriteString(r[x:idx[0]]) // write bytes we've skipped over so far
+ s := r[idx[0]+1 : idx[1]-1] // remove leading "(" and trailing ")"
+ buf.WriteString(strings.Split(s, "|")[i]) // write the op component for this rule
+ x = idx[1] // note that we've written more bytes
+ }
+ buf.WriteString(r[x:])
+ res[i] = buf.String()
+ }
+ return res
+}
+
+// varCount returns a map which counts the number of occurrences of
+// Value variables in the s-expression rr.Match and the Go expression rr.Cond.
+func varCount(rr *RuleRewrite) map[string]int {
+ cnt := map[string]int{}
+ varCount1(rr.Loc, rr.Match, cnt)
+ if rr.Cond != "" {
+ expr, err := parser.ParseExpr(rr.Cond)
+ if err != nil {
+ log.Fatalf("%s: failed to parse cond %q: %v", rr.Loc, rr.Cond, err)
+ }
+ ast.Inspect(expr, func(n ast.Node) bool {
+ if id, ok := n.(*ast.Ident); ok {
+ cnt[id.Name]++
+ }
+ return true
+ })
+ }
+ return cnt
+}
+
+func varCount1(loc, m string, cnt map[string]int) {
+ if m[0] == '<' || m[0] == '[' || m[0] == '{' {
+ return
+ }
+ if token.IsIdentifier(m) {
+ cnt[m]++
+ return
+ }
+ // Split up input.
+ name, expr := splitNameExpr(m)
+ if name != "" {
+ cnt[name]++
+ }
+ if expr[0] != '(' || expr[len(expr)-1] != ')' {
+ log.Fatalf("%s: non-compound expr in varCount1: %q", loc, expr)
+ }
+ s := split(expr[1 : len(expr)-1])
+ for _, arg := range s[1:] {
+ varCount1(loc, arg, cnt)
+ }
+}
+
+// normalizeWhitespace replaces 2+ whitespace sequences with a single space.
+func normalizeWhitespace(x string) string {
+ x = strings.Join(strings.Fields(x), " ")
+ x = strings.Replace(x, "( ", "(", -1)
+ x = strings.Replace(x, " )", ")", -1)
+ x = strings.Replace(x, "[ ", "[", -1)
+ x = strings.Replace(x, " ]", "]", -1)
+ x = strings.Replace(x, ")=>", ") =>", -1)
+ return x
+}
+
+// opIsCommutative reports whether op s is commutative.
+func opIsCommutative(op string, arch arch) bool {
+ for _, x := range genericOps {
+ if op == x.name {
+ if x.commutative {
+ return true
+ }
+ break
+ }
+ }
+ if arch.name != "generic" {
+ for _, x := range arch.ops {
+ if op == x.name {
+ if x.commutative {
+ return true
+ }
+ break
+ }
+ }
+ }
+ return false
+}
+
+func normalizeMatch(m string, arch arch) string {
+ if token.IsIdentifier(m) {
+ return m
+ }
+ op, typ, auxint, aux, args := extract(m)
+ if opIsCommutative(op, arch) {
+ if args[1] < args[0] {
+ args[0], args[1] = args[1], args[0]
+ }
+ }
+ s := new(strings.Builder)
+ fmt.Fprintf(s, "%s <%s> [%s] {%s}", op, typ, auxint, aux)
+ for _, arg := range args {
+ prefix, expr := splitNameExpr(arg)
+ fmt.Fprint(s, " ", prefix, normalizeMatch(expr, arch))
+ }
+ return s.String()
+}
+
+func parseEllipsisRules(rules []Rule, arch arch) (newop string, ok bool) {
+ if len(rules) != 1 {
+ for _, r := range rules {
+ if strings.Contains(r.Rule, "...") {
+ log.Fatalf("%s: found ellipsis in rule, but there are other rules with the same op", r.Loc)
+ }
+ }
+ return "", false
+ }
+ rule := rules[0]
+ match, cond, result := rule.parse()
+ if cond != "" || !isEllipsisValue(match) || !isEllipsisValue(result) {
+ if strings.Contains(rule.Rule, "...") {
+ log.Fatalf("%s: found ellipsis in non-ellipsis rule", rule.Loc)
+ }
+ checkEllipsisRuleCandidate(rule, arch)
+ return "", false
+ }
+ op, oparch, _, _, _, _ := parseValue(result, arch, rule.Loc)
+ return fmt.Sprintf("Op%s%s", oparch, op.name), true
+}
+
+// isEllipsisValue reports whether s is of the form (OpX ...).
+func isEllipsisValue(s string) bool {
+ if len(s) < 2 || s[0] != '(' || s[len(s)-1] != ')' {
+ return false
+ }
+ c := split(s[1 : len(s)-1])
+ if len(c) != 2 || c[1] != "..." {
+ return false
+ }
+ return true
+}
+
+func checkEllipsisRuleCandidate(rule Rule, arch arch) {
+ match, cond, result := rule.parse()
+ if cond != "" {
+ return
+ }
+ op, _, _, auxint, aux, args := parseValue(match, arch, rule.Loc)
+ var auxint2, aux2 string
+ var args2 []string
+ var usingCopy string
+ var eop opData
+ if result[0] != '(' {
+ // Check for (Foo x) => x, which can be converted to (Foo ...) => (Copy ...).
+ args2 = []string{result}
+ usingCopy = " using Copy"
+ } else {
+ eop, _, _, auxint2, aux2, args2 = parseValue(result, arch, rule.Loc)
+ }
+ // Check that all restrictions in match are reproduced exactly in result.
+ if aux != aux2 || auxint != auxint2 || len(args) != len(args2) {
+ return
+ }
+ if strings.Contains(rule.Rule, "=>") && op.aux != eop.aux {
+ return
+ }
+ for i := range args {
+ if args[i] != args2[i] {
+ return
+ }
+ }
+ switch {
+ case opHasAux(op) && aux == "" && aux2 == "":
+ fmt.Printf("%s: rule silently zeros aux, either copy aux or explicitly zero\n", rule.Loc)
+ case opHasAuxInt(op) && auxint == "" && auxint2 == "":
+ fmt.Printf("%s: rule silently zeros auxint, either copy auxint or explicitly zero\n", rule.Loc)
+ default:
+ fmt.Printf("%s: possible ellipsis rule candidate%s: %q\n", rule.Loc, usingCopy, rule.Rule)
+ }
+}
+
+func opByName(arch arch, name string) opData {
+ name = name[2:]
+ for _, x := range genericOps {
+ if name == x.name {
+ return x
+ }
+ }
+ if arch.name != "generic" {
+ name = name[len(arch.name):]
+ for _, x := range arch.ops {
+ if name == x.name {
+ return x
+ }
+ }
+ }
+ log.Fatalf("failed to find op named %s in arch %s", name, arch.name)
+ panic("unreachable")
+}
+
+// auxType returns the Go type that this operation should store in its aux field.
+func (op opData) auxType() string {
+ switch op.aux {
+ case "String":
+ return "string"
+ case "Sym":
+ // Note: a Sym can be an *obj.LSym, a *gc.Node, or nil.
+ return "Sym"
+ case "SymOff":
+ return "Sym"
+ case "Call":
+ return "Call"
+ case "CallOff":
+ return "Call"
+ case "SymValAndOff":
+ return "Sym"
+ case "Typ":
+ return "*types.Type"
+ case "TypSize":
+ return "*types.Type"
+ case "S390XCCMask":
+ return "s390x.CCMask"
+ case "S390XRotateParams":
+ return "s390x.RotateParams"
+ default:
+ return "invalid"
+ }
+}
+
+// auxIntType returns the Go type that this operation should store in its auxInt field.
+func (op opData) auxIntType() string {
+ switch op.aux {
+ case "Bool":
+ return "bool"
+ case "Int8":
+ return "int8"
+ case "Int16":
+ return "int16"
+ case "Int32":
+ return "int32"
+ case "Int64":
+ return "int64"
+ case "Int128":
+ return "int128"
+ case "UInt8":
+ return "uint8"
+ case "Float32":
+ return "float32"
+ case "Float64":
+ return "float64"
+ case "CallOff":
+ return "int32"
+ case "SymOff":
+ return "int32"
+ case "SymValAndOff":
+ return "ValAndOff"
+ case "TypSize":
+ return "int64"
+ case "CCop":
+ return "Op"
+ case "FlagConstant":
+ return "flagConstant"
+ case "ARM64BitField":
+ return "arm64BitField"
+ default:
+ return "invalid"
+ }
+}
+
+// auxType returns the Go type that this block should store in its aux field.
+func (b blockData) auxType() string {
+ switch b.aux {
+ case "S390XCCMask", "S390XCCMaskInt8", "S390XCCMaskUint8":
+ return "s390x.CCMask"
+ case "S390XRotateParams":
+ return "s390x.RotateParams"
+ default:
+ return "invalid"
+ }
+}
+
+// auxIntType returns the Go type that this block should store in its auxInt field.
+func (b blockData) auxIntType() string {
+ switch b.aux {
+ case "S390XCCMaskInt8":
+ return "int8"
+ case "S390XCCMaskUint8":
+ return "uint8"
+ case "Int64":
+ return "int64"
+ default:
+ return "invalid"
+ }
+}
+
+func title(s string) string {
+ if i := strings.Index(s, "."); i >= 0 {
+ switch strings.ToLower(s[:i]) {
+ case "s390x": // keep arch prefix for clarity
+ s = s[:i] + s[i+1:]
+ default:
+ s = s[i+1:]
+ }
+ }
+ return strings.Title(s)
+}
+
+func unTitle(s string) string {
+ if i := strings.Index(s, "."); i >= 0 {
+ switch strings.ToLower(s[:i]) {
+ case "s390x": // keep arch prefix for clarity
+ s = s[:i] + s[i+1:]
+ default:
+ s = s[i+1:]
+ }
+ }
+ return strings.ToLower(s[:1]) + s[1:]
+}
diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go
new file mode 100644
index 0000000..c06b580
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/html.go
@@ -0,0 +1,1319 @@
+// 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 (
+ "bytes"
+ "cmd/internal/src"
+ "fmt"
+ "html"
+ exec "internal/execabs"
+ "io"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+)
+
+type HTMLWriter struct {
+ w io.WriteCloser
+ Func *Func
+ path string
+ dot *dotWriter
+ prevHash []byte
+ pendingPhases []string
+ pendingTitles []string
+}
+
+func NewHTMLWriter(path string, f *Func, cfgMask string) *HTMLWriter {
+ path = strings.Replace(path, "/", string(filepath.Separator), -1)
+ out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+ if err != nil {
+ f.Fatalf("%v", err)
+ }
+ reportPath := path
+ if !filepath.IsAbs(reportPath) {
+ pwd, err := os.Getwd()
+ if err != nil {
+ f.Fatalf("%v", err)
+ }
+ reportPath = filepath.Join(pwd, path)
+ }
+ html := HTMLWriter{
+ w: out,
+ Func: f,
+ path: reportPath,
+ dot: newDotWriter(cfgMask),
+ }
+ html.start()
+ return &html
+}
+
+// Fatalf reports an error and exits.
+func (w *HTMLWriter) Fatalf(msg string, args ...interface{}) {
+ fe := w.Func.Frontend()
+ fe.Fatalf(src.NoXPos, msg, args...)
+}
+
+// Logf calls the (w *HTMLWriter).Func's Logf method passing along a msg and args.
+func (w *HTMLWriter) Logf(msg string, args ...interface{}) {
+ w.Func.Logf(msg, args...)
+}
+
+func (w *HTMLWriter) start() {
+ if w == nil {
+ return
+ }
+ w.WriteString("<html>")
+ w.WriteString(`<head>
+<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<style>
+
+body {
+ font-size: 14px;
+ font-family: Arial, sans-serif;
+}
+
+h1 {
+ font-size: 18px;
+ display: inline-block;
+ margin: 0 1em .5em 0;
+}
+
+#helplink {
+ display: inline-block;
+}
+
+#help {
+ display: none;
+}
+
+.stats {
+ font-size: 60%;
+}
+
+table {
+ border: 1px solid black;
+ table-layout: fixed;
+ width: 300px;
+}
+
+th, td {
+ border: 1px solid black;
+ overflow: hidden;
+ width: 400px;
+ vertical-align: top;
+ padding: 5px;
+}
+
+td > h2 {
+ cursor: pointer;
+ font-size: 120%;
+ margin: 5px 0px 5px 0px;
+}
+
+td.collapsed {
+ font-size: 12px;
+ width: 12px;
+ border: 1px solid white;
+ padding: 2px;
+ cursor: pointer;
+ background: #fafafa;
+}
+
+td.collapsed div {
+ text-align: right;
+ transform: rotate(180deg);
+ writing-mode: vertical-lr;
+ white-space: pre;
+}
+
+code, pre, .lines, .ast {
+ font-family: Menlo, monospace;
+ font-size: 12px;
+}
+
+pre {
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+}
+
+.allow-x-scroll {
+ overflow-x: scroll;
+}
+
+.lines {
+ float: left;
+ overflow: hidden;
+ text-align: right;
+ margin-top: 7px;
+}
+
+.lines div {
+ padding-right: 10px;
+ color: gray;
+}
+
+div.line-number {
+ font-size: 12px;
+}
+
+.ast {
+ white-space: nowrap;
+}
+
+td.ssa-prog {
+ width: 600px;
+ word-wrap: break-word;
+}
+
+li {
+ list-style-type: none;
+}
+
+li.ssa-long-value {
+ text-indent: -2em; /* indent wrapped lines */
+}
+
+li.ssa-value-list {
+ display: inline;
+}
+
+li.ssa-start-block {
+ padding: 0;
+ margin: 0;
+}
+
+li.ssa-end-block {
+ padding: 0;
+ margin: 0;
+}
+
+ul.ssa-print-func {
+ padding-left: 0;
+}
+
+li.ssa-start-block button {
+ padding: 0 1em;
+ margin: 0;
+ border: none;
+ display: inline;
+ font-size: 14px;
+ float: right;
+}
+
+button:hover {
+ background-color: #eee;
+ cursor: pointer;
+}
+
+dl.ssa-gen {
+ padding-left: 0;
+}
+
+dt.ssa-prog-src {
+ padding: 0;
+ margin: 0;
+ float: left;
+ width: 4em;
+}
+
+dd.ssa-prog {
+ padding: 0;
+ margin-right: 0;
+ margin-left: 4em;
+}
+
+.dead-value {
+ color: gray;
+}
+
+.dead-block {
+ opacity: 0.5;
+}
+
+.depcycle {
+ font-style: italic;
+}
+
+.line-number {
+ font-size: 11px;
+}
+
+.no-line-number {
+ font-size: 11px;
+ color: gray;
+}
+
+.zoom {
+ position: absolute;
+ float: left;
+ white-space: nowrap;
+ background-color: #eee;
+}
+
+.zoom a:link, .zoom a:visited {
+ text-decoration: none;
+ color: blue;
+ font-size: 16px;
+ padding: 4px 2px;
+}
+
+svg {
+ cursor: default;
+ outline: 1px solid #eee;
+ width: 100%;
+}
+
+body.darkmode {
+ background-color: rgb(21, 21, 21);
+ color: rgb(230, 255, 255);
+ opacity: 100%;
+}
+
+td.darkmode {
+ background-color: rgb(21, 21, 21);
+ border: 1px solid gray;
+}
+
+body.darkmode table, th {
+ border: 1px solid gray;
+}
+
+body.darkmode text {
+ fill: white;
+}
+
+body.darkmode svg polygon:first-child {
+ fill: rgb(21, 21, 21);
+}
+
+.highlight-aquamarine { background-color: aquamarine; color: black; }
+.highlight-coral { background-color: coral; color: black; }
+.highlight-lightpink { background-color: lightpink; color: black; }
+.highlight-lightsteelblue { background-color: lightsteelblue; color: black; }
+.highlight-palegreen { background-color: palegreen; color: black; }
+.highlight-skyblue { background-color: skyblue; color: black; }
+.highlight-lightgray { background-color: lightgray; color: black; }
+.highlight-yellow { background-color: yellow; color: black; }
+.highlight-lime { background-color: lime; color: black; }
+.highlight-khaki { background-color: khaki; color: black; }
+.highlight-aqua { background-color: aqua; color: black; }
+.highlight-salmon { background-color: salmon; color: black; }
+
+/* Ensure all dead values/blocks continue to have gray font color in dark mode with highlights */
+.dead-value span.highlight-aquamarine,
+.dead-block.highlight-aquamarine,
+.dead-value span.highlight-coral,
+.dead-block.highlight-coral,
+.dead-value span.highlight-lightpink,
+.dead-block.highlight-lightpink,
+.dead-value span.highlight-lightsteelblue,
+.dead-block.highlight-lightsteelblue,
+.dead-value span.highlight-palegreen,
+.dead-block.highlight-palegreen,
+.dead-value span.highlight-skyblue,
+.dead-block.highlight-skyblue,
+.dead-value span.highlight-lightgray,
+.dead-block.highlight-lightgray,
+.dead-value span.highlight-yellow,
+.dead-block.highlight-yellow,
+.dead-value span.highlight-lime,
+.dead-block.highlight-lime,
+.dead-value span.highlight-khaki,
+.dead-block.highlight-khaki,
+.dead-value span.highlight-aqua,
+.dead-block.highlight-aqua,
+.dead-value span.highlight-salmon,
+.dead-block.highlight-salmon {
+ color: gray;
+}
+
+.outline-blue { outline: #2893ff solid 2px; }
+.outline-red { outline: red solid 2px; }
+.outline-blueviolet { outline: blueviolet solid 2px; }
+.outline-darkolivegreen { outline: darkolivegreen solid 2px; }
+.outline-fuchsia { outline: fuchsia solid 2px; }
+.outline-sienna { outline: sienna solid 2px; }
+.outline-gold { outline: gold solid 2px; }
+.outline-orangered { outline: orangered solid 2px; }
+.outline-teal { outline: teal solid 2px; }
+.outline-maroon { outline: maroon solid 2px; }
+.outline-black { outline: black solid 2px; }
+
+ellipse.outline-blue { stroke-width: 2px; stroke: #2893ff; }
+ellipse.outline-red { stroke-width: 2px; stroke: red; }
+ellipse.outline-blueviolet { stroke-width: 2px; stroke: blueviolet; }
+ellipse.outline-darkolivegreen { stroke-width: 2px; stroke: darkolivegreen; }
+ellipse.outline-fuchsia { stroke-width: 2px; stroke: fuchsia; }
+ellipse.outline-sienna { stroke-width: 2px; stroke: sienna; }
+ellipse.outline-gold { stroke-width: 2px; stroke: gold; }
+ellipse.outline-orangered { stroke-width: 2px; stroke: orangered; }
+ellipse.outline-teal { stroke-width: 2px; stroke: teal; }
+ellipse.outline-maroon { stroke-width: 2px; stroke: maroon; }
+ellipse.outline-black { stroke-width: 2px; stroke: black; }
+
+/* Capture alternative for outline-black and ellipse.outline-black when in dark mode */
+body.darkmode .outline-black { outline: gray solid 2px; }
+body.darkmode ellipse.outline-black { outline: gray solid 2px; }
+
+</style>
+
+<script type="text/javascript">
+
+// Contains phase names which are expanded by default. Other columns are collapsed.
+let expandedDefault = [
+ "start",
+ "deadcode",
+ "opt",
+ "lower",
+ "late-deadcode",
+ "regalloc",
+ "genssa",
+];
+if (history.state === null) {
+ history.pushState({expandedDefault}, "", location.href);
+}
+
+// ordered list of all available highlight colors
+var highlights = [
+ "highlight-aquamarine",
+ "highlight-coral",
+ "highlight-lightpink",
+ "highlight-lightsteelblue",
+ "highlight-palegreen",
+ "highlight-skyblue",
+ "highlight-lightgray",
+ "highlight-yellow",
+ "highlight-lime",
+ "highlight-khaki",
+ "highlight-aqua",
+ "highlight-salmon"
+];
+
+// state: which value is highlighted this color?
+var highlighted = {};
+for (var i = 0; i < highlights.length; i++) {
+ highlighted[highlights[i]] = "";
+}
+
+// ordered list of all available outline colors
+var outlines = [
+ "outline-blue",
+ "outline-red",
+ "outline-blueviolet",
+ "outline-darkolivegreen",
+ "outline-fuchsia",
+ "outline-sienna",
+ "outline-gold",
+ "outline-orangered",
+ "outline-teal",
+ "outline-maroon",
+ "outline-black"
+];
+
+// state: which value is outlined this color?
+var outlined = {};
+for (var i = 0; i < outlines.length; i++) {
+ outlined[outlines[i]] = "";
+}
+
+window.onload = function() {
+ if (history.state !== null) {
+ expandedDefault = history.state.expandedDefault;
+ }
+ if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
+ toggleDarkMode();
+ document.getElementById("dark-mode-button").checked = true;
+ }
+
+ var ssaElemClicked = function(elem, event, selections, selected) {
+ event.stopPropagation();
+
+ // find all values with the same name
+ var c = elem.classList.item(0);
+ var x = document.getElementsByClassName(c);
+
+ // if selected, remove selections from all of them
+ // otherwise, attempt to add
+
+ var remove = "";
+ for (var i = 0; i < selections.length; i++) {
+ var color = selections[i];
+ if (selected[color] == c) {
+ remove = color;
+ break;
+ }
+ }
+
+ if (remove != "") {
+ for (var i = 0; i < x.length; i++) {
+ x[i].classList.remove(remove);
+ }
+ selected[remove] = "";
+ return;
+ }
+
+ // we're adding a selection
+ // find first available color
+ var avail = "";
+ for (var i = 0; i < selections.length; i++) {
+ var color = selections[i];
+ if (selected[color] == "") {
+ avail = color;
+ break;
+ }
+ }
+ if (avail == "") {
+ alert("out of selection colors; go add more");
+ return;
+ }
+
+ // set that as the selection
+ for (var i = 0; i < x.length; i++) {
+ x[i].classList.add(avail);
+ }
+ selected[avail] = c;
+ };
+
+ var ssaValueClicked = function(event) {
+ ssaElemClicked(this, event, highlights, highlighted);
+ };
+
+ var ssaBlockClicked = function(event) {
+ ssaElemClicked(this, event, outlines, outlined);
+ };
+
+ var ssavalues = document.getElementsByClassName("ssa-value");
+ for (var i = 0; i < ssavalues.length; i++) {
+ ssavalues[i].addEventListener('click', ssaValueClicked);
+ }
+
+ var ssalongvalues = document.getElementsByClassName("ssa-long-value");
+ for (var i = 0; i < ssalongvalues.length; i++) {
+ // don't attach listeners to li nodes, just the spans they contain
+ if (ssalongvalues[i].nodeName == "SPAN") {
+ ssalongvalues[i].addEventListener('click', ssaValueClicked);
+ }
+ }
+
+ var ssablocks = document.getElementsByClassName("ssa-block");
+ for (var i = 0; i < ssablocks.length; i++) {
+ ssablocks[i].addEventListener('click', ssaBlockClicked);
+ }
+
+ var lines = document.getElementsByClassName("line-number");
+ for (var i = 0; i < lines.length; i++) {
+ lines[i].addEventListener('click', ssaValueClicked);
+ }
+
+
+ function toggler(phase) {
+ return function() {
+ toggle_cell(phase+'-col');
+ toggle_cell(phase+'-exp');
+ const i = expandedDefault.indexOf(phase);
+ if (i !== -1) {
+ expandedDefault.splice(i, 1);
+ } else {
+ expandedDefault.push(phase);
+ }
+ history.pushState({expandedDefault}, "", location.href);
+ };
+ }
+
+ function toggle_cell(id) {
+ var e = document.getElementById(id);
+ if (e.style.display == 'table-cell') {
+ e.style.display = 'none';
+ } else {
+ e.style.display = 'table-cell';
+ }
+ }
+
+ // Go through all columns and collapse needed phases.
+ const td = document.getElementsByTagName("td");
+ for (let i = 0; i < td.length; i++) {
+ const id = td[i].id;
+ const phase = id.substr(0, id.length-4);
+ let show = expandedDefault.indexOf(phase) !== -1
+
+ // If show == false, check to see if this is a combined column (multiple phases).
+ // If combined, check each of the phases to see if they are in our expandedDefaults.
+ // If any are found, that entire combined column gets shown.
+ if (!show) {
+ const combined = phase.split('--+--');
+ const len = combined.length;
+ if (len > 1) {
+ for (let i = 0; i < len; i++) {
+ const num = expandedDefault.indexOf(combined[i]);
+ if (num !== -1) {
+ expandedDefault.splice(num, 1);
+ if (expandedDefault.indexOf(phase) === -1) {
+ expandedDefault.push(phase);
+ show = true;
+ }
+ }
+ }
+ }
+ }
+ if (id.endsWith("-exp")) {
+ const h2Els = td[i].getElementsByTagName("h2");
+ const len = h2Els.length;
+ if (len > 0) {
+ for (let i = 0; i < len; i++) {
+ h2Els[i].addEventListener('click', toggler(phase));
+ }
+ }
+ } else {
+ td[i].addEventListener('click', toggler(phase));
+ }
+ if (id.endsWith("-col") && show || id.endsWith("-exp") && !show) {
+ td[i].style.display = 'none';
+ continue;
+ }
+ td[i].style.display = 'table-cell';
+ }
+
+ // find all svg block nodes, add their block classes
+ var nodes = document.querySelectorAll('*[id^="graph_node_"]');
+ for (var i = 0; i < nodes.length; i++) {
+ var node = nodes[i];
+ var name = node.id.toString();
+ var block = name.substring(name.lastIndexOf("_")+1);
+ node.classList.remove("node");
+ node.classList.add(block);
+ node.addEventListener('click', ssaBlockClicked);
+ var ellipse = node.getElementsByTagName('ellipse')[0];
+ ellipse.classList.add(block);
+ ellipse.addEventListener('click', ssaBlockClicked);
+ }
+
+ // make big graphs smaller
+ var targetScale = 0.5;
+ var nodes = document.querySelectorAll('*[id^="svg_graph_"]');
+ // TODO: Implement smarter auto-zoom using the viewBox attribute
+ // and in case of big graphs set the width and height of the svg graph to
+ // maximum allowed.
+ for (var i = 0; i < nodes.length; i++) {
+ var node = nodes[i];
+ var name = node.id.toString();
+ var phase = name.substring(name.lastIndexOf("_")+1);
+ var gNode = document.getElementById("g_graph_"+phase);
+ var scale = gNode.transform.baseVal.getItem(0).matrix.a;
+ if (scale > targetScale) {
+ node.width.baseVal.value *= targetScale / scale;
+ node.height.baseVal.value *= targetScale / scale;
+ }
+ }
+};
+
+function toggle_visibility(id) {
+ var e = document.getElementById(id);
+ if (e.style.display == 'block') {
+ e.style.display = 'none';
+ } else {
+ e.style.display = 'block';
+ }
+}
+
+function hideBlock(el) {
+ var es = el.parentNode.parentNode.getElementsByClassName("ssa-value-list");
+ if (es.length===0)
+ return;
+ var e = es[0];
+ if (e.style.display === 'block' || e.style.display === '') {
+ e.style.display = 'none';
+ el.innerHTML = '+';
+ } else {
+ e.style.display = 'block';
+ el.innerHTML = '-';
+ }
+}
+
+// TODO: scale the graph with the viewBox attribute.
+function graphReduce(id) {
+ var node = document.getElementById(id);
+ if (node) {
+ node.width.baseVal.value *= 0.9;
+ node.height.baseVal.value *= 0.9;
+ }
+ return false;
+}
+
+function graphEnlarge(id) {
+ var node = document.getElementById(id);
+ if (node) {
+ node.width.baseVal.value *= 1.1;
+ node.height.baseVal.value *= 1.1;
+ }
+ return false;
+}
+
+function makeDraggable(event) {
+ var svg = event.target;
+ if (window.PointerEvent) {
+ svg.addEventListener('pointerdown', startDrag);
+ svg.addEventListener('pointermove', drag);
+ svg.addEventListener('pointerup', endDrag);
+ svg.addEventListener('pointerleave', endDrag);
+ } else {
+ svg.addEventListener('mousedown', startDrag);
+ svg.addEventListener('mousemove', drag);
+ svg.addEventListener('mouseup', endDrag);
+ svg.addEventListener('mouseleave', endDrag);
+ }
+
+ var point = svg.createSVGPoint();
+ var isPointerDown = false;
+ var pointerOrigin;
+ var viewBox = svg.viewBox.baseVal;
+
+ function getPointFromEvent (event) {
+ point.x = event.clientX;
+ point.y = event.clientY;
+
+ // We get the current transformation matrix of the SVG and we inverse it
+ var invertedSVGMatrix = svg.getScreenCTM().inverse();
+ return point.matrixTransform(invertedSVGMatrix);
+ }
+
+ function startDrag(event) {
+ isPointerDown = true;
+ pointerOrigin = getPointFromEvent(event);
+ }
+
+ function drag(event) {
+ if (!isPointerDown) {
+ return;
+ }
+ event.preventDefault();
+
+ var pointerPosition = getPointFromEvent(event);
+ viewBox.x -= (pointerPosition.x - pointerOrigin.x);
+ viewBox.y -= (pointerPosition.y - pointerOrigin.y);
+ }
+
+ function endDrag(event) {
+ isPointerDown = false;
+ }
+}
+
+function toggleDarkMode() {
+ document.body.classList.toggle('darkmode');
+
+ // Collect all of the "collapsed" elements and apply dark mode on each collapsed column
+ const collapsedEls = document.getElementsByClassName('collapsed');
+ const len = collapsedEls.length;
+
+ for (let i = 0; i < len; i++) {
+ collapsedEls[i].classList.toggle('darkmode');
+ }
+
+ // Collect and spread the appropriate elements from all of the svgs on the page into one array
+ const svgParts = [
+ ...document.querySelectorAll('path'),
+ ...document.querySelectorAll('ellipse'),
+ ...document.querySelectorAll('polygon'),
+ ];
+
+ // Iterate over the svgParts specifically looking for white and black fill/stroke to be toggled.
+ // The verbose conditional is intentional here so that we do not mutate any svg path, ellipse, or polygon that is of any color other than white or black.
+ svgParts.forEach(el => {
+ if (el.attributes.stroke.value === 'white') {
+ el.attributes.stroke.value = 'black';
+ } else if (el.attributes.stroke.value === 'black') {
+ el.attributes.stroke.value = 'white';
+ }
+ if (el.attributes.fill.value === 'white') {
+ el.attributes.fill.value = 'black';
+ } else if (el.attributes.fill.value === 'black') {
+ el.attributes.fill.value = 'white';
+ }
+ });
+}
+
+</script>
+
+</head>`)
+ w.WriteString("<body>")
+ w.WriteString("<h1>")
+ w.WriteString(html.EscapeString(w.Func.Name))
+ w.WriteString("</h1>")
+ w.WriteString(`
+<a href="#" onclick="toggle_visibility('help');return false;" id="helplink">help</a>
+<div id="help">
+
+<p>
+Click on a value or block to toggle highlighting of that value/block
+and its uses. (Values and blocks are highlighted by ID, and IDs of
+dead items may be reused, so not all highlights necessarily correspond
+to the clicked item.)
+</p>
+
+<p>
+Faded out values and blocks are dead code that has not been eliminated.
+</p>
+
+<p>
+Values printed in italics have a dependency cycle.
+</p>
+
+<p>
+<b>CFG</b>: Dashed edge is for unlikely branches. Blue color is for backward edges.
+Edge with a dot means that this edge follows the order in which blocks were laidout.
+</p>
+
+</div>
+<label for="dark-mode-button" style="margin-left: 15px; cursor: pointer;">darkmode</label>
+<input type="checkbox" onclick="toggleDarkMode();" id="dark-mode-button" style="cursor: pointer" />
+`)
+ w.WriteString("<table>")
+ w.WriteString("<tr>")
+}
+
+func (w *HTMLWriter) Close() {
+ if w == nil {
+ return
+ }
+ io.WriteString(w.w, "</tr>")
+ io.WriteString(w.w, "</table>")
+ io.WriteString(w.w, "</body>")
+ io.WriteString(w.w, "</html>")
+ w.w.Close()
+ fmt.Printf("dumped SSA to %v\n", w.path)
+}
+
+// WritePhase writes f in a column headed by title.
+// phase is used for collapsing columns and should be unique across the table.
+func (w *HTMLWriter) WritePhase(phase, title string) {
+ if w == nil {
+ return // avoid generating HTML just to discard it
+ }
+ hash := hashFunc(w.Func)
+ w.pendingPhases = append(w.pendingPhases, phase)
+ w.pendingTitles = append(w.pendingTitles, title)
+ if !bytes.Equal(hash, w.prevHash) {
+ w.flushPhases()
+ }
+ w.prevHash = hash
+}
+
+// flushPhases collects any pending phases and titles, writes them to the html, and resets the pending slices.
+func (w *HTMLWriter) flushPhases() {
+ phaseLen := len(w.pendingPhases)
+ if phaseLen == 0 {
+ return
+ }
+ phases := strings.Join(w.pendingPhases, " + ")
+ w.WriteMultiTitleColumn(
+ phases,
+ w.pendingTitles,
+ fmt.Sprintf("hash-%x", w.prevHash),
+ w.Func.HTML(w.pendingPhases[phaseLen-1], w.dot),
+ )
+ w.pendingPhases = w.pendingPhases[:0]
+ w.pendingTitles = w.pendingTitles[:0]
+}
+
+// FuncLines contains source code for a function to be displayed
+// in sources column.
+type FuncLines struct {
+ Filename string
+ StartLineno uint
+ Lines []string
+}
+
+// ByTopo sorts topologically: target function is on top,
+// followed by inlined functions sorted by filename and line numbers.
+type ByTopo []*FuncLines
+
+func (x ByTopo) Len() int { return len(x) }
+func (x ByTopo) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x ByTopo) Less(i, j int) bool {
+ a := x[i]
+ b := x[j]
+ if a.Filename == b.Filename {
+ return a.StartLineno < b.StartLineno
+ }
+ return a.Filename < b.Filename
+}
+
+// WriteSources writes lines as source code in a column headed by title.
+// phase is used for collapsing columns and should be unique across the table.
+func (w *HTMLWriter) WriteSources(phase string, all []*FuncLines) {
+ if w == nil {
+ return // avoid generating HTML just to discard it
+ }
+ var buf bytes.Buffer
+ fmt.Fprint(&buf, "<div class=\"lines\" style=\"width: 8%\">")
+ filename := ""
+ for _, fl := range all {
+ fmt.Fprint(&buf, "<div>&nbsp;</div>")
+ if filename != fl.Filename {
+ fmt.Fprint(&buf, "<div>&nbsp;</div>")
+ filename = fl.Filename
+ }
+ for i := range fl.Lines {
+ ln := int(fl.StartLineno) + i
+ fmt.Fprintf(&buf, "<div class=\"l%v line-number\">%v</div>", ln, ln)
+ }
+ }
+ fmt.Fprint(&buf, "</div><div style=\"width: 92%\"><pre>")
+ filename = ""
+ for _, fl := range all {
+ fmt.Fprint(&buf, "<div>&nbsp;</div>")
+ if filename != fl.Filename {
+ fmt.Fprintf(&buf, "<div><strong>%v</strong></div>", fl.Filename)
+ filename = fl.Filename
+ }
+ for i, line := range fl.Lines {
+ ln := int(fl.StartLineno) + i
+ var escaped string
+ if strings.TrimSpace(line) == "" {
+ escaped = "&nbsp;"
+ } else {
+ escaped = html.EscapeString(line)
+ }
+ fmt.Fprintf(&buf, "<div class=\"l%v line-number\">%v</div>", ln, escaped)
+ }
+ }
+ fmt.Fprint(&buf, "</pre></div>")
+ w.WriteColumn(phase, phase, "allow-x-scroll", buf.String())
+}
+
+func (w *HTMLWriter) WriteAST(phase string, buf *bytes.Buffer) {
+ if w == nil {
+ return // avoid generating HTML just to discard it
+ }
+ lines := strings.Split(buf.String(), "\n")
+ var out bytes.Buffer
+
+ fmt.Fprint(&out, "<div>")
+ for _, l := range lines {
+ l = strings.TrimSpace(l)
+ var escaped string
+ var lineNo string
+ if l == "" {
+ escaped = "&nbsp;"
+ } else {
+ if strings.HasPrefix(l, "buildssa") {
+ escaped = fmt.Sprintf("<b>%v</b>", l)
+ } else {
+ // Parse the line number from the format l(123).
+ idx := strings.Index(l, " l(")
+ if idx != -1 {
+ subl := l[idx+3:]
+ idxEnd := strings.Index(subl, ")")
+ if idxEnd != -1 {
+ if _, err := strconv.Atoi(subl[:idxEnd]); err == nil {
+ lineNo = subl[:idxEnd]
+ }
+ }
+ }
+ escaped = html.EscapeString(l)
+ }
+ }
+ if lineNo != "" {
+ fmt.Fprintf(&out, "<div class=\"l%v line-number ast\">%v</div>", lineNo, escaped)
+ } else {
+ fmt.Fprintf(&out, "<div class=\"ast\">%v</div>", escaped)
+ }
+ }
+ fmt.Fprint(&out, "</div>")
+ w.WriteColumn(phase, phase, "allow-x-scroll", out.String())
+}
+
+// WriteColumn writes raw HTML in a column headed by title.
+// It is intended for pre- and post-compilation log output.
+func (w *HTMLWriter) WriteColumn(phase, title, class, html string) {
+ w.WriteMultiTitleColumn(phase, []string{title}, class, html)
+}
+
+func (w *HTMLWriter) WriteMultiTitleColumn(phase string, titles []string, class, html string) {
+ if w == nil {
+ return
+ }
+ id := strings.Replace(phase, " ", "-", -1)
+ // collapsed column
+ w.Printf("<td id=\"%v-col\" class=\"collapsed\"><div>%v</div></td>", id, phase)
+
+ if class == "" {
+ w.Printf("<td id=\"%v-exp\">", id)
+ } else {
+ w.Printf("<td id=\"%v-exp\" class=\"%v\">", id, class)
+ }
+ for _, title := range titles {
+ w.WriteString("<h2>" + title + "</h2>")
+ }
+ w.WriteString(html)
+ w.WriteString("</td>\n")
+}
+
+func (w *HTMLWriter) Printf(msg string, v ...interface{}) {
+ if _, err := fmt.Fprintf(w.w, msg, v...); err != nil {
+ w.Fatalf("%v", err)
+ }
+}
+
+func (w *HTMLWriter) WriteString(s string) {
+ if _, err := io.WriteString(w.w, s); err != nil {
+ w.Fatalf("%v", err)
+ }
+}
+
+func (v *Value) HTML() string {
+ // TODO: Using the value ID as the class ignores the fact
+ // that value IDs get recycled and that some values
+ // are transmuted into other values.
+ s := v.String()
+ return fmt.Sprintf("<span class=\"%s ssa-value\">%s</span>", s, s)
+}
+
+func (v *Value) LongHTML() string {
+ // TODO: Any intra-value formatting?
+ // I'm wary of adding too much visual noise,
+ // but a little bit might be valuable.
+ // We already have visual noise in the form of punctuation
+ // maybe we could replace some of that with formatting.
+ s := fmt.Sprintf("<span class=\"%s ssa-long-value\">", v.String())
+
+ linenumber := "<span class=\"no-line-number\">(?)</span>"
+ if v.Pos.IsKnown() {
+ linenumber = fmt.Sprintf("<span class=\"l%v line-number\">(%s)</span>", v.Pos.LineNumber(), v.Pos.LineNumberHTML())
+ }
+
+ s += fmt.Sprintf("%s %s = %s", v.HTML(), linenumber, v.Op.String())
+
+ s += " &lt;" + html.EscapeString(v.Type.String()) + "&gt;"
+ s += html.EscapeString(v.auxString())
+ for _, a := range v.Args {
+ s += fmt.Sprintf(" %s", a.HTML())
+ }
+ r := v.Block.Func.RegAlloc
+ if int(v.ID) < len(r) && r[v.ID] != nil {
+ s += " : " + html.EscapeString(r[v.ID].String())
+ }
+ var names []string
+ for name, values := range v.Block.Func.NamedValues {
+ for _, value := range values {
+ if value == v {
+ names = append(names, name.String())
+ break // drop duplicates.
+ }
+ }
+ }
+ if len(names) != 0 {
+ s += " (" + strings.Join(names, ", ") + ")"
+ }
+
+ s += "</span>"
+ return s
+}
+
+func (b *Block) HTML() string {
+ // TODO: Using the value ID as the class ignores the fact
+ // that value IDs get recycled and that some values
+ // are transmuted into other values.
+ s := html.EscapeString(b.String())
+ return fmt.Sprintf("<span class=\"%s ssa-block\">%s</span>", s, s)
+}
+
+func (b *Block) LongHTML() string {
+ // TODO: improve this for HTML?
+ s := fmt.Sprintf("<span class=\"%s ssa-block\">%s</span>", html.EscapeString(b.String()), html.EscapeString(b.Kind.String()))
+ if b.Aux != nil {
+ s += html.EscapeString(fmt.Sprintf(" {%v}", b.Aux))
+ }
+ if t := b.AuxIntString(); t != "" {
+ s += html.EscapeString(fmt.Sprintf(" [%v]", t))
+ }
+ for _, c := range b.ControlValues() {
+ s += fmt.Sprintf(" %s", c.HTML())
+ }
+ if len(b.Succs) > 0 {
+ s += " &#8594;" // right arrow
+ for _, e := range b.Succs {
+ c := e.b
+ s += " " + c.HTML()
+ }
+ }
+ switch b.Likely {
+ case BranchUnlikely:
+ s += " (unlikely)"
+ case BranchLikely:
+ s += " (likely)"
+ }
+ if b.Pos.IsKnown() {
+ // TODO does not begin to deal with the full complexity of line numbers.
+ // Maybe we want a string/slice instead, of outer-inner when inlining.
+ s += fmt.Sprintf(" <span class=\"l%v line-number\">(%s)</span>", b.Pos.LineNumber(), b.Pos.LineNumberHTML())
+ }
+ return s
+}
+
+func (f *Func) HTML(phase string, dot *dotWriter) string {
+ buf := new(bytes.Buffer)
+ if dot != nil {
+ dot.writeFuncSVG(buf, phase, f)
+ }
+ fmt.Fprint(buf, "<code>")
+ p := htmlFuncPrinter{w: buf}
+ fprintFunc(p, f)
+
+ // fprintFunc(&buf, f) // TODO: HTML, not text, <br /> for line breaks, etc.
+ fmt.Fprint(buf, "</code>")
+ return buf.String()
+}
+
+func (d *dotWriter) writeFuncSVG(w io.Writer, phase string, f *Func) {
+ if d.broken {
+ return
+ }
+ if _, ok := d.phases[phase]; !ok {
+ return
+ }
+ cmd := exec.Command(d.path, "-Tsvg")
+ pipe, err := cmd.StdinPipe()
+ if err != nil {
+ d.broken = true
+ fmt.Println(err)
+ return
+ }
+ buf := new(bytes.Buffer)
+ cmd.Stdout = buf
+ bufErr := new(bytes.Buffer)
+ cmd.Stderr = bufErr
+ err = cmd.Start()
+ if err != nil {
+ d.broken = true
+ fmt.Println(err)
+ return
+ }
+ fmt.Fprint(pipe, `digraph "" { margin=0; ranksep=.2; `)
+ id := strings.Replace(phase, " ", "-", -1)
+ fmt.Fprintf(pipe, `id="g_graph_%s";`, id)
+ fmt.Fprintf(pipe, `node [style=filled,fillcolor=white,fontsize=16,fontname="Menlo,Times,serif",margin="0.01,0.03"];`)
+ fmt.Fprintf(pipe, `edge [fontsize=16,fontname="Menlo,Times,serif"];`)
+ for i, b := range f.Blocks {
+ if b.Kind == BlockInvalid {
+ continue
+ }
+ layout := ""
+ if f.laidout {
+ layout = fmt.Sprintf(" #%d", i)
+ }
+ fmt.Fprintf(pipe, `%v [label="%v%s\n%v",id="graph_node_%v_%v",tooltip="%v"];`, b, b, layout, b.Kind.String(), id, b, b.LongString())
+ }
+ indexOf := make([]int, f.NumBlocks())
+ for i, b := range f.Blocks {
+ indexOf[b.ID] = i
+ }
+ layoutDrawn := make([]bool, f.NumBlocks())
+
+ ponums := make([]int32, f.NumBlocks())
+ _ = postorderWithNumbering(f, ponums)
+ isBackEdge := func(from, to ID) bool {
+ return ponums[from] <= ponums[to]
+ }
+
+ for _, b := range f.Blocks {
+ for i, s := range b.Succs {
+ style := "solid"
+ color := "black"
+ arrow := "vee"
+ if b.unlikelyIndex() == i {
+ style = "dashed"
+ }
+ if f.laidout && indexOf[s.b.ID] == indexOf[b.ID]+1 {
+ // Red color means ordered edge. It overrides other colors.
+ arrow = "dotvee"
+ layoutDrawn[s.b.ID] = true
+ } else if isBackEdge(b.ID, s.b.ID) {
+ color = "#2893ff"
+ }
+ fmt.Fprintf(pipe, `%v -> %v [label=" %d ",style="%s",color="%s",arrowhead="%s"];`, b, s.b, i, style, color, arrow)
+ }
+ }
+ if f.laidout {
+ fmt.Fprintln(pipe, `edge[constraint=false,color=gray,style=solid,arrowhead=dot];`)
+ colors := [...]string{"#eea24f", "#f38385", "#f4d164", "#ca89fc", "gray"}
+ ci := 0
+ for i := 1; i < len(f.Blocks); i++ {
+ if layoutDrawn[f.Blocks[i].ID] {
+ continue
+ }
+ fmt.Fprintf(pipe, `%s -> %s [color="%s"];`, f.Blocks[i-1], f.Blocks[i], colors[ci])
+ ci = (ci + 1) % len(colors)
+ }
+ }
+ fmt.Fprint(pipe, "}")
+ pipe.Close()
+ err = cmd.Wait()
+ if err != nil {
+ d.broken = true
+ fmt.Printf("dot: %v\n%v\n", err, bufErr.String())
+ return
+ }
+
+ svgID := "svg_graph_" + id
+ fmt.Fprintf(w, `<div class="zoom"><button onclick="return graphReduce('%s');">-</button> <button onclick="return graphEnlarge('%s');">+</button></div>`, svgID, svgID)
+ // For now, an awful hack: edit the html as it passes through
+ // our fingers, finding '<svg ' and injecting needed attributes after it.
+ err = d.copyUntil(w, buf, `<svg `)
+ if err != nil {
+ fmt.Printf("injecting attributes: %v\n", err)
+ return
+ }
+ fmt.Fprintf(w, ` id="%s" onload="makeDraggable(evt)" `, svgID)
+ io.Copy(w, buf)
+}
+
+func (b *Block) unlikelyIndex() int {
+ switch b.Likely {
+ case BranchLikely:
+ return 1
+ case BranchUnlikely:
+ return 0
+ }
+ return -1
+}
+
+func (d *dotWriter) copyUntil(w io.Writer, buf *bytes.Buffer, sep string) error {
+ i := bytes.Index(buf.Bytes(), []byte(sep))
+ if i == -1 {
+ return fmt.Errorf("couldn't find dot sep %q", sep)
+ }
+ _, err := io.CopyN(w, buf, int64(i+len(sep)))
+ return err
+}
+
+type htmlFuncPrinter struct {
+ w io.Writer
+}
+
+func (p htmlFuncPrinter) header(f *Func) {}
+
+func (p htmlFuncPrinter) startBlock(b *Block, reachable bool) {
+ var dead string
+ if !reachable {
+ dead = "dead-block"
+ }
+ fmt.Fprintf(p.w, "<ul class=\"%s ssa-print-func %s\">", b, dead)
+ fmt.Fprintf(p.w, "<li class=\"ssa-start-block\">%s:", b.HTML())
+ if len(b.Preds) > 0 {
+ io.WriteString(p.w, " &#8592;") // left arrow
+ for _, e := range b.Preds {
+ pred := e.b
+ fmt.Fprintf(p.w, " %s", pred.HTML())
+ }
+ }
+ if len(b.Values) > 0 {
+ io.WriteString(p.w, `<button onclick="hideBlock(this)">-</button>`)
+ }
+ io.WriteString(p.w, "</li>")
+ if len(b.Values) > 0 { // start list of values
+ io.WriteString(p.w, "<li class=\"ssa-value-list\">")
+ io.WriteString(p.w, "<ul>")
+ }
+}
+
+func (p htmlFuncPrinter) endBlock(b *Block) {
+ if len(b.Values) > 0 { // end list of values
+ io.WriteString(p.w, "</ul>")
+ io.WriteString(p.w, "</li>")
+ }
+ io.WriteString(p.w, "<li class=\"ssa-end-block\">")
+ fmt.Fprint(p.w, b.LongHTML())
+ io.WriteString(p.w, "</li>")
+ io.WriteString(p.w, "</ul>")
+}
+
+func (p htmlFuncPrinter) value(v *Value, live bool) {
+ var dead string
+ if !live {
+ dead = "dead-value"
+ }
+ fmt.Fprintf(p.w, "<li class=\"ssa-long-value %s\">", dead)
+ fmt.Fprint(p.w, v.LongHTML())
+ io.WriteString(p.w, "</li>")
+}
+
+func (p htmlFuncPrinter) startDepCycle() {
+ fmt.Fprintln(p.w, "<span class=\"depcycle\">")
+}
+
+func (p htmlFuncPrinter) endDepCycle() {
+ fmt.Fprintln(p.w, "</span>")
+}
+
+func (p htmlFuncPrinter) named(n LocalSlot, vals []*Value) {
+ fmt.Fprintf(p.w, "<li>name %s: ", n)
+ for _, val := range vals {
+ fmt.Fprintf(p.w, "%s ", val.HTML())
+ }
+ fmt.Fprintf(p.w, "</li>")
+}
+
+type dotWriter struct {
+ path string
+ broken bool
+ phases map[string]bool // keys specify phases with CFGs
+}
+
+// newDotWriter returns non-nil value when mask is valid.
+// dotWriter will generate SVGs only for the phases specified in the mask.
+// mask can contain following patterns and combinations of them:
+// * - all of them;
+// x-y - x through y, inclusive;
+// x,y - x and y, but not the passes between.
+func newDotWriter(mask string) *dotWriter {
+ if mask == "" {
+ return nil
+ }
+ // User can specify phase name with _ instead of spaces.
+ mask = strings.Replace(mask, "_", " ", -1)
+ ph := make(map[string]bool)
+ ranges := strings.Split(mask, ",")
+ for _, r := range ranges {
+ spl := strings.Split(r, "-")
+ if len(spl) > 2 {
+ fmt.Printf("range is not valid: %v\n", mask)
+ return nil
+ }
+ var first, last int
+ if mask == "*" {
+ first = 0
+ last = len(passes) - 1
+ } else {
+ first = passIdxByName(spl[0])
+ last = passIdxByName(spl[len(spl)-1])
+ }
+ if first < 0 || last < 0 || first > last {
+ fmt.Printf("range is not valid: %v\n", r)
+ return nil
+ }
+ for p := first; p <= last; p++ {
+ ph[passes[p].name] = true
+ }
+ }
+
+ path, err := exec.LookPath("dot")
+ if err != nil {
+ fmt.Println(err)
+ return nil
+ }
+ return &dotWriter{path: path, phases: ph}
+}
+
+func passIdxByName(name string) int {
+ for i, p := range passes {
+ if p.name == name {
+ return i
+ }
+ }
+ return -1
+}
diff --git a/src/cmd/compile/internal/ssa/id.go b/src/cmd/compile/internal/ssa/id.go
new file mode 100644
index 0000000..725279e
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/id.go
@@ -0,0 +1,28 @@
+// 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
+
+type ID int32
+
+// idAlloc provides an allocator for unique integers.
+type idAlloc struct {
+ last ID
+}
+
+// get allocates an ID and returns it. IDs are always > 0.
+func (a *idAlloc) get() ID {
+ x := a.last
+ x++
+ if x == 1<<31-1 {
+ panic("too many ids for this function")
+ }
+ a.last = x
+ return x
+}
+
+// num returns the maximum ID ever returned + 1.
+func (a *idAlloc) num() int {
+ return int(a.last + 1)
+}
diff --git a/src/cmd/compile/internal/ssa/layout.go b/src/cmd/compile/internal/ssa/layout.go
new file mode 100644
index 0000000..30b7b97
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/layout.go
@@ -0,0 +1,180 @@
+// 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
+
+// layout orders basic blocks in f with the goal of minimizing control flow instructions.
+// After this phase returns, the order of f.Blocks matters and is the order
+// in which those blocks will appear in the assembly output.
+func layout(f *Func) {
+ f.Blocks = layoutOrder(f)
+}
+
+// Register allocation may use a different order which has constraints
+// imposed by the linear-scan algorithm. Note that f.pass here is
+// regalloc, so the switch is conditional on -d=ssa/regalloc/test=N
+func layoutRegallocOrder(f *Func) []*Block {
+
+ switch f.pass.test {
+ case 0: // layout order
+ return layoutOrder(f)
+ case 1: // existing block order
+ return f.Blocks
+ case 2: // reverse of postorder; legal, but usually not good.
+ po := f.postorder()
+ visitOrder := make([]*Block, len(po))
+ for i, b := range po {
+ j := len(po) - i - 1
+ visitOrder[j] = b
+ }
+ return visitOrder
+ }
+
+ return nil
+}
+
+func layoutOrder(f *Func) []*Block {
+ order := make([]*Block, 0, f.NumBlocks())
+ scheduled := make([]bool, f.NumBlocks())
+ idToBlock := make([]*Block, f.NumBlocks())
+ indegree := make([]int, f.NumBlocks())
+ posdegree := f.newSparseSet(f.NumBlocks()) // blocks with positive remaining degree
+ defer f.retSparseSet(posdegree)
+ zerodegree := f.newSparseSet(f.NumBlocks()) // blocks with zero remaining degree
+ defer f.retSparseSet(zerodegree)
+ exit := f.newSparseSet(f.NumBlocks()) // exit blocks
+ defer f.retSparseSet(exit)
+
+ // Populate idToBlock and find exit blocks.
+ for _, b := range f.Blocks {
+ idToBlock[b.ID] = b
+ if b.Kind == BlockExit {
+ exit.add(b.ID)
+ }
+ }
+
+ // Expand exit to include blocks post-dominated by exit blocks.
+ for {
+ changed := false
+ for _, id := range exit.contents() {
+ b := idToBlock[id]
+ NextPred:
+ for _, pe := range b.Preds {
+ p := pe.b
+ if exit.contains(p.ID) {
+ continue
+ }
+ for _, s := range p.Succs {
+ if !exit.contains(s.b.ID) {
+ continue NextPred
+ }
+ }
+ // All Succs are in exit; add p.
+ exit.add(p.ID)
+ changed = true
+ }
+ }
+ if !changed {
+ break
+ }
+ }
+
+ // Initialize indegree of each block
+ for _, b := range f.Blocks {
+ if exit.contains(b.ID) {
+ // exit blocks are always scheduled last
+ continue
+ }
+ indegree[b.ID] = len(b.Preds)
+ if len(b.Preds) == 0 {
+ zerodegree.add(b.ID)
+ } else {
+ posdegree.add(b.ID)
+ }
+ }
+
+ bid := f.Entry.ID
+blockloop:
+ for {
+ // add block to schedule
+ b := idToBlock[bid]
+ order = append(order, b)
+ scheduled[bid] = true
+ if len(order) == len(f.Blocks) {
+ break
+ }
+
+ for _, e := range b.Succs {
+ c := e.b
+ indegree[c.ID]--
+ if indegree[c.ID] == 0 {
+ posdegree.remove(c.ID)
+ zerodegree.add(c.ID)
+ }
+ }
+
+ // Pick the next block to schedule
+ // Pick among the successor blocks that have not been scheduled yet.
+
+ // Use likely direction if we have it.
+ var likely *Block
+ switch b.Likely {
+ case BranchLikely:
+ likely = b.Succs[0].b
+ case BranchUnlikely:
+ likely = b.Succs[1].b
+ }
+ if likely != nil && !scheduled[likely.ID] {
+ bid = likely.ID
+ continue
+ }
+
+ // Use degree for now.
+ bid = 0
+ mindegree := f.NumBlocks()
+ for _, e := range order[len(order)-1].Succs {
+ c := e.b
+ if scheduled[c.ID] || c.Kind == BlockExit {
+ continue
+ }
+ if indegree[c.ID] < mindegree {
+ mindegree = indegree[c.ID]
+ bid = c.ID
+ }
+ }
+ if bid != 0 {
+ continue
+ }
+ // TODO: improve this part
+ // No successor of the previously scheduled block works.
+ // Pick a zero-degree block if we can.
+ for zerodegree.size() > 0 {
+ cid := zerodegree.pop()
+ if !scheduled[cid] {
+ bid = cid
+ continue blockloop
+ }
+ }
+ // Still nothing, pick any non-exit block.
+ for posdegree.size() > 0 {
+ cid := posdegree.pop()
+ if !scheduled[cid] {
+ bid = cid
+ continue blockloop
+ }
+ }
+ // Pick any exit block.
+ // TODO: Order these to minimize jump distances?
+ for {
+ cid := exit.pop()
+ if !scheduled[cid] {
+ bid = cid
+ continue blockloop
+ }
+ }
+ }
+ f.laidout = true
+ return order
+ //f.Blocks = order
+}
diff --git a/src/cmd/compile/internal/ssa/lca.go b/src/cmd/compile/internal/ssa/lca.go
new file mode 100644
index 0000000..5cb7391
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/lca.go
@@ -0,0 +1,123 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// Code to compute lowest common ancestors in the dominator tree.
+// https://en.wikipedia.org/wiki/Lowest_common_ancestor
+// https://en.wikipedia.org/wiki/Range_minimum_query#Solution_using_constant_time_and_linearithmic_space
+
+// lcaRange is a data structure that can compute lowest common ancestor queries
+// in O(n lg n) precomputed space and O(1) time per query.
+type lcaRange struct {
+ // Additional information about each block (indexed by block ID).
+ blocks []lcaRangeBlock
+
+ // Data structure for range minimum queries.
+ // rangeMin[k][i] contains the ID of the minimum depth block
+ // in the Euler tour from positions i to i+1<<k-1, inclusive.
+ rangeMin [][]ID
+}
+
+type lcaRangeBlock struct {
+ b *Block
+ parent ID // parent in dominator tree. 0 = no parent (entry or unreachable)
+ firstChild ID // first child in dominator tree
+ sibling ID // next child of parent
+ pos int32 // an index in the Euler tour where this block appears (any one of its occurrences)
+ depth int32 // depth in dominator tree (root=0, its children=1, etc.)
+}
+
+func makeLCArange(f *Func) *lcaRange {
+ dom := f.Idom()
+
+ // Build tree
+ blocks := make([]lcaRangeBlock, f.NumBlocks())
+ for _, b := range f.Blocks {
+ blocks[b.ID].b = b
+ if dom[b.ID] == nil {
+ continue // entry or unreachable
+ }
+ parent := dom[b.ID].ID
+ blocks[b.ID].parent = parent
+ blocks[b.ID].sibling = blocks[parent].firstChild
+ blocks[parent].firstChild = b.ID
+ }
+
+ // Compute euler tour ordering.
+ // Each reachable block will appear #children+1 times in the tour.
+ tour := make([]ID, 0, f.NumBlocks()*2-1)
+ type queueEntry struct {
+ bid ID // block to work on
+ cid ID // child we're already working on (0 = haven't started yet)
+ }
+ q := []queueEntry{{f.Entry.ID, 0}}
+ for len(q) > 0 {
+ n := len(q) - 1
+ bid := q[n].bid
+ cid := q[n].cid
+ q = q[:n]
+
+ // Add block to tour.
+ blocks[bid].pos = int32(len(tour))
+ tour = append(tour, bid)
+
+ // Proceed down next child edge (if any).
+ if cid == 0 {
+ // This is our first visit to b. Set its depth.
+ blocks[bid].depth = blocks[blocks[bid].parent].depth + 1
+ // Then explore its first child.
+ cid = blocks[bid].firstChild
+ } else {
+ // We've seen b before. Explore the next child.
+ cid = blocks[cid].sibling
+ }
+ if cid != 0 {
+ q = append(q, queueEntry{bid, cid}, queueEntry{cid, 0})
+ }
+ }
+
+ // Compute fast range-minimum query data structure
+ var rangeMin [][]ID
+ rangeMin = append(rangeMin, tour) // 1-size windows are just the tour itself.
+ for logS, s := 1, 2; s < len(tour); logS, s = logS+1, s*2 {
+ r := make([]ID, len(tour)-s+1)
+ for i := 0; i < len(tour)-s+1; i++ {
+ bid := rangeMin[logS-1][i]
+ bid2 := rangeMin[logS-1][i+s/2]
+ if blocks[bid2].depth < blocks[bid].depth {
+ bid = bid2
+ }
+ r[i] = bid
+ }
+ rangeMin = append(rangeMin, r)
+ }
+
+ return &lcaRange{blocks: blocks, rangeMin: rangeMin}
+}
+
+// find returns the lowest common ancestor of a and b.
+func (lca *lcaRange) find(a, b *Block) *Block {
+ if a == b {
+ return a
+ }
+ // Find the positions of a and bin the Euler tour.
+ p1 := lca.blocks[a.ID].pos
+ p2 := lca.blocks[b.ID].pos
+ if p1 > p2 {
+ p1, p2 = p2, p1
+ }
+
+ // The lowest common ancestor is the minimum depth block
+ // on the tour from p1 to p2. We've precomputed minimum
+ // depth blocks for powers-of-two subsequences of the tour.
+ // Combine the right two precomputed values to get the answer.
+ logS := uint(log64(int64(p2 - p1)))
+ bid1 := lca.rangeMin[logS][p1]
+ bid2 := lca.rangeMin[logS][p2-1<<logS+1]
+ if lca.blocks[bid1].depth < lca.blocks[bid2].depth {
+ return lca.blocks[bid1].b
+ }
+ return lca.blocks[bid2].b
+}
diff --git a/src/cmd/compile/internal/ssa/lca_test.go b/src/cmd/compile/internal/ssa/lca_test.go
new file mode 100644
index 0000000..8c8920c
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/lca_test.go
@@ -0,0 +1,88 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import "testing"
+
+func testLCAgen(t *testing.T, bg blockGen, size int) {
+ c := testConfig(t)
+ fun := c.Fun("entry", bg(size)...)
+ CheckFunc(fun.f)
+ if size == 4 {
+ t.Logf(fun.f.String())
+ }
+ lca1 := makeLCArange(fun.f)
+ lca2 := makeLCAeasy(fun.f)
+ for _, b := range fun.f.Blocks {
+ for _, c := range fun.f.Blocks {
+ l1 := lca1.find(b, c)
+ l2 := lca2.find(b, c)
+ if l1 != l2 {
+ t.Errorf("lca(%s,%s)=%s, want %s", b, c, l1, l2)
+ }
+ }
+ }
+}
+
+func TestLCALinear(t *testing.T) {
+ testLCAgen(t, genLinear, 10)
+ testLCAgen(t, genLinear, 100)
+}
+
+func TestLCAFwdBack(t *testing.T) {
+ testLCAgen(t, genFwdBack, 10)
+ testLCAgen(t, genFwdBack, 100)
+}
+
+func TestLCAManyPred(t *testing.T) {
+ testLCAgen(t, genManyPred, 10)
+ testLCAgen(t, genManyPred, 100)
+}
+
+func TestLCAMaxPred(t *testing.T) {
+ testLCAgen(t, genMaxPred, 10)
+ testLCAgen(t, genMaxPred, 100)
+}
+
+func TestLCAMaxPredValue(t *testing.T) {
+ testLCAgen(t, genMaxPredValue, 10)
+ testLCAgen(t, genMaxPredValue, 100)
+}
+
+// Simple implementation of LCA to compare against.
+type lcaEasy struct {
+ parent []*Block
+}
+
+func makeLCAeasy(f *Func) *lcaEasy {
+ return &lcaEasy{parent: dominators(f)}
+}
+
+func (lca *lcaEasy) find(a, b *Block) *Block {
+ da := lca.depth(a)
+ db := lca.depth(b)
+ for da > db {
+ da--
+ a = lca.parent[a.ID]
+ }
+ for da < db {
+ db--
+ b = lca.parent[b.ID]
+ }
+ for a != b {
+ a = lca.parent[a.ID]
+ b = lca.parent[b.ID]
+ }
+ return a
+}
+
+func (lca *lcaEasy) depth(b *Block) int {
+ n := 0
+ for b != nil {
+ b = lca.parent[b.ID]
+ n++
+ }
+ return n
+}
diff --git a/src/cmd/compile/internal/ssa/likelyadjust.go b/src/cmd/compile/internal/ssa/likelyadjust.go
new file mode 100644
index 0000000..49898a1
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/likelyadjust.go
@@ -0,0 +1,575 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "fmt"
+)
+
+type loop struct {
+ header *Block // The header node of this (reducible) loop
+ outer *loop // loop containing this loop
+
+ // By default, children, exits, and depth are not initialized.
+ children []*loop // loops nested directly within this loop. Initialized by assembleChildren().
+ exits []*Block // exits records blocks reached by exits from this loop. Initialized by findExits().
+
+ // Next three fields used by regalloc and/or
+ // aid in computation of inner-ness and list of blocks.
+ nBlocks int32 // Number of blocks in this loop but not within inner loops
+ depth int16 // Nesting depth of the loop; 1 is outermost. Initialized by calculateDepths().
+ isInner bool // True if never discovered to contain a loop
+
+ // register allocation uses this.
+ containsUnavoidableCall bool // True if all paths through the loop have a call
+}
+
+// outerinner records that outer contains inner
+func (sdom SparseTree) outerinner(outer, inner *loop) {
+ // There could be other outer loops found in some random order,
+ // locate the new outer loop appropriately among them.
+
+ // Outer loop headers dominate inner loop headers.
+ // Use this to put the "new" "outer" loop in the right place.
+ oldouter := inner.outer
+ for oldouter != nil && sdom.isAncestor(outer.header, oldouter.header) {
+ inner = oldouter
+ oldouter = inner.outer
+ }
+ if outer == oldouter {
+ return
+ }
+ if oldouter != nil {
+ sdom.outerinner(oldouter, outer)
+ }
+
+ inner.outer = outer
+ outer.isInner = false
+}
+
+func checkContainsCall(bb *Block) bool {
+ if bb.Kind == BlockDefer {
+ return true
+ }
+ for _, v := range bb.Values {
+ if opcodeTable[v.Op].call {
+ return true
+ }
+ }
+ return false
+}
+
+type loopnest struct {
+ f *Func
+ b2l []*loop
+ po []*Block
+ sdom SparseTree
+ loops []*loop
+ hasIrreducible bool // TODO current treatment of irreducible loops is very flaky, if accurate loops are needed, must punt at function level.
+
+ // Record which of the lazily initialized fields have actually been initialized.
+ initializedChildren, initializedDepth, initializedExits bool
+}
+
+func min8(a, b int8) int8 {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func max8(a, b int8) int8 {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+const (
+ blDEFAULT = 0
+ blMin = blDEFAULT
+ blCALL = 1
+ blRET = 2
+ blEXIT = 3
+)
+
+var bllikelies = [4]string{"default", "call", "ret", "exit"}
+
+func describePredictionAgrees(b *Block, prediction BranchPrediction) string {
+ s := ""
+ if prediction == b.Likely {
+ s = " (agrees with previous)"
+ } else if b.Likely != BranchUnknown {
+ s = " (disagrees with previous, ignored)"
+ }
+ return s
+}
+
+func describeBranchPrediction(f *Func, b *Block, likely, not int8, prediction BranchPrediction) {
+ f.Warnl(b.Pos, "Branch prediction rule %s < %s%s",
+ bllikelies[likely-blMin], bllikelies[not-blMin], describePredictionAgrees(b, prediction))
+}
+
+func likelyadjust(f *Func) {
+ // The values assigned to certain and local only matter
+ // in their rank order. 0 is default, more positive
+ // is less likely. It's possible to assign a negative
+ // unlikeliness (though not currently the case).
+ certain := make([]int8, f.NumBlocks()) // In the long run, all outcomes are at least this bad. Mainly for Exit
+ local := make([]int8, f.NumBlocks()) // for our immediate predecessors.
+
+ po := f.postorder()
+ nest := f.loopnest()
+ b2l := nest.b2l
+
+ for _, b := range po {
+ switch b.Kind {
+ case BlockExit:
+ // Very unlikely.
+ local[b.ID] = blEXIT
+ certain[b.ID] = blEXIT
+
+ // Ret, it depends.
+ case BlockRet, BlockRetJmp:
+ local[b.ID] = blRET
+ certain[b.ID] = blRET
+
+ // Calls. TODO not all calls are equal, names give useful clues.
+ // Any name-based heuristics are only relative to other calls,
+ // and less influential than inferences from loop structure.
+ case BlockDefer:
+ local[b.ID] = blCALL
+ certain[b.ID] = max8(blCALL, certain[b.Succs[0].b.ID])
+
+ default:
+ if len(b.Succs) == 1 {
+ certain[b.ID] = certain[b.Succs[0].b.ID]
+ } else if len(b.Succs) == 2 {
+ // If successor is an unvisited backedge, it's in loop and we don't care.
+ // Its default unlikely is also zero which is consistent with favoring loop edges.
+ // Notice that this can act like a "reset" on unlikeliness at loops; the
+ // default "everything returns" unlikeliness is erased by min with the
+ // backedge likeliness; however a loop with calls on every path will be
+ // tagged with call cost. Net effect is that loop entry is favored.
+ b0 := b.Succs[0].b.ID
+ b1 := b.Succs[1].b.ID
+ certain[b.ID] = min8(certain[b0], certain[b1])
+
+ l := b2l[b.ID]
+ l0 := b2l[b0]
+ l1 := b2l[b1]
+
+ prediction := b.Likely
+ // Weak loop heuristic -- both source and at least one dest are in loops,
+ // and there is a difference in the destinations.
+ // TODO what is best arrangement for nested loops?
+ if l != nil && l0 != l1 {
+ noprediction := false
+ switch {
+ // prefer not to exit loops
+ case l1 == nil:
+ prediction = BranchLikely
+ case l0 == nil:
+ prediction = BranchUnlikely
+
+ // prefer to stay in loop, not exit to outer.
+ case l == l0:
+ prediction = BranchLikely
+ case l == l1:
+ prediction = BranchUnlikely
+ default:
+ noprediction = true
+ }
+ if f.pass.debug > 0 && !noprediction {
+ f.Warnl(b.Pos, "Branch prediction rule stay in loop%s",
+ describePredictionAgrees(b, prediction))
+ }
+
+ } else {
+ // Lacking loop structure, fall back on heuristics.
+ if certain[b1] > certain[b0] {
+ prediction = BranchLikely
+ if f.pass.debug > 0 {
+ describeBranchPrediction(f, b, certain[b0], certain[b1], prediction)
+ }
+ } else if certain[b0] > certain[b1] {
+ prediction = BranchUnlikely
+ if f.pass.debug > 0 {
+ describeBranchPrediction(f, b, certain[b1], certain[b0], prediction)
+ }
+ } else if local[b1] > local[b0] {
+ prediction = BranchLikely
+ if f.pass.debug > 0 {
+ describeBranchPrediction(f, b, local[b0], local[b1], prediction)
+ }
+ } else if local[b0] > local[b1] {
+ prediction = BranchUnlikely
+ if f.pass.debug > 0 {
+ describeBranchPrediction(f, b, local[b1], local[b0], prediction)
+ }
+ }
+ }
+ if b.Likely != prediction {
+ if b.Likely == BranchUnknown {
+ b.Likely = prediction
+ }
+ }
+ }
+ // Look for calls in the block. If there is one, make this block unlikely.
+ for _, v := range b.Values {
+ if opcodeTable[v.Op].call {
+ local[b.ID] = blCALL
+ certain[b.ID] = max8(blCALL, certain[b.Succs[0].b.ID])
+ }
+ }
+ }
+ if f.pass.debug > 2 {
+ f.Warnl(b.Pos, "BP: Block %s, local=%s, certain=%s", b, bllikelies[local[b.ID]-blMin], bllikelies[certain[b.ID]-blMin])
+ }
+
+ }
+}
+
+func (l *loop) String() string {
+ return fmt.Sprintf("hdr:%s", l.header)
+}
+
+func (l *loop) LongString() string {
+ i := ""
+ o := ""
+ if l.isInner {
+ i = ", INNER"
+ }
+ if l.outer != nil {
+ o = ", o=" + l.outer.header.String()
+ }
+ return fmt.Sprintf("hdr:%s%s%s", l.header, i, o)
+}
+
+func (l *loop) isWithinOrEq(ll *loop) bool {
+ if ll == nil { // nil means whole program
+ return true
+ }
+ for ; l != nil; l = l.outer {
+ if l == ll {
+ return true
+ }
+ }
+ return false
+}
+
+// nearestOuterLoop returns the outer loop of loop most nearly
+// containing block b; the header must dominate b. loop itself
+// is assumed to not be that loop. For acceptable performance,
+// we're relying on loop nests to not be terribly deep.
+func (l *loop) nearestOuterLoop(sdom SparseTree, b *Block) *loop {
+ var o *loop
+ for o = l.outer; o != nil && !sdom.IsAncestorEq(o.header, b); o = o.outer {
+ }
+ return o
+}
+
+func loopnestfor(f *Func) *loopnest {
+ po := f.postorder()
+ sdom := f.Sdom()
+ b2l := make([]*loop, f.NumBlocks())
+ loops := make([]*loop, 0)
+ visited := make([]bool, f.NumBlocks())
+ sawIrred := false
+
+ if f.pass.debug > 2 {
+ fmt.Printf("loop finding in %s\n", f.Name)
+ }
+
+ // Reducible-loop-nest-finding.
+ for _, b := range po {
+ if f.pass != nil && f.pass.debug > 3 {
+ fmt.Printf("loop finding at %s\n", b)
+ }
+
+ var innermost *loop // innermost header reachable from this block
+
+ // IF any successor s of b is in a loop headed by h
+ // AND h dominates b
+ // THEN b is in the loop headed by h.
+ //
+ // Choose the first/innermost such h.
+ //
+ // IF s itself dominates b, then s is a loop header;
+ // and there may be more than one such s.
+ // Since there's at most 2 successors, the inner/outer ordering
+ // between them can be established with simple comparisons.
+ for _, e := range b.Succs {
+ bb := e.b
+ l := b2l[bb.ID]
+
+ if sdom.IsAncestorEq(bb, b) { // Found a loop header
+ if f.pass != nil && f.pass.debug > 4 {
+ fmt.Printf("loop finding succ %s of %s is header\n", bb.String(), b.String())
+ }
+ if l == nil {
+ l = &loop{header: bb, isInner: true}
+ loops = append(loops, l)
+ b2l[bb.ID] = l
+ }
+ } else if !visited[bb.ID] { // Found an irreducible loop
+ sawIrred = true
+ if f.pass != nil && f.pass.debug > 4 {
+ fmt.Printf("loop finding succ %s of %s is IRRED, in %s\n", bb.String(), b.String(), f.Name)
+ }
+ } else if l != nil {
+ // TODO handle case where l is irreducible.
+ // Perhaps a loop header is inherited.
+ // is there any loop containing our successor whose
+ // header dominates b?
+ if !sdom.IsAncestorEq(l.header, b) {
+ l = l.nearestOuterLoop(sdom, b)
+ }
+ if f.pass != nil && f.pass.debug > 4 {
+ if l == nil {
+ fmt.Printf("loop finding succ %s of %s has no loop\n", bb.String(), b.String())
+ } else {
+ fmt.Printf("loop finding succ %s of %s provides loop with header %s\n", bb.String(), b.String(), l.header.String())
+ }
+ }
+ } else { // No loop
+ if f.pass != nil && f.pass.debug > 4 {
+ fmt.Printf("loop finding succ %s of %s has no loop\n", bb.String(), b.String())
+ }
+
+ }
+
+ if l == nil || innermost == l {
+ continue
+ }
+
+ if innermost == nil {
+ innermost = l
+ continue
+ }
+
+ if sdom.isAncestor(innermost.header, l.header) {
+ sdom.outerinner(innermost, l)
+ innermost = l
+ } else if sdom.isAncestor(l.header, innermost.header) {
+ sdom.outerinner(l, innermost)
+ }
+ }
+
+ if innermost != nil {
+ b2l[b.ID] = innermost
+ innermost.nBlocks++
+ }
+ visited[b.ID] = true
+ }
+
+ ln := &loopnest{f: f, b2l: b2l, po: po, sdom: sdom, loops: loops, hasIrreducible: sawIrred}
+
+ // Calculate containsUnavoidableCall for regalloc
+ dominatedByCall := make([]bool, f.NumBlocks())
+ for _, b := range po {
+ if checkContainsCall(b) {
+ dominatedByCall[b.ID] = true
+ }
+ }
+ // Run dfs to find path through the loop that avoids all calls.
+ // Such path either escapes loop or return back to header.
+ // It isn't enough to have exit not dominated by any call, for example:
+ // ... some loop
+ // call1 call2
+ // \ /
+ // exit
+ // ...
+ // exit is not dominated by any call, but we don't have call-free path to it.
+ for _, l := range loops {
+ // Header contains call.
+ if dominatedByCall[l.header.ID] {
+ l.containsUnavoidableCall = true
+ continue
+ }
+ callfreepath := false
+ tovisit := make([]*Block, 0, len(l.header.Succs))
+ // Push all non-loop non-exit successors of header onto toVisit.
+ for _, s := range l.header.Succs {
+ nb := s.Block()
+ // This corresponds to loop with zero iterations.
+ if !l.iterationEnd(nb, b2l) {
+ tovisit = append(tovisit, nb)
+ }
+ }
+ for len(tovisit) > 0 {
+ cur := tovisit[len(tovisit)-1]
+ tovisit = tovisit[:len(tovisit)-1]
+ if dominatedByCall[cur.ID] {
+ continue
+ }
+ // Record visited in dominatedByCall.
+ dominatedByCall[cur.ID] = true
+ for _, s := range cur.Succs {
+ nb := s.Block()
+ if l.iterationEnd(nb, b2l) {
+ callfreepath = true
+ }
+ if !dominatedByCall[nb.ID] {
+ tovisit = append(tovisit, nb)
+ }
+
+ }
+ if callfreepath {
+ break
+ }
+ }
+ if !callfreepath {
+ l.containsUnavoidableCall = true
+ }
+ }
+
+ // Curious about the loopiness? "-d=ssa/likelyadjust/stats"
+ if f.pass != nil && f.pass.stats > 0 && len(loops) > 0 {
+ ln.assembleChildren()
+ ln.calculateDepths()
+ ln.findExits()
+
+ // Note stats for non-innermost loops are slightly flawed because
+ // they don't account for inner loop exits that span multiple levels.
+
+ for _, l := range loops {
+ x := len(l.exits)
+ cf := 0
+ if !l.containsUnavoidableCall {
+ cf = 1
+ }
+ inner := 0
+ if l.isInner {
+ inner++
+ }
+
+ f.LogStat("loopstats:",
+ l.depth, "depth", x, "exits",
+ inner, "is_inner", cf, "always_calls", l.nBlocks, "n_blocks")
+ }
+ }
+
+ if f.pass != nil && f.pass.debug > 1 && len(loops) > 0 {
+ fmt.Printf("Loops in %s:\n", f.Name)
+ for _, l := range loops {
+ fmt.Printf("%s, b=", l.LongString())
+ for _, b := range f.Blocks {
+ if b2l[b.ID] == l {
+ fmt.Printf(" %s", b)
+ }
+ }
+ fmt.Print("\n")
+ }
+ fmt.Printf("Nonloop blocks in %s:", f.Name)
+ for _, b := range f.Blocks {
+ if b2l[b.ID] == nil {
+ fmt.Printf(" %s", b)
+ }
+ }
+ fmt.Print("\n")
+ }
+ return ln
+}
+
+// assembleChildren initializes the children field of each
+// loop in the nest. Loop A is a child of loop B if A is
+// directly nested within B (based on the reducible-loops
+// detection above)
+func (ln *loopnest) assembleChildren() {
+ if ln.initializedChildren {
+ return
+ }
+ for _, l := range ln.loops {
+ if l.outer != nil {
+ l.outer.children = append(l.outer.children, l)
+ }
+ }
+ ln.initializedChildren = true
+}
+
+// calculateDepths uses the children field of loops
+// to determine the nesting depth (outer=1) of each
+// loop. This is helpful for finding exit edges.
+func (ln *loopnest) calculateDepths() {
+ if ln.initializedDepth {
+ return
+ }
+ ln.assembleChildren()
+ for _, l := range ln.loops {
+ if l.outer == nil {
+ l.setDepth(1)
+ }
+ }
+ ln.initializedDepth = true
+}
+
+// findExits uses loop depth information to find the
+// exits from a loop.
+func (ln *loopnest) findExits() {
+ if ln.initializedExits {
+ return
+ }
+ ln.calculateDepths()
+ b2l := ln.b2l
+ for _, b := range ln.po {
+ l := b2l[b.ID]
+ if l != nil && len(b.Succs) == 2 {
+ sl := b2l[b.Succs[0].b.ID]
+ if recordIfExit(l, sl, b.Succs[0].b) {
+ continue
+ }
+ sl = b2l[b.Succs[1].b.ID]
+ if recordIfExit(l, sl, b.Succs[1].b) {
+ continue
+ }
+ }
+ }
+ ln.initializedExits = true
+}
+
+// depth returns the loop nesting level of block b.
+func (ln *loopnest) depth(b ID) int16 {
+ if l := ln.b2l[b]; l != nil {
+ return l.depth
+ }
+ return 0
+}
+
+// recordIfExit checks sl (the loop containing b) to see if it
+// is outside of loop l, and if so, records b as an exit block
+// from l and returns true.
+func recordIfExit(l, sl *loop, b *Block) bool {
+ if sl != l {
+ if sl == nil || sl.depth <= l.depth {
+ l.exits = append(l.exits, b)
+ return true
+ }
+ // sl is not nil, and is deeper than l
+ // it's possible for this to be a goto into an irreducible loop made from gotos.
+ for sl.depth > l.depth {
+ sl = sl.outer
+ }
+ if sl != l {
+ l.exits = append(l.exits, b)
+ return true
+ }
+ }
+ return false
+}
+
+func (l *loop) setDepth(d int16) {
+ l.depth = d
+ for _, c := range l.children {
+ c.setDepth(d + 1)
+ }
+}
+
+// iterationEnd checks if block b ends iteration of loop l.
+// Ending iteration means either escaping to outer loop/code or
+// going back to header
+func (l *loop) iterationEnd(b *Block, b2l []*loop) bool {
+ return b == l.header || b2l[b.ID] == nil || (b2l[b.ID] != l && b2l[b.ID].depth <= l.depth)
+}
diff --git a/src/cmd/compile/internal/ssa/location.go b/src/cmd/compile/internal/ssa/location.go
new file mode 100644
index 0000000..a333982
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/location.go
@@ -0,0 +1,88 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "fmt"
+)
+
+// A place that an ssa variable can reside.
+type Location interface {
+ String() string // name to use in assembly templates: AX, 16(SP), ...
+}
+
+// A Register is a machine register, like AX.
+// They are numbered densely from 0 (for each architecture).
+type Register struct {
+ num int32 // dense numbering
+ objNum int16 // register number from cmd/internal/obj/$ARCH
+ gcNum int16 // GC register map number (dense numbering of registers that can contain pointers)
+ name string
+}
+
+func (r *Register) String() string {
+ return r.name
+}
+
+// ObjNum returns the register number from cmd/internal/obj/$ARCH that
+// corresponds to this register.
+func (r *Register) ObjNum() int16 {
+ return r.objNum
+}
+
+// GCNum returns the runtime GC register index of r, or -1 if this
+// register can't contain pointers.
+func (r *Register) GCNum() int16 {
+ return r.gcNum
+}
+
+// A LocalSlot is a location in the stack frame, which identifies and stores
+// part or all of a PPARAM, PPARAMOUT, or PAUTO ONAME node.
+// It can represent a whole variable, part of a larger stack slot, or part of a
+// variable that has been decomposed into multiple stack slots.
+// As an example, a string could have the following configurations:
+//
+// stack layout LocalSlots
+//
+// Optimizations are disabled. s is on the stack and represented in its entirety.
+// [ ------- s string ---- ] { N: s, Type: string, Off: 0 }
+//
+// s was not decomposed, but the SSA operates on its parts individually, so
+// there is a LocalSlot for each of its fields that points into the single stack slot.
+// [ ------- s string ---- ] { N: s, Type: *uint8, Off: 0 }, {N: s, Type: int, Off: 8}
+//
+// s was decomposed. Each of its fields is in its own stack slot and has its own LocalSLot.
+// [ ptr *uint8 ] [ len int] { N: ptr, Type: *uint8, Off: 0, SplitOf: parent, SplitOffset: 0},
+// { N: len, Type: int, Off: 0, SplitOf: parent, SplitOffset: 8}
+// parent = &{N: s, Type: string}
+type LocalSlot struct {
+ N GCNode // an ONAME *gc.Node representing a stack location.
+ Type *types.Type // type of slot
+ Off int64 // offset of slot in N
+
+ SplitOf *LocalSlot // slot is a decomposition of SplitOf
+ SplitOffset int64 // .. at this offset.
+}
+
+func (s LocalSlot) String() string {
+ if s.Off == 0 {
+ return fmt.Sprintf("%v[%v]", s.N, s.Type)
+ }
+ return fmt.Sprintf("%v+%d[%v]", s.N, s.Off, s.Type)
+}
+
+type LocPair [2]Location
+
+func (t LocPair) String() string {
+ n0, n1 := "nil", "nil"
+ if t[0] != nil {
+ n0 = t[0].String()
+ }
+ if t[1] != nil {
+ n1 = t[1].String()
+ }
+ return fmt.Sprintf("<%s,%s>", n0, n1)
+}
diff --git a/src/cmd/compile/internal/ssa/loopbce.go b/src/cmd/compile/internal/ssa/loopbce.go
new file mode 100644
index 0000000..5a4bc1d
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/loopbce.go
@@ -0,0 +1,346 @@
+// Copyright 2018 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"
+)
+
+type indVarFlags uint8
+
+const (
+ indVarMinExc indVarFlags = 1 << iota // minimum value is exclusive (default: inclusive)
+ indVarMaxInc // maximum value is inclusive (default: exclusive)
+)
+
+type indVar struct {
+ ind *Value // induction variable
+ min *Value // minimum value, inclusive/exclusive depends on flags
+ max *Value // maximum value, inclusive/exclusive depends on flags
+ entry *Block // entry block in the loop.
+ flags indVarFlags
+ // Invariant: for all blocks strictly dominated by entry:
+ // min <= ind < max [if flags == 0]
+ // min < ind < max [if flags == indVarMinExc]
+ // min <= ind <= max [if flags == indVarMaxInc]
+ // min < ind <= max [if flags == indVarMinExc|indVarMaxInc]
+}
+
+// parseIndVar checks whether the SSA value passed as argument is a valid induction
+// variable, and, if so, extracts:
+// * the minimum bound
+// * the increment value
+// * the "next" value (SSA value that is Phi'd into the induction variable every loop)
+// Currently, we detect induction variables that match (Phi min nxt),
+// with nxt being (Add inc ind).
+// If it can't parse the induction variable correctly, it returns (nil, nil, nil).
+func parseIndVar(ind *Value) (min, inc, nxt *Value) {
+ if ind.Op != OpPhi {
+ return
+ }
+
+ if n := ind.Args[0]; n.Op == OpAdd64 && (n.Args[0] == ind || n.Args[1] == ind) {
+ min, nxt = ind.Args[1], n
+ } else if n := ind.Args[1]; n.Op == OpAdd64 && (n.Args[0] == ind || n.Args[1] == ind) {
+ min, nxt = ind.Args[0], n
+ } else {
+ // Not a recognized induction variable.
+ return
+ }
+
+ if nxt.Args[0] == ind { // nxt = ind + inc
+ inc = nxt.Args[1]
+ } else if nxt.Args[1] == ind { // nxt = inc + ind
+ inc = nxt.Args[0]
+ } else {
+ panic("unreachable") // one of the cases must be true from the above.
+ }
+
+ return
+}
+
+// findIndVar finds induction variables in a function.
+//
+// Look for variables and blocks that satisfy the following
+//
+// loop:
+// ind = (Phi min nxt),
+// if ind < max
+// then goto enter_loop
+// else goto exit_loop
+//
+// enter_loop:
+// do something
+// nxt = inc + ind
+// goto loop
+//
+// exit_loop:
+//
+//
+// TODO: handle 32 bit operations
+func findIndVar(f *Func) []indVar {
+ var iv []indVar
+ sdom := f.Sdom()
+
+ for _, b := range f.Blocks {
+ if b.Kind != BlockIf || len(b.Preds) != 2 {
+ continue
+ }
+
+ var flags indVarFlags
+ var ind, max *Value // induction, and maximum
+
+ // Check thet the control if it either ind </<= max or max >/>= ind.
+ // TODO: Handle 32-bit comparisons.
+ // TODO: Handle unsigned comparisons?
+ c := b.Controls[0]
+ switch c.Op {
+ case OpLeq64:
+ flags |= indVarMaxInc
+ fallthrough
+ case OpLess64:
+ ind, max = c.Args[0], c.Args[1]
+ default:
+ continue
+ }
+
+ // See if this is really an induction variable
+ less := true
+ min, inc, nxt := parseIndVar(ind)
+ if min == nil {
+ // We failed to parse the induction variable. Before punting, we want to check
+ // whether the control op was written with arguments in non-idiomatic order,
+ // so that we believe being "max" (the upper bound) is actually the induction
+ // variable itself. This would happen for code like:
+ // for i := 0; len(n) > i; i++
+ min, inc, nxt = parseIndVar(max)
+ if min == nil {
+ // No recognied induction variable on either operand
+ continue
+ }
+
+ // Ok, the arguments were reversed. Swap them, and remember that we're
+ // looking at a ind >/>= loop (so the induction must be decrementing).
+ ind, max = max, ind
+ less = false
+ }
+
+ // Expect the increment to be a nonzero constant.
+ if inc.Op != OpConst64 {
+ continue
+ }
+ step := inc.AuxInt
+ if step == 0 {
+ continue
+ }
+
+ // Increment sign must match comparison direction.
+ // When incrementing, the termination comparison must be ind </<= max.
+ // When decrementing, the termination comparison must be ind >/>= max.
+ // See issue 26116.
+ if step > 0 && !less {
+ continue
+ }
+ if step < 0 && less {
+ continue
+ }
+
+ // If the increment is negative, swap min/max and their flags
+ if step < 0 {
+ min, max = max, min
+ oldf := flags
+ flags = indVarMaxInc
+ if oldf&indVarMaxInc == 0 {
+ flags |= indVarMinExc
+ }
+ step = -step
+ }
+
+ // Up to now we extracted the induction variable (ind),
+ // the increment delta (inc), the temporary sum (nxt),
+ // the mininum value (min) and the maximum value (max).
+ //
+ // We also know that ind has the form (Phi min nxt) where
+ // nxt is (Add inc nxt) which means: 1) inc dominates nxt
+ // and 2) there is a loop starting at inc and containing nxt.
+ //
+ // We need to prove that the induction variable is incremented
+ // only when it's smaller than the maximum value.
+ // Two conditions must happen listed below to accept ind
+ // as an induction variable.
+
+ // First condition: loop entry has a single predecessor, which
+ // is the header block. This implies that b.Succs[0] is
+ // reached iff ind < max.
+ if len(b.Succs[0].b.Preds) != 1 {
+ // b.Succs[1] must exit the loop.
+ continue
+ }
+
+ // Second condition: b.Succs[0] dominates nxt so that
+ // nxt is computed when inc < max, meaning nxt <= max.
+ if !sdom.IsAncestorEq(b.Succs[0].b, nxt.Block) {
+ // inc+ind can only be reached through the branch that enters the loop.
+ continue
+ }
+
+ // We can only guarantee that the loop runs within limits of induction variable
+ // if (one of)
+ // (1) the increment is ±1
+ // (2) the limits are constants
+ // (3) loop is of the form k0 upto Known_not_negative-k inclusive, step <= k
+ // (4) loop is of the form k0 upto Known_not_negative-k exclusive, step <= k+1
+ // (5) loop is of the form Known_not_negative downto k0, minint+step < k0
+ if step > 1 {
+ ok := false
+ if min.Op == OpConst64 && max.Op == OpConst64 {
+ if max.AuxInt > min.AuxInt && max.AuxInt%step == min.AuxInt%step { // handle overflow
+ ok = true
+ }
+ }
+ // Handle induction variables of these forms.
+ // KNN is known-not-negative.
+ // SIGNED ARITHMETIC ONLY. (see switch on c above)
+ // Possibilities for KNN are len and cap; perhaps we can infer others.
+ // for i := 0; i <= KNN-k ; i += k
+ // for i := 0; i < KNN-(k-1); i += k
+ // Also handle decreasing.
+
+ // "Proof" copied from https://go-review.googlesource.com/c/go/+/104041/10/src/cmd/compile/internal/ssa/loopbce.go#164
+ //
+ // In the case of
+ // // PC is Positive Constant
+ // L := len(A)-PC
+ // for i := 0; i < L; i = i+PC
+ //
+ // we know:
+ //
+ // 0 + PC does not over/underflow.
+ // len(A)-PC does not over/underflow
+ // maximum value for L is MaxInt-PC
+ // i < L <= MaxInt-PC means i + PC < MaxInt hence no overflow.
+
+ // To match in SSA:
+ // if (a) min.Op == OpConst64(k0)
+ // and (b) k0 >= MININT + step
+ // and (c) max.Op == OpSubtract(Op{StringLen,SliceLen,SliceCap}, k)
+ // or (c) max.Op == OpAdd(Op{StringLen,SliceLen,SliceCap}, -k)
+ // or (c) max.Op == Op{StringLen,SliceLen,SliceCap}
+ // and (d) if upto loop, require indVarMaxInc && step <= k or !indVarMaxInc && step-1 <= k
+
+ if min.Op == OpConst64 && min.AuxInt >= step+math.MinInt64 {
+ knn := max
+ k := int64(0)
+ var kArg *Value
+
+ switch max.Op {
+ case OpSub64:
+ knn = max.Args[0]
+ kArg = max.Args[1]
+
+ case OpAdd64:
+ knn = max.Args[0]
+ kArg = max.Args[1]
+ if knn.Op == OpConst64 {
+ knn, kArg = kArg, knn
+ }
+ }
+ switch knn.Op {
+ case OpSliceLen, OpStringLen, OpSliceCap:
+ default:
+ knn = nil
+ }
+
+ if kArg != nil && kArg.Op == OpConst64 {
+ k = kArg.AuxInt
+ if max.Op == OpAdd64 {
+ k = -k
+ }
+ }
+ if k >= 0 && knn != nil {
+ if inc.AuxInt > 0 { // increasing iteration
+ // The concern for the relation between step and k is to ensure that iv never exceeds knn
+ // i.e., iv < knn-(K-1) ==> iv + K <= knn; iv <= knn-K ==> iv +K < knn
+ if step <= k || flags&indVarMaxInc == 0 && step-1 == k {
+ ok = true
+ }
+ } else { // decreasing iteration
+ // Will be decrementing from max towards min; max is knn-k; will only attempt decrement if
+ // knn-k >[=] min; underflow is only a concern if min-step is not smaller than min.
+ // This all assumes signed integer arithmetic
+ // This is already assured by the test above: min.AuxInt >= step+math.MinInt64
+ ok = true
+ }
+ }
+ }
+
+ // TODO: other unrolling idioms
+ // for i := 0; i < KNN - KNN % k ; i += k
+ // for i := 0; i < KNN&^(k-1) ; i += k // k a power of 2
+ // for i := 0; i < KNN&(-k) ; i += k // k a power of 2
+
+ if !ok {
+ continue
+ }
+ }
+
+ if f.pass.debug >= 1 {
+ printIndVar(b, ind, min, max, step, flags)
+ }
+
+ iv = append(iv, indVar{
+ ind: ind,
+ min: min,
+ max: max,
+ entry: b.Succs[0].b,
+ flags: flags,
+ })
+ b.Logf("found induction variable %v (inc = %v, min = %v, max = %v)\n", ind, inc, min, max)
+ }
+
+ return iv
+}
+
+func dropAdd64(v *Value) (*Value, int64) {
+ if v.Op == OpAdd64 && v.Args[0].Op == OpConst64 {
+ return v.Args[1], v.Args[0].AuxInt
+ }
+ if v.Op == OpAdd64 && v.Args[1].Op == OpConst64 {
+ return v.Args[0], v.Args[1].AuxInt
+ }
+ return v, 0
+}
+
+func printIndVar(b *Block, i, min, max *Value, inc int64, flags indVarFlags) {
+ mb1, mb2 := "[", "]"
+ if flags&indVarMinExc != 0 {
+ mb1 = "("
+ }
+ if flags&indVarMaxInc == 0 {
+ mb2 = ")"
+ }
+
+ mlim1, mlim2 := fmt.Sprint(min.AuxInt), fmt.Sprint(max.AuxInt)
+ if !min.isGenericIntConst() {
+ if b.Func.pass.debug >= 2 {
+ mlim1 = fmt.Sprint(min)
+ } else {
+ mlim1 = "?"
+ }
+ }
+ if !max.isGenericIntConst() {
+ if b.Func.pass.debug >= 2 {
+ mlim2 = fmt.Sprint(max)
+ } else {
+ mlim2 = "?"
+ }
+ }
+ extra := ""
+ if b.Func.pass.debug >= 2 {
+ extra = fmt.Sprintf(" (%s)", i)
+ }
+ b.Func.Warnl(b.Pos, "Induction variable: limits %v%v,%v%v, increment %d%s", mb1, mlim1, mlim2, mb2, inc, extra)
+}
diff --git a/src/cmd/compile/internal/ssa/loopreschedchecks.go b/src/cmd/compile/internal/ssa/loopreschedchecks.go
new file mode 100644
index 0000000..9c73bcf
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/loopreschedchecks.go
@@ -0,0 +1,499 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "fmt"
+)
+
+// an edgeMem records a backedge, together with the memory
+// phi functions at the target of the backedge that must
+// be updated when a rescheduling check replaces the backedge.
+type edgeMem struct {
+ e Edge
+ m *Value // phi for memory at dest of e
+}
+
+// a rewriteTarget is a value-argindex pair indicating
+// where a rewrite is applied. Note that this is for values,
+// not for block controls, because block controls are not targets
+// for the rewrites performed in inserting rescheduling checks.
+type rewriteTarget struct {
+ v *Value
+ i int
+}
+
+type rewrite struct {
+ before, after *Value // before is the expected value before rewrite, after is the new value installed.
+ rewrites []rewriteTarget // all the targets for this rewrite.
+}
+
+func (r *rewrite) String() string {
+ s := "\n\tbefore=" + r.before.String() + ", after=" + r.after.String()
+ for _, rw := range r.rewrites {
+ s += ", (i=" + fmt.Sprint(rw.i) + ", v=" + rw.v.LongString() + ")"
+ }
+ s += "\n"
+ return s
+}
+
+// insertLoopReschedChecks inserts rescheduling checks on loop backedges.
+func insertLoopReschedChecks(f *Func) {
+ // TODO: when split information is recorded in export data, insert checks only on backedges that can be reached on a split-call-free path.
+
+ // Loop reschedule checks compare the stack pointer with
+ // the per-g stack bound. If the pointer appears invalid,
+ // that means a reschedule check is needed.
+ //
+ // Steps:
+ // 1. locate backedges.
+ // 2. Record memory definitions at block end so that
+ // the SSA graph for mem can be properly modified.
+ // 3. Ensure that phi functions that will-be-needed for mem
+ // are present in the graph, initially with trivial inputs.
+ // 4. Record all to-be-modified uses of mem;
+ // apply modifications (split into two steps to simplify and
+ // avoided nagging order-dependencies).
+ // 5. Rewrite backedges to include reschedule check,
+ // and modify destination phi function appropriately with new
+ // definitions for mem.
+
+ if f.NoSplit { // nosplit functions don't reschedule.
+ return
+ }
+
+ backedges := backedges(f)
+ if len(backedges) == 0 { // no backedges means no rescheduling checks.
+ return
+ }
+
+ lastMems := findLastMems(f)
+
+ idom := f.Idom()
+ po := f.postorder()
+ // The ordering in the dominator tree matters; it's important that
+ // the walk of the dominator tree also be a preorder (i.e., a node is
+ // visited only after all its non-backedge predecessors have been visited).
+ sdom := newSparseOrderedTree(f, idom, po)
+
+ if f.pass.debug > 1 {
+ fmt.Printf("before %s = %s\n", f.Name, sdom.treestructure(f.Entry))
+ }
+
+ tofixBackedges := []edgeMem{}
+
+ for _, e := range backedges { // TODO: could filter here by calls in loops, if declared and inferred nosplit are recorded in export data.
+ tofixBackedges = append(tofixBackedges, edgeMem{e, nil})
+ }
+
+ // It's possible that there is no memory state (no global/pointer loads/stores or calls)
+ if lastMems[f.Entry.ID] == nil {
+ lastMems[f.Entry.ID] = f.Entry.NewValue0(f.Entry.Pos, OpInitMem, types.TypeMem)
+ }
+
+ memDefsAtBlockEnds := make([]*Value, f.NumBlocks()) // For each block, the mem def seen at its bottom. Could be from earlier block.
+
+ // Propagate last mem definitions forward through successor blocks.
+ for i := len(po) - 1; i >= 0; i-- {
+ b := po[i]
+ mem := lastMems[b.ID]
+ for j := 0; mem == nil; j++ { // if there's no def, then there's no phi, so the visible mem is identical in all predecessors.
+ // loop because there might be backedges that haven't been visited yet.
+ mem = memDefsAtBlockEnds[b.Preds[j].b.ID]
+ }
+ memDefsAtBlockEnds[b.ID] = mem
+ if f.pass.debug > 2 {
+ fmt.Printf("memDefsAtBlockEnds[%s] = %s\n", b, mem)
+ }
+ }
+
+ // Maps from block to newly-inserted phi function in block.
+ newmemphis := make(map[*Block]rewrite)
+
+ // Insert phi functions as necessary for future changes to flow graph.
+ for i, emc := range tofixBackedges {
+ e := emc.e
+ h := e.b
+
+ // find the phi function for the memory input at "h", if there is one.
+ var headerMemPhi *Value // look for header mem phi
+
+ for _, v := range h.Values {
+ if v.Op == OpPhi && v.Type.IsMemory() {
+ headerMemPhi = v
+ }
+ }
+
+ if headerMemPhi == nil {
+ // if the header is nil, make a trivial phi from the dominator
+ mem0 := memDefsAtBlockEnds[idom[h.ID].ID]
+ headerMemPhi = newPhiFor(h, mem0)
+ newmemphis[h] = rewrite{before: mem0, after: headerMemPhi}
+ addDFphis(mem0, h, h, f, memDefsAtBlockEnds, newmemphis, sdom)
+
+ }
+ tofixBackedges[i].m = headerMemPhi
+
+ }
+ if f.pass.debug > 0 {
+ for b, r := range newmemphis {
+ fmt.Printf("before b=%s, rewrite=%s\n", b, r.String())
+ }
+ }
+
+ // dfPhiTargets notes inputs to phis in dominance frontiers that should not
+ // be rewritten as part of the dominated children of some outer rewrite.
+ dfPhiTargets := make(map[rewriteTarget]bool)
+
+ rewriteNewPhis(f.Entry, f.Entry, f, memDefsAtBlockEnds, newmemphis, dfPhiTargets, sdom)
+
+ if f.pass.debug > 0 {
+ for b, r := range newmemphis {
+ fmt.Printf("after b=%s, rewrite=%s\n", b, r.String())
+ }
+ }
+
+ // Apply collected rewrites.
+ for _, r := range newmemphis {
+ for _, rw := range r.rewrites {
+ rw.v.SetArg(rw.i, r.after)
+ }
+ }
+
+ // Rewrite backedges to include reschedule checks.
+ for _, emc := range tofixBackedges {
+ e := emc.e
+ headerMemPhi := emc.m
+ h := e.b
+ i := e.i
+ p := h.Preds[i]
+ bb := p.b
+ mem0 := headerMemPhi.Args[i]
+ // bb e->p h,
+ // Because we're going to insert a rare-call, make sure the
+ // looping edge still looks likely.
+ likely := BranchLikely
+ if p.i != 0 {
+ likely = BranchUnlikely
+ }
+ if bb.Kind != BlockPlain { // backedges can be unconditional. e.g., if x { something; continue }
+ bb.Likely = likely
+ }
+
+ // rewrite edge to include reschedule check
+ // existing edges:
+ //
+ // bb.Succs[p.i] == Edge{h, i}
+ // h.Preds[i] == p == Edge{bb,p.i}
+ //
+ // new block(s):
+ // test:
+ // if sp < g.limit { goto sched }
+ // goto join
+ // sched:
+ // mem1 := call resched (mem0)
+ // goto join
+ // join:
+ // mem2 := phi(mem0, mem1)
+ // goto h
+ //
+ // and correct arg i of headerMemPhi and headerCtrPhi
+ //
+ // EXCEPT: join block containing only phi functions is bad
+ // for the register allocator. Therefore, there is no
+ // join, and branches targeting join must instead target
+ // the header, and the other phi functions within header are
+ // adjusted for the additional input.
+
+ test := f.NewBlock(BlockIf)
+ sched := f.NewBlock(BlockPlain)
+
+ test.Pos = bb.Pos
+ sched.Pos = bb.Pos
+
+ // if sp < g.limit { goto sched }
+ // goto header
+
+ cfgtypes := &f.Config.Types
+ pt := cfgtypes.Uintptr
+ g := test.NewValue1(bb.Pos, OpGetG, pt, mem0)
+ sp := test.NewValue0(bb.Pos, OpSP, pt)
+ cmpOp := OpLess64U
+ if pt.Size() == 4 {
+ cmpOp = OpLess32U
+ }
+ limaddr := test.NewValue1I(bb.Pos, OpOffPtr, pt, 2*pt.Size(), g)
+ lim := test.NewValue2(bb.Pos, OpLoad, pt, limaddr, mem0)
+ cmp := test.NewValue2(bb.Pos, cmpOp, cfgtypes.Bool, sp, lim)
+ test.SetControl(cmp)
+
+ // if true, goto sched
+ test.AddEdgeTo(sched)
+
+ // if false, rewrite edge to header.
+ // do NOT remove+add, because that will perturb all the other phi functions
+ // as well as messing up other edges to the header.
+ test.Succs = append(test.Succs, Edge{h, i})
+ h.Preds[i] = Edge{test, 1}
+ headerMemPhi.SetArg(i, mem0)
+
+ test.Likely = BranchUnlikely
+
+ // sched:
+ // mem1 := call resched (mem0)
+ // goto header
+ resched := f.fe.Syslook("goschedguarded")
+ mem1 := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeMem, StaticAuxCall(resched, nil, nil), mem0)
+ sched.AddEdgeTo(h)
+ headerMemPhi.AddArg(mem1)
+
+ bb.Succs[p.i] = Edge{test, 0}
+ test.Preds = append(test.Preds, Edge{bb, p.i})
+
+ // Must correct all the other phi functions in the header for new incoming edge.
+ // Except for mem phis, it will be the same value seen on the original
+ // backedge at index i.
+ for _, v := range h.Values {
+ if v.Op == OpPhi && v != headerMemPhi {
+ v.AddArg(v.Args[i])
+ }
+ }
+ }
+
+ f.invalidateCFG()
+
+ if f.pass.debug > 1 {
+ sdom = newSparseTree(f, f.Idom())
+ fmt.Printf("after %s = %s\n", f.Name, sdom.treestructure(f.Entry))
+ }
+}
+
+// newPhiFor inserts a new Phi function into b,
+// with all inputs set to v.
+func newPhiFor(b *Block, v *Value) *Value {
+ phiV := b.NewValue0(b.Pos, OpPhi, v.Type)
+
+ for range b.Preds {
+ phiV.AddArg(v)
+ }
+ return phiV
+}
+
+// rewriteNewPhis updates newphis[h] to record all places where the new phi function inserted
+// in block h will replace a previous definition. Block b is the block currently being processed;
+// if b has its own phi definition then it takes the place of h.
+// defsForUses provides information about other definitions of the variable that are present
+// (and if nil, indicates that the variable is no longer live)
+// sdom must yield a preorder of the flow graph if recursively walked, root-to-children.
+// The result of newSparseOrderedTree with order supplied by a dfs-postorder satisfies this
+// requirement.
+func rewriteNewPhis(h, b *Block, f *Func, defsForUses []*Value, newphis map[*Block]rewrite, dfPhiTargets map[rewriteTarget]bool, sdom SparseTree) {
+ // If b is a block with a new phi, then a new rewrite applies below it in the dominator tree.
+ if _, ok := newphis[b]; ok {
+ h = b
+ }
+ change := newphis[h]
+ x := change.before
+ y := change.after
+
+ // Apply rewrites to this block
+ if x != nil { // don't waste time on the common case of no definition.
+ p := &change.rewrites
+ for _, v := range b.Values {
+ if v == y { // don't rewrite self -- phi inputs are handled below.
+ continue
+ }
+ for i, w := range v.Args {
+ if w != x {
+ continue
+ }
+ tgt := rewriteTarget{v, i}
+
+ // It's possible dominated control flow will rewrite this instead.
+ // Visiting in preorder (a property of how sdom was constructed)
+ // ensures that these are seen in the proper order.
+ if dfPhiTargets[tgt] {
+ continue
+ }
+ *p = append(*p, tgt)
+ if f.pass.debug > 1 {
+ fmt.Printf("added block target for h=%v, b=%v, x=%v, y=%v, tgt.v=%s, tgt.i=%d\n",
+ h, b, x, y, v, i)
+ }
+ }
+ }
+
+ // Rewrite appropriate inputs of phis reached in successors
+ // in dominance frontier, self, and dominated.
+ // If the variable def reaching uses in b is itself defined in b, then the new phi function
+ // does not reach the successors of b. (This assumes a bit about the structure of the
+ // phi use-def graph, but it's true for memory.)
+ if dfu := defsForUses[b.ID]; dfu != nil && dfu.Block != b {
+ for _, e := range b.Succs {
+ s := e.b
+
+ for _, v := range s.Values {
+ if v.Op == OpPhi && v.Args[e.i] == x {
+ tgt := rewriteTarget{v, e.i}
+ *p = append(*p, tgt)
+ dfPhiTargets[tgt] = true
+ if f.pass.debug > 1 {
+ fmt.Printf("added phi target for h=%v, b=%v, s=%v, x=%v, y=%v, tgt.v=%s, tgt.i=%d\n",
+ h, b, s, x, y, v.LongString(), e.i)
+ }
+ break
+ }
+ }
+ }
+ }
+ newphis[h] = change
+ }
+
+ for c := sdom[b.ID].child; c != nil; c = sdom[c.ID].sibling {
+ rewriteNewPhis(h, c, f, defsForUses, newphis, dfPhiTargets, sdom) // TODO: convert to explicit stack from recursion.
+ }
+}
+
+// addDFphis creates new trivial phis that are necessary to correctly reflect (within SSA)
+// a new definition for variable "x" inserted at h (usually but not necessarily a phi).
+// These new phis can only occur at the dominance frontier of h; block s is in the dominance
+// frontier of h if h does not strictly dominate s and if s is a successor of a block b where
+// either b = h or h strictly dominates b.
+// These newly created phis are themselves new definitions that may require addition of their
+// own trivial phi functions in their own dominance frontier, and this is handled recursively.
+func addDFphis(x *Value, h, b *Block, f *Func, defForUses []*Value, newphis map[*Block]rewrite, sdom SparseTree) {
+ oldv := defForUses[b.ID]
+ if oldv != x { // either a new definition replacing x, or nil if it is proven that there are no uses reachable from b
+ return
+ }
+ idom := f.Idom()
+outer:
+ for _, e := range b.Succs {
+ s := e.b
+ // check phi functions in the dominance frontier
+ if sdom.isAncestor(h, s) {
+ continue // h dominates s, successor of b, therefore s is not in the frontier.
+ }
+ if _, ok := newphis[s]; ok {
+ continue // successor s of b already has a new phi function, so there is no need to add another.
+ }
+ if x != nil {
+ for _, v := range s.Values {
+ if v.Op == OpPhi && v.Args[e.i] == x {
+ continue outer // successor s of b has an old phi function, so there is no need to add another.
+ }
+ }
+ }
+
+ old := defForUses[idom[s.ID].ID] // new phi function is correct-but-redundant, combining value "old" on all inputs.
+ headerPhi := newPhiFor(s, old)
+ // the new phi will replace "old" in block s and all blocks dominated by s.
+ newphis[s] = rewrite{before: old, after: headerPhi} // record new phi, to have inputs labeled "old" rewritten to "headerPhi"
+ addDFphis(old, s, s, f, defForUses, newphis, sdom) // the new definition may also create new phi functions.
+ }
+ for c := sdom[b.ID].child; c != nil; c = sdom[c.ID].sibling {
+ addDFphis(x, h, c, f, defForUses, newphis, sdom) // TODO: convert to explicit stack from recursion.
+ }
+}
+
+// findLastMems maps block ids to last memory-output op in a block, if any
+func findLastMems(f *Func) []*Value {
+
+ var stores []*Value
+ lastMems := make([]*Value, f.NumBlocks())
+ storeUse := f.newSparseSet(f.NumValues())
+ defer f.retSparseSet(storeUse)
+ for _, b := range f.Blocks {
+ // Find all the stores in this block. Categorize their uses:
+ // storeUse contains stores which are used by a subsequent store.
+ storeUse.clear()
+ stores = stores[:0]
+ var memPhi *Value
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ if v.Type.IsMemory() {
+ memPhi = v
+ }
+ continue
+ }
+ if v.Type.IsMemory() {
+ stores = append(stores, v)
+ for _, a := range v.Args {
+ if a.Block == b && a.Type.IsMemory() {
+ storeUse.add(a.ID)
+ }
+ }
+ }
+ }
+ if len(stores) == 0 {
+ lastMems[b.ID] = memPhi
+ continue
+ }
+
+ // find last store in the block
+ var last *Value
+ for _, v := range stores {
+ if storeUse.contains(v.ID) {
+ continue
+ }
+ if last != nil {
+ b.Fatalf("two final stores - simultaneous live stores %s %s", last, v)
+ }
+ last = v
+ }
+ if last == nil {
+ b.Fatalf("no last store found - cycle?")
+ }
+ lastMems[b.ID] = last
+ }
+ return lastMems
+}
+
+// mark values
+type markKind uint8
+
+const (
+ notFound markKind = iota // block has not been discovered yet
+ notExplored // discovered and in queue, outedges not processed yet
+ explored // discovered and in queue, outedges processed
+ done // all done, in output ordering
+)
+
+type backedgesState struct {
+ b *Block
+ i int
+}
+
+// backedges returns a slice of successor edges that are back
+// edges. For reducible loops, edge.b is the header.
+func backedges(f *Func) []Edge {
+ edges := []Edge{}
+ mark := make([]markKind, f.NumBlocks())
+ stack := []backedgesState{}
+
+ mark[f.Entry.ID] = notExplored
+ stack = append(stack, backedgesState{f.Entry, 0})
+
+ for len(stack) > 0 {
+ l := len(stack)
+ x := stack[l-1]
+ if x.i < len(x.b.Succs) {
+ e := x.b.Succs[x.i]
+ stack[l-1].i++
+ s := e.b
+ if mark[s.ID] == notFound {
+ mark[s.ID] = notExplored
+ stack = append(stack, backedgesState{s, 0})
+ } else if mark[s.ID] == notExplored {
+ edges = append(edges, e)
+ }
+ } else {
+ mark[x.b.ID] = done
+ stack = stack[0 : l-1]
+ }
+ }
+ return edges
+}
diff --git a/src/cmd/compile/internal/ssa/looprotate.go b/src/cmd/compile/internal/ssa/looprotate.go
new file mode 100644
index 0000000..2e5e421
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/looprotate.go
@@ -0,0 +1,106 @@
+// Copyright 2017 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
+
+// loopRotate converts loops with a check-loop-condition-at-beginning
+// to loops with a check-loop-condition-at-end.
+// This helps loops avoid extra unnecessary jumps.
+//
+// loop:
+// CMPQ ...
+// JGE exit
+// ...
+// JMP loop
+// exit:
+//
+// JMP entry
+// loop:
+// ...
+// entry:
+// CMPQ ...
+// JLT loop
+func loopRotate(f *Func) {
+ loopnest := f.loopnest()
+ if loopnest.hasIrreducible {
+ return
+ }
+ if len(loopnest.loops) == 0 {
+ return
+ }
+
+ idToIdx := make([]int, f.NumBlocks())
+ for i, b := range f.Blocks {
+ idToIdx[b.ID] = i
+ }
+
+ // Set of blocks we're moving, by ID.
+ move := map[ID]struct{}{}
+
+ // Map from block ID to the moving blocks that should
+ // come right after it.
+ after := map[ID][]*Block{}
+
+ // Check each loop header and decide if we want to move it.
+ for _, loop := range loopnest.loops {
+ b := loop.header
+ var p *Block // b's in-loop predecessor
+ for _, e := range b.Preds {
+ if e.b.Kind != BlockPlain {
+ continue
+ }
+ if loopnest.b2l[e.b.ID] != loop {
+ continue
+ }
+ p = e.b
+ }
+ if p == nil || p == b {
+ continue
+ }
+ after[p.ID] = []*Block{b}
+ for {
+ nextIdx := idToIdx[b.ID] + 1
+ if nextIdx >= len(f.Blocks) { // reached end of function (maybe impossible?)
+ break
+ }
+ nextb := f.Blocks[nextIdx]
+ if nextb == p { // original loop predecessor is next
+ break
+ }
+ if loopnest.b2l[nextb.ID] != loop { // about to leave loop
+ break
+ }
+ after[p.ID] = append(after[p.ID], nextb)
+ b = nextb
+ }
+
+ // Place b after p.
+ for _, b := range after[p.ID] {
+ move[b.ID] = struct{}{}
+ }
+ }
+
+ // Move blocks to their destinations in a single pass.
+ // We rely here on the fact that loop headers must come
+ // before the rest of the loop. And that relies on the
+ // fact that we only identify reducible loops.
+ j := 0
+ for i, b := range f.Blocks {
+ if _, ok := move[b.ID]; ok {
+ continue
+ }
+ f.Blocks[j] = b
+ j++
+ for _, a := range after[b.ID] {
+ if j > i {
+ f.Fatalf("head before tail in loop %s", b)
+ }
+ f.Blocks[j] = a
+ j++
+ }
+ }
+ if j != len(f.Blocks) {
+ f.Fatalf("bad reordering in looprotate")
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/lower.go b/src/cmd/compile/internal/ssa/lower.go
new file mode 100644
index 0000000..f332b2e
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/lower.go
@@ -0,0 +1,39 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// convert to machine-dependent ops
+func lower(f *Func) {
+ // repeat rewrites until we find no more rewrites
+ applyRewrite(f, f.Config.lowerBlock, f.Config.lowerValue, removeDeadValues)
+}
+
+// checkLower checks for unlowered opcodes and fails if we find one.
+func checkLower(f *Func) {
+ // Needs to be a separate phase because it must run after both
+ // lowering and a subsequent dead code elimination (because lowering
+ // rules may leave dead generic ops behind).
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if !opcodeTable[v.Op].generic {
+ continue // lowered
+ }
+ switch v.Op {
+ case OpSP, OpSB, OpInitMem, OpArg, OpPhi, OpVarDef, OpVarKill, OpVarLive, OpKeepAlive, OpSelect0, OpSelect1, OpConvert, OpInlMark:
+ continue // ok not to lower
+ case OpGetG:
+ if f.Config.hasGReg {
+ // has hardware g register, regalloc takes care of it
+ continue // ok not to lower
+ }
+ }
+ s := "not lowered: " + v.String() + ", " + v.Op.String() + " " + v.Type.SimpleString()
+ for _, a := range v.Args {
+ s += " " + a.Type.SimpleString()
+ }
+ f.Fatalf("%s", s)
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/magic.go b/src/cmd/compile/internal/ssa/magic.go
new file mode 100644
index 0000000..93f8801
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/magic.go
@@ -0,0 +1,424 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "math/big"
+ "math/bits"
+)
+
+// So you want to compute x / c for some constant c?
+// Machine division instructions are slow, so we try to
+// compute this division with a multiplication + a few
+// other cheap instructions instead.
+// (We assume here that c != 0, +/- 1, or +/- 2^i. Those
+// cases are easy to handle in different ways).
+
+// Technique from https://gmplib.org/~tege/divcnst-pldi94.pdf
+
+// First consider unsigned division.
+// Our strategy is to precompute 1/c then do
+// ⎣x / c⎦ = ⎣x * (1/c)⎦.
+// 1/c is less than 1, so we can't compute it directly in
+// integer arithmetic. Let's instead compute 2^e/c
+// for a value of e TBD (^ = exponentiation). Then
+// ⎣x / c⎦ = ⎣x * (2^e/c) / 2^e⎦.
+// Dividing by 2^e is easy. 2^e/c isn't an integer, unfortunately.
+// So we must approximate it. Let's call its approximation m.
+// We'll then compute
+// ⎣x * m / 2^e⎦
+// Which we want to be equal to ⎣x / c⎦ for 0 <= x < 2^n-1
+// where n is the word size.
+// Setting x = c gives us c * m >= 2^e.
+// We'll chose m = ⎡2^e/c⎤ to satisfy that equation.
+// What remains is to choose e.
+// Let m = 2^e/c + delta, 0 <= delta < 1
+// ⎣x * (2^e/c + delta) / 2^e⎦
+// ⎣x / c + x * delta / 2^e⎦
+// We must have x * delta / 2^e < 1/c so that this
+// additional term never rounds differently than ⎣x / c⎦ does.
+// Rearranging,
+// 2^e > x * delta * c
+// x can be at most 2^n-1 and delta can be at most 1.
+// So it is sufficient to have 2^e >= 2^n*c.
+// So we'll choose e = n + s, with s = ⎡log2(c)⎤.
+//
+// An additional complication arises because m has n+1 bits in it.
+// Hardware restricts us to n bit by n bit multiplies.
+// We divide into 3 cases:
+//
+// Case 1: m is even.
+// ⎣x / c⎦ = ⎣x * m / 2^(n+s)⎦
+// ⎣x / c⎦ = ⎣x * (m/2) / 2^(n+s-1)⎦
+// ⎣x / c⎦ = ⎣x * (m/2) / 2^n / 2^(s-1)⎦
+// ⎣x / c⎦ = ⎣⎣x * (m/2) / 2^n⎦ / 2^(s-1)⎦
+// multiply + shift
+//
+// Case 2: c is even.
+// ⎣x / c⎦ = ⎣(x/2) / (c/2)⎦
+// ⎣x / c⎦ = ⎣⎣x/2⎦ / (c/2)⎦
+// This is just the original problem, with x' = ⎣x/2⎦, c' = c/2, n' = n-1.
+// s' = s-1
+// m' = ⎡2^(n'+s')/c'⎤
+// = ⎡2^(n+s-1)/c⎤
+// = ⎡m/2⎤
+// ⎣x / c⎦ = ⎣x' * m' / 2^(n'+s')⎦
+// ⎣x / c⎦ = ⎣⎣x/2⎦ * ⎡m/2⎤ / 2^(n+s-2)⎦
+// ⎣x / c⎦ = ⎣⎣⎣x/2⎦ * ⎡m/2⎤ / 2^n⎦ / 2^(s-2)⎦
+// shift + multiply + shift
+//
+// Case 3: everything else
+// let k = m - 2^n. k fits in n bits.
+// ⎣x / c⎦ = ⎣x * m / 2^(n+s)⎦
+// ⎣x / c⎦ = ⎣x * (2^n + k) / 2^(n+s)⎦
+// ⎣x / c⎦ = ⎣(x + x * k / 2^n) / 2^s⎦
+// ⎣x / c⎦ = ⎣(x + ⎣x * k / 2^n⎦) / 2^s⎦
+// ⎣x / c⎦ = ⎣(x + ⎣x * k / 2^n⎦) / 2^s⎦
+// ⎣x / c⎦ = ⎣⎣(x + ⎣x * k / 2^n⎦) / 2⎦ / 2^(s-1)⎦
+// multiply + avg + shift
+//
+// These can be implemented in hardware using:
+// ⎣a * b / 2^n⎦ - aka high n bits of an n-bit by n-bit multiply.
+// ⎣(a+b) / 2⎦ - aka "average" of two n-bit numbers.
+// (Not just a regular add & shift because the intermediate result
+// a+b has n+1 bits in it. Nevertheless, can be done
+// in 2 instructions on x86.)
+
+// umagicOK reports whether we should strength reduce a n-bit divide by c.
+func umagicOK(n uint, c int64) bool {
+ // Convert from ConstX auxint values to the real uint64 constant they represent.
+ d := uint64(c) << (64 - n) >> (64 - n)
+
+ // Doesn't work for 0.
+ // Don't use for powers of 2.
+ return d&(d-1) != 0
+}
+
+// umagicOKn reports whether we should strength reduce an unsigned n-bit divide by c.
+// We can strength reduce when c != 0 and c is not a power of two.
+func umagicOK8(c int8) bool { return c&(c-1) != 0 }
+func umagicOK16(c int16) bool { return c&(c-1) != 0 }
+func umagicOK32(c int32) bool { return c&(c-1) != 0 }
+func umagicOK64(c int64) bool { return c&(c-1) != 0 }
+
+type umagicData struct {
+ s int64 // ⎡log2(c)⎤
+ m uint64 // ⎡2^(n+s)/c⎤ - 2^n
+}
+
+// umagic computes the constants needed to strength reduce unsigned n-bit divides by the constant uint64(c).
+// The return values satisfy for all 0 <= x < 2^n
+// floor(x / uint64(c)) = x * (m + 2^n) >> (n+s)
+func umagic(n uint, c int64) umagicData {
+ // Convert from ConstX auxint values to the real uint64 constant they represent.
+ d := uint64(c) << (64 - n) >> (64 - n)
+
+ C := new(big.Int).SetUint64(d)
+ s := C.BitLen()
+ M := big.NewInt(1)
+ M.Lsh(M, n+uint(s)) // 2^(n+s)
+ M.Add(M, C) // 2^(n+s)+c
+ M.Sub(M, big.NewInt(1)) // 2^(n+s)+c-1
+ M.Div(M, C) // ⎡2^(n+s)/c⎤
+ if M.Bit(int(n)) != 1 {
+ panic("n+1st bit isn't set")
+ }
+ M.SetBit(M, int(n), 0)
+ m := M.Uint64()
+ return umagicData{s: int64(s), m: m}
+}
+
+func umagic8(c int8) umagicData { return umagic(8, int64(c)) }
+func umagic16(c int16) umagicData { return umagic(16, int64(c)) }
+func umagic32(c int32) umagicData { return umagic(32, int64(c)) }
+func umagic64(c int64) umagicData { return umagic(64, c) }
+
+// For signed division, we use a similar strategy.
+// First, we enforce a positive c.
+// x / c = -(x / (-c))
+// This will require an additional Neg op for c<0.
+//
+// If x is positive we're in a very similar state
+// to the unsigned case above. We define:
+// s = ⎡log2(c)⎤-1
+// m = ⎡2^(n+s)/c⎤
+// Then
+// ⎣x / c⎦ = ⎣x * m / 2^(n+s)⎦
+// If x is negative we have
+// ⎡x / c⎤ = ⎣x * m / 2^(n+s)⎦ + 1
+// (TODO: derivation?)
+//
+// The multiply is a bit odd, as it is a signed n-bit value
+// times an unsigned n-bit value. For n smaller than the
+// word size, we can extend x and m appropriately and use the
+// signed multiply instruction. For n == word size,
+// we must use the signed multiply high and correct
+// the result by adding x*2^n.
+//
+// Adding 1 if x<0 is done by subtracting x>>(n-1).
+
+func smagicOK(n uint, c int64) bool {
+ if c < 0 {
+ // Doesn't work for negative c.
+ return false
+ }
+ // Doesn't work for 0.
+ // Don't use it for powers of 2.
+ return c&(c-1) != 0
+}
+
+// smagicOKn reports whether we should strength reduce an signed n-bit divide by c.
+func smagicOK8(c int8) bool { return smagicOK(8, int64(c)) }
+func smagicOK16(c int16) bool { return smagicOK(16, int64(c)) }
+func smagicOK32(c int32) bool { return smagicOK(32, int64(c)) }
+func smagicOK64(c int64) bool { return smagicOK(64, c) }
+
+type smagicData struct {
+ s int64 // ⎡log2(c)⎤-1
+ m uint64 // ⎡2^(n+s)/c⎤
+}
+
+// magic computes the constants needed to strength reduce signed n-bit divides by the constant c.
+// Must have c>0.
+// The return values satisfy for all -2^(n-1) <= x < 2^(n-1)
+// trunc(x / c) = x * m >> (n+s) + (x < 0 ? 1 : 0)
+func smagic(n uint, c int64) smagicData {
+ C := new(big.Int).SetInt64(c)
+ s := C.BitLen() - 1
+ M := big.NewInt(1)
+ M.Lsh(M, n+uint(s)) // 2^(n+s)
+ M.Add(M, C) // 2^(n+s)+c
+ M.Sub(M, big.NewInt(1)) // 2^(n+s)+c-1
+ M.Div(M, C) // ⎡2^(n+s)/c⎤
+ if M.Bit(int(n)) != 0 {
+ panic("n+1st bit is set")
+ }
+ if M.Bit(int(n-1)) == 0 {
+ panic("nth bit is not set")
+ }
+ m := M.Uint64()
+ return smagicData{s: int64(s), m: m}
+}
+
+func smagic8(c int8) smagicData { return smagic(8, int64(c)) }
+func smagic16(c int16) smagicData { return smagic(16, int64(c)) }
+func smagic32(c int32) smagicData { return smagic(32, int64(c)) }
+func smagic64(c int64) smagicData { return smagic(64, c) }
+
+// Divisibility x%c == 0 can be checked more efficiently than directly computing
+// the modulus x%c and comparing against 0.
+//
+// The same "Division by invariant integers using multiplication" paper
+// by Granlund and Montgomery referenced above briefly mentions this method
+// and it is further elaborated in "Hacker's Delight" by Warren Section 10-17
+//
+// The first thing to note is that for odd integers, exact division can be computed
+// by using the modular inverse with respect to the word size 2^n.
+//
+// Given c, compute m such that (c * m) mod 2^n == 1
+// Then if c divides x (x%c ==0), the quotient is given by q = x/c == x*m mod 2^n
+//
+// x can range from 0, c, 2c, 3c, ... ⎣(2^n - 1)/c⎦ * c the maximum multiple
+// Thus, x*m mod 2^n is 0, 1, 2, 3, ... ⎣(2^n - 1)/c⎦
+// i.e. the quotient takes all values from zero up to max = ⎣(2^n - 1)/c⎦
+//
+// If x is not divisible by c, then x*m mod 2^n must take some larger value than max.
+//
+// This gives x*m mod 2^n <= ⎣(2^n - 1)/c⎦ as a test for divisibility
+// involving one multiplication and compare.
+//
+// To extend this to even integers, consider c = d0 * 2^k where d0 is odd.
+// We can test whether x is divisible by both d0 and 2^k.
+// For d0, the test is the same as above. Let m be such that m*d0 mod 2^n == 1
+// Then x*m mod 2^n <= ⎣(2^n - 1)/d0⎦ is the first test.
+// The test for divisibility by 2^k is a check for k trailing zeroes.
+// Note that since d0 is odd, m is odd and thus x*m will have the same number of
+// trailing zeroes as x. So the two tests are,
+//
+// x*m mod 2^n <= ⎣(2^n - 1)/d0⎦
+// and x*m ends in k zero bits
+//
+// These can be combined into a single comparison by the following
+// (theorem ZRU in Hacker's Delight) for unsigned integers.
+//
+// x <= a and x ends in k zero bits if and only if RotRight(x ,k) <= ⎣a/(2^k)⎦
+// Where RotRight(x ,k) is right rotation of x by k bits.
+//
+// To prove the first direction, x <= a -> ⎣x/(2^k)⎦ <= ⎣a/(2^k)⎦
+// But since x ends in k zeroes all the rotated bits would be zero too.
+// So RotRight(x, k) == ⎣x/(2^k)⎦ <= ⎣a/(2^k)⎦
+//
+// If x does not end in k zero bits, then RotRight(x, k)
+// has some non-zero bits in the k highest bits.
+// ⎣x/(2^k)⎦ has all zeroes in the k highest bits,
+// so RotRight(x, k) > ⎣x/(2^k)⎦
+//
+// Finally, if x > a and has k trailing zero bits, then RotRight(x, k) == ⎣x/(2^k)⎦
+// and ⎣x/(2^k)⎦ must be greater than ⎣a/(2^k)⎦, that is the top n-k bits of x must
+// be greater than the top n-k bits of a because the rest of x bits are zero.
+//
+// So the two conditions about can be replaced with the single test
+//
+// RotRight(x*m mod 2^n, k) <= ⎣(2^n - 1)/c⎦
+//
+// Where d0*2^k was replaced by c on the right hand side.
+
+// udivisibleOK reports whether we should strength reduce an unsigned n-bit divisibilty check by c.
+func udivisibleOK(n uint, c int64) bool {
+ // Convert from ConstX auxint values to the real uint64 constant they represent.
+ d := uint64(c) << (64 - n) >> (64 - n)
+
+ // Doesn't work for 0.
+ // Don't use for powers of 2.
+ return d&(d-1) != 0
+}
+
+func udivisibleOK8(c int8) bool { return udivisibleOK(8, int64(c)) }
+func udivisibleOK16(c int16) bool { return udivisibleOK(16, int64(c)) }
+func udivisibleOK32(c int32) bool { return udivisibleOK(32, int64(c)) }
+func udivisibleOK64(c int64) bool { return udivisibleOK(64, c) }
+
+type udivisibleData struct {
+ k int64 // trailingZeros(c)
+ m uint64 // m * (c>>k) mod 2^n == 1 multiplicative inverse of odd portion modulo 2^n
+ max uint64 // ⎣(2^n - 1)/ c⎦ max value to for divisibility
+}
+
+func udivisible(n uint, c int64) udivisibleData {
+ // Convert from ConstX auxint values to the real uint64 constant they represent.
+ d := uint64(c) << (64 - n) >> (64 - n)
+
+ k := bits.TrailingZeros64(d)
+ d0 := d >> uint(k) // the odd portion of the divisor
+
+ mask := ^uint64(0) >> (64 - n)
+
+ // Calculate the multiplicative inverse via Newton's method.
+ // Quadratic convergence doubles the number of correct bits per iteration.
+ m := d0 // initial guess correct to 3-bits d0*d0 mod 8 == 1
+ m = m * (2 - m*d0) // 6-bits
+ m = m * (2 - m*d0) // 12-bits
+ m = m * (2 - m*d0) // 24-bits
+ m = m * (2 - m*d0) // 48-bits
+ m = m * (2 - m*d0) // 96-bits >= 64-bits
+ m = m & mask
+
+ max := mask / d
+
+ return udivisibleData{
+ k: int64(k),
+ m: m,
+ max: max,
+ }
+}
+
+func udivisible8(c int8) udivisibleData { return udivisible(8, int64(c)) }
+func udivisible16(c int16) udivisibleData { return udivisible(16, int64(c)) }
+func udivisible32(c int32) udivisibleData { return udivisible(32, int64(c)) }
+func udivisible64(c int64) udivisibleData { return udivisible(64, c) }
+
+// For signed integers, a similar method follows.
+//
+// Given c > 1 and odd, compute m such that (c * m) mod 2^n == 1
+// Then if c divides x (x%c ==0), the quotient is given by q = x/c == x*m mod 2^n
+//
+// x can range from ⎡-2^(n-1)/c⎤ * c, ... -c, 0, c, ... ⎣(2^(n-1) - 1)/c⎦ * c
+// Thus, x*m mod 2^n is ⎡-2^(n-1)/c⎤, ... -2, -1, 0, 1, 2, ... ⎣(2^(n-1) - 1)/c⎦
+//
+// So, x is a multiple of c if and only if:
+// ⎡-2^(n-1)/c⎤ <= x*m mod 2^n <= ⎣(2^(n-1) - 1)/c⎦
+//
+// Since c > 1 and odd, this can be simplified by
+// ⎡-2^(n-1)/c⎤ == ⎡(-2^(n-1) + 1)/c⎤ == -⎣(2^(n-1) - 1)/c⎦
+//
+// -⎣(2^(n-1) - 1)/c⎦ <= x*m mod 2^n <= ⎣(2^(n-1) - 1)/c⎦
+//
+// To extend this to even integers, consider c = d0 * 2^k where d0 is odd.
+// We can test whether x is divisible by both d0 and 2^k.
+//
+// Let m be such that (d0 * m) mod 2^n == 1.
+// Let q = x*m mod 2^n. Then c divides x if:
+//
+// -⎣(2^(n-1) - 1)/d0⎦ <= q <= ⎣(2^(n-1) - 1)/d0⎦ and q ends in at least k 0-bits
+//
+// To transform this to a single comparison, we use the following theorem (ZRS in Hacker's Delight).
+//
+// For a >= 0 the following conditions are equivalent:
+// 1) -a <= x <= a and x ends in at least k 0-bits
+// 2) RotRight(x+a', k) <= ⎣2a'/2^k⎦
+//
+// Where a' = a & -2^k (a with its right k bits set to zero)
+//
+// To see that 1 & 2 are equivalent, note that -a <= x <= a is equivalent to
+// -a' <= x <= a' if and only if x ends in at least k 0-bits. Adding -a' to each side gives,
+// 0 <= x + a' <= 2a' and x + a' ends in at least k 0-bits if and only if x does since a' has
+// k 0-bits by definition. We can use theorem ZRU above with x -> x + a' and a -> 2a' giving 1) == 2).
+//
+// Let m be such that (d0 * m) mod 2^n == 1.
+// Let q = x*m mod 2^n.
+// Let a' = ⎣(2^(n-1) - 1)/d0⎦ & -2^k
+//
+// Then the divisibility test is:
+//
+// RotRight(q+a', k) <= ⎣2a'/2^k⎦
+//
+// Note that the calculation is performed using unsigned integers.
+// Since a' can have n-1 bits, 2a' may have n bits and there is no risk of overflow.
+
+// sdivisibleOK reports whether we should strength reduce a signed n-bit divisibilty check by c.
+func sdivisibleOK(n uint, c int64) bool {
+ if c < 0 {
+ // Doesn't work for negative c.
+ return false
+ }
+ // Doesn't work for 0.
+ // Don't use it for powers of 2.
+ return c&(c-1) != 0
+}
+
+func sdivisibleOK8(c int8) bool { return sdivisibleOK(8, int64(c)) }
+func sdivisibleOK16(c int16) bool { return sdivisibleOK(16, int64(c)) }
+func sdivisibleOK32(c int32) bool { return sdivisibleOK(32, int64(c)) }
+func sdivisibleOK64(c int64) bool { return sdivisibleOK(64, c) }
+
+type sdivisibleData struct {
+ k int64 // trailingZeros(c)
+ m uint64 // m * (c>>k) mod 2^n == 1 multiplicative inverse of odd portion modulo 2^n
+ a uint64 // ⎣(2^(n-1) - 1)/ (c>>k)⎦ & -(1<<k) additive constant
+ max uint64 // ⎣(2 a) / (1<<k)⎦ max value to for divisibility
+}
+
+func sdivisible(n uint, c int64) sdivisibleData {
+ d := uint64(c)
+ k := bits.TrailingZeros64(d)
+ d0 := d >> uint(k) // the odd portion of the divisor
+
+ mask := ^uint64(0) >> (64 - n)
+
+ // Calculate the multiplicative inverse via Newton's method.
+ // Quadratic convergence doubles the number of correct bits per iteration.
+ m := d0 // initial guess correct to 3-bits d0*d0 mod 8 == 1
+ m = m * (2 - m*d0) // 6-bits
+ m = m * (2 - m*d0) // 12-bits
+ m = m * (2 - m*d0) // 24-bits
+ m = m * (2 - m*d0) // 48-bits
+ m = m * (2 - m*d0) // 96-bits >= 64-bits
+ m = m & mask
+
+ a := ((mask >> 1) / d0) & -(1 << uint(k))
+ max := (2 * a) >> uint(k)
+
+ return sdivisibleData{
+ k: int64(k),
+ m: m,
+ a: a,
+ max: max,
+ }
+}
+
+func sdivisible8(c int8) sdivisibleData { return sdivisible(8, int64(c)) }
+func sdivisible16(c int16) sdivisibleData { return sdivisible(16, int64(c)) }
+func sdivisible32(c int32) sdivisibleData { return sdivisible(32, int64(c)) }
+func sdivisible64(c int64) sdivisibleData { return sdivisible(64, c) }
diff --git a/src/cmd/compile/internal/ssa/magic_test.go b/src/cmd/compile/internal/ssa/magic_test.go
new file mode 100644
index 0000000..7c6009d
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/magic_test.go
@@ -0,0 +1,410 @@
+// Copyright 2017 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 (
+ "math/big"
+ "testing"
+)
+
+func TestMagicExhaustive8(t *testing.T) {
+ testMagicExhaustive(t, 8)
+}
+func TestMagicExhaustive8U(t *testing.T) {
+ testMagicExhaustiveU(t, 8)
+}
+func TestMagicExhaustive16(t *testing.T) {
+ if testing.Short() {
+ t.Skip("slow test; skipping")
+ }
+ testMagicExhaustive(t, 16)
+}
+func TestMagicExhaustive16U(t *testing.T) {
+ if testing.Short() {
+ t.Skip("slow test; skipping")
+ }
+ testMagicExhaustiveU(t, 16)
+}
+
+// exhaustive test of magic for n bits
+func testMagicExhaustive(t *testing.T, n uint) {
+ min := -int64(1) << (n - 1)
+ max := int64(1) << (n - 1)
+ for c := int64(1); c < max; c++ {
+ if !smagicOK(n, int64(c)) {
+ continue
+ }
+ m := int64(smagic(n, c).m)
+ s := smagic(n, c).s
+ for i := min; i < max; i++ {
+ want := i / c
+ got := (i * m) >> (n + uint(s))
+ if i < 0 {
+ got++
+ }
+ if want != got {
+ t.Errorf("signed magic wrong for %d / %d: got %d, want %d (m=%d,s=%d)\n", i, c, got, want, m, s)
+ }
+ }
+ }
+}
+func testMagicExhaustiveU(t *testing.T, n uint) {
+ max := uint64(1) << n
+ for c := uint64(1); c < max; c++ {
+ if !umagicOK(n, int64(c)) {
+ continue
+ }
+ m := umagic(n, int64(c)).m
+ s := umagic(n, int64(c)).s
+ for i := uint64(0); i < max; i++ {
+ want := i / c
+ got := (i * (max + m)) >> (n + uint(s))
+ if want != got {
+ t.Errorf("unsigned magic wrong for %d / %d: got %d, want %d (m=%d,s=%d)\n", i, c, got, want, m, s)
+ }
+ }
+ }
+}
+
+func TestMagicUnsigned(t *testing.T) {
+ One := new(big.Int).SetUint64(1)
+ for _, n := range [...]uint{8, 16, 32, 64} {
+ TwoN := new(big.Int).Lsh(One, n)
+ Max := new(big.Int).Sub(TwoN, One)
+ for _, c := range [...]uint64{
+ 3,
+ 5,
+ 6,
+ 7,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 17,
+ 1<<8 - 1,
+ 1<<8 + 1,
+ 1<<16 - 1,
+ 1<<16 + 1,
+ 1<<32 - 1,
+ 1<<32 + 1,
+ 1<<64 - 1,
+ } {
+ if c>>n != 0 {
+ continue // not appropriate for the given n.
+ }
+ if !umagicOK(n, int64(c)) {
+ t.Errorf("expected n=%d c=%d to pass\n", n, c)
+ }
+ m := umagic(n, int64(c)).m
+ s := umagic(n, int64(c)).s
+
+ C := new(big.Int).SetUint64(c)
+ M := new(big.Int).SetUint64(m)
+ M.Add(M, TwoN)
+
+ // Find largest multiple of c.
+ Mul := new(big.Int).Div(Max, C)
+ Mul.Mul(Mul, C)
+ mul := Mul.Uint64()
+
+ // Try some input values, mostly around multiples of c.
+ for _, x := range [...]uint64{0, 1,
+ c - 1, c, c + 1,
+ 2*c - 1, 2 * c, 2*c + 1,
+ mul - 1, mul, mul + 1,
+ uint64(1)<<n - 1,
+ } {
+ X := new(big.Int).SetUint64(x)
+ if X.Cmp(Max) > 0 {
+ continue
+ }
+ Want := new(big.Int).Quo(X, C)
+ Got := new(big.Int).Mul(X, M)
+ Got.Rsh(Got, n+uint(s))
+ if Want.Cmp(Got) != 0 {
+ t.Errorf("umagic for %d/%d n=%d doesn't work, got=%s, want %s\n", x, c, n, Got, Want)
+ }
+ }
+ }
+ }
+}
+
+func TestMagicSigned(t *testing.T) {
+ One := new(big.Int).SetInt64(1)
+ for _, n := range [...]uint{8, 16, 32, 64} {
+ TwoNMinusOne := new(big.Int).Lsh(One, n-1)
+ Max := new(big.Int).Sub(TwoNMinusOne, One)
+ Min := new(big.Int).Neg(TwoNMinusOne)
+ for _, c := range [...]int64{
+ 3,
+ 5,
+ 6,
+ 7,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 17,
+ 1<<7 - 1,
+ 1<<7 + 1,
+ 1<<15 - 1,
+ 1<<15 + 1,
+ 1<<31 - 1,
+ 1<<31 + 1,
+ 1<<63 - 1,
+ } {
+ if c>>(n-1) != 0 {
+ continue // not appropriate for the given n.
+ }
+ if !smagicOK(n, int64(c)) {
+ t.Errorf("expected n=%d c=%d to pass\n", n, c)
+ }
+ m := smagic(n, int64(c)).m
+ s := smagic(n, int64(c)).s
+
+ C := new(big.Int).SetInt64(c)
+ M := new(big.Int).SetUint64(m)
+
+ // Find largest multiple of c.
+ Mul := new(big.Int).Div(Max, C)
+ Mul.Mul(Mul, C)
+ mul := Mul.Int64()
+
+ // Try some input values, mostly around multiples of c.
+ for _, x := range [...]int64{
+ -1, 1,
+ -c - 1, -c, -c + 1, c - 1, c, c + 1,
+ -2*c - 1, -2 * c, -2*c + 1, 2*c - 1, 2 * c, 2*c + 1,
+ -mul - 1, -mul, -mul + 1, mul - 1, mul, mul + 1,
+ int64(1)<<(n-1) - 1, -int64(1) << (n - 1),
+ } {
+ X := new(big.Int).SetInt64(x)
+ if X.Cmp(Min) < 0 || X.Cmp(Max) > 0 {
+ continue
+ }
+ Want := new(big.Int).Quo(X, C)
+ Got := new(big.Int).Mul(X, M)
+ Got.Rsh(Got, n+uint(s))
+ if x < 0 {
+ Got.Add(Got, One)
+ }
+ if Want.Cmp(Got) != 0 {
+ t.Errorf("smagic for %d/%d n=%d doesn't work, got=%s, want %s\n", x, c, n, Got, Want)
+ }
+ }
+ }
+ }
+}
+
+func testDivisibleExhaustiveU(t *testing.T, n uint) {
+ maxU := uint64(1) << n
+ for c := uint64(1); c < maxU; c++ {
+ if !udivisibleOK(n, int64(c)) {
+ continue
+ }
+ k := udivisible(n, int64(c)).k
+ m := udivisible(n, int64(c)).m
+ max := udivisible(n, int64(c)).max
+ mask := ^uint64(0) >> (64 - n)
+ for i := uint64(0); i < maxU; i++ {
+ want := i%c == 0
+ mul := (i * m) & mask
+ rot := (mul>>uint(k) | mul<<(n-uint(k))) & mask
+ got := rot <= max
+ if want != got {
+ t.Errorf("unsigned divisible wrong for %d %% %d == 0: got %v, want %v (k=%d,m=%d,max=%d)\n", i, c, got, want, k, m, max)
+ }
+ }
+ }
+}
+
+func TestDivisibleExhaustive8U(t *testing.T) {
+ testDivisibleExhaustiveU(t, 8)
+}
+
+func TestDivisibleExhaustive16U(t *testing.T) {
+ if testing.Short() {
+ t.Skip("slow test; skipping")
+ }
+ testDivisibleExhaustiveU(t, 16)
+}
+
+func TestDivisibleUnsigned(t *testing.T) {
+ One := new(big.Int).SetUint64(1)
+ for _, n := range [...]uint{8, 16, 32, 64} {
+ TwoN := new(big.Int).Lsh(One, n)
+ Max := new(big.Int).Sub(TwoN, One)
+ for _, c := range [...]uint64{
+ 3,
+ 5,
+ 6,
+ 7,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 17,
+ 1<<8 - 1,
+ 1<<8 + 1,
+ 1<<16 - 1,
+ 1<<16 + 1,
+ 1<<32 - 1,
+ 1<<32 + 1,
+ 1<<64 - 1,
+ } {
+ if c>>n != 0 {
+ continue // c too large for the given n.
+ }
+ if !udivisibleOK(n, int64(c)) {
+ t.Errorf("expected n=%d c=%d to pass\n", n, c)
+ }
+ k := udivisible(n, int64(c)).k
+ m := udivisible(n, int64(c)).m
+ max := udivisible(n, int64(c)).max
+ mask := ^uint64(0) >> (64 - n)
+
+ C := new(big.Int).SetUint64(c)
+
+ // Find largest multiple of c.
+ Mul := new(big.Int).Div(Max, C)
+ Mul.Mul(Mul, C)
+ mul := Mul.Uint64()
+
+ // Try some input values, mostly around multiples of c.
+ for _, x := range [...]uint64{0, 1,
+ c - 1, c, c + 1,
+ 2*c - 1, 2 * c, 2*c + 1,
+ mul - 1, mul, mul + 1,
+ uint64(1)<<n - 1,
+ } {
+ X := new(big.Int).SetUint64(x)
+ if X.Cmp(Max) > 0 {
+ continue
+ }
+ want := x%c == 0
+ mul := (x * m) & mask
+ rot := (mul>>uint(k) | mul<<(n-uint(k))) & mask
+ got := rot <= max
+ if want != got {
+ t.Errorf("unsigned divisible wrong for %d %% %d == 0: got %v, want %v (k=%d,m=%d,max=%d)\n", x, c, got, want, k, m, max)
+ }
+ }
+ }
+ }
+}
+
+func testDivisibleExhaustive(t *testing.T, n uint) {
+ minI := -int64(1) << (n - 1)
+ maxI := int64(1) << (n - 1)
+ for c := int64(1); c < maxI; c++ {
+ if !sdivisibleOK(n, int64(c)) {
+ continue
+ }
+ k := sdivisible(n, int64(c)).k
+ m := sdivisible(n, int64(c)).m
+ a := sdivisible(n, int64(c)).a
+ max := sdivisible(n, int64(c)).max
+ mask := ^uint64(0) >> (64 - n)
+ for i := minI; i < maxI; i++ {
+ want := i%c == 0
+ mul := (uint64(i)*m + a) & mask
+ rot := (mul>>uint(k) | mul<<(n-uint(k))) & mask
+ got := rot <= max
+ if want != got {
+ t.Errorf("signed divisible wrong for %d %% %d == 0: got %v, want %v (k=%d,m=%d,a=%d,max=%d)\n", i, c, got, want, k, m, a, max)
+ }
+ }
+ }
+}
+
+func TestDivisibleExhaustive8(t *testing.T) {
+ testDivisibleExhaustive(t, 8)
+}
+
+func TestDivisibleExhaustive16(t *testing.T) {
+ if testing.Short() {
+ t.Skip("slow test; skipping")
+ }
+ testDivisibleExhaustive(t, 16)
+}
+
+func TestDivisibleSigned(t *testing.T) {
+ One := new(big.Int).SetInt64(1)
+ for _, n := range [...]uint{8, 16, 32, 64} {
+ TwoNMinusOne := new(big.Int).Lsh(One, n-1)
+ Max := new(big.Int).Sub(TwoNMinusOne, One)
+ Min := new(big.Int).Neg(TwoNMinusOne)
+ for _, c := range [...]int64{
+ 3,
+ 5,
+ 6,
+ 7,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 17,
+ 1<<7 - 1,
+ 1<<7 + 1,
+ 1<<15 - 1,
+ 1<<15 + 1,
+ 1<<31 - 1,
+ 1<<31 + 1,
+ 1<<63 - 1,
+ } {
+ if c>>(n-1) != 0 {
+ continue // not appropriate for the given n.
+ }
+ if !sdivisibleOK(n, int64(c)) {
+ t.Errorf("expected n=%d c=%d to pass\n", n, c)
+ }
+ k := sdivisible(n, int64(c)).k
+ m := sdivisible(n, int64(c)).m
+ a := sdivisible(n, int64(c)).a
+ max := sdivisible(n, int64(c)).max
+ mask := ^uint64(0) >> (64 - n)
+
+ C := new(big.Int).SetInt64(c)
+
+ // Find largest multiple of c.
+ Mul := new(big.Int).Div(Max, C)
+ Mul.Mul(Mul, C)
+ mul := Mul.Int64()
+
+ // Try some input values, mostly around multiples of c.
+ for _, x := range [...]int64{
+ -1, 1,
+ -c - 1, -c, -c + 1, c - 1, c, c + 1,
+ -2*c - 1, -2 * c, -2*c + 1, 2*c - 1, 2 * c, 2*c + 1,
+ -mul - 1, -mul, -mul + 1, mul - 1, mul, mul + 1,
+ int64(1)<<(n-1) - 1, -int64(1) << (n - 1),
+ } {
+ X := new(big.Int).SetInt64(x)
+ if X.Cmp(Min) < 0 || X.Cmp(Max) > 0 {
+ continue
+ }
+ want := x%c == 0
+ mul := (uint64(x)*m + a) & mask
+ rot := (mul>>uint(k) | mul<<(n-uint(k))) & mask
+ got := rot <= max
+ if want != got {
+ t.Errorf("signed divisible wrong for %d %% %d == 0: got %v, want %v (k=%d,m=%d,a=%d,max=%d)\n", x, c, got, want, k, m, a, max)
+ }
+ }
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go
new file mode 100644
index 0000000..d1bad52
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/nilcheck.go
@@ -0,0 +1,336 @@
+// 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 (
+ "cmd/internal/objabi"
+ "cmd/internal/src"
+)
+
+// nilcheckelim eliminates unnecessary nil checks.
+// runs on machine-independent code.
+func nilcheckelim(f *Func) {
+ // A nil check is redundant if the same nil check was successful in a
+ // dominating block. The efficacy of this pass depends heavily on the
+ // efficacy of the cse pass.
+ sdom := f.Sdom()
+
+ // TODO: Eliminate more nil checks.
+ // We can recursively remove any chain of fixed offset calculations,
+ // i.e. struct fields and array elements, even with non-constant
+ // indices: x is non-nil iff x.a.b[i].c is.
+
+ type walkState int
+ const (
+ Work walkState = iota // process nil checks and traverse to dominees
+ ClearPtr // forget the fact that ptr is nil
+ )
+
+ type bp struct {
+ block *Block // block, or nil in ClearPtr state
+ ptr *Value // if non-nil, ptr that is to be cleared in ClearPtr state
+ op walkState
+ }
+
+ work := make([]bp, 0, 256)
+ work = append(work, bp{block: f.Entry})
+
+ // map from value ID to bool indicating if value is known to be non-nil
+ // in the current dominator path being walked. This slice is updated by
+ // walkStates to maintain the known non-nil values.
+ nonNilValues := make([]bool, f.NumValues())
+
+ // make an initial pass identifying any non-nil values
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ // a value resulting from taking the address of a
+ // value, or a value constructed from an offset of a
+ // non-nil ptr (OpAddPtr) implies it is non-nil
+ // We also assume unsafe pointer arithmetic generates non-nil pointers. See #27180.
+ // We assume that SlicePtr is non-nil because we do a bounds check
+ // before the slice access (and all cap>0 slices have a non-nil ptr). See #30366.
+ if v.Op == OpAddr || v.Op == OpLocalAddr || v.Op == OpAddPtr || v.Op == OpOffPtr || v.Op == OpAdd32 || v.Op == OpAdd64 || v.Op == OpSub32 || v.Op == OpSub64 || v.Op == OpSlicePtr {
+ nonNilValues[v.ID] = true
+ }
+ }
+ }
+
+ for changed := true; changed; {
+ changed = false
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ // phis whose arguments are all non-nil
+ // are non-nil
+ if v.Op == OpPhi {
+ argsNonNil := true
+ for _, a := range v.Args {
+ if !nonNilValues[a.ID] {
+ argsNonNil = false
+ break
+ }
+ }
+ if argsNonNil {
+ if !nonNilValues[v.ID] {
+ changed = true
+ }
+ nonNilValues[v.ID] = true
+ }
+ }
+ }
+ }
+ }
+
+ // allocate auxiliary date structures for computing store order
+ sset := f.newSparseSet(f.NumValues())
+ defer f.retSparseSet(sset)
+ storeNumber := make([]int32, f.NumValues())
+
+ // perform a depth first walk of the dominee tree
+ for len(work) > 0 {
+ node := work[len(work)-1]
+ work = work[:len(work)-1]
+
+ switch node.op {
+ case Work:
+ b := node.block
+
+ // First, see if we're dominated by an explicit nil check.
+ if len(b.Preds) == 1 {
+ p := b.Preds[0].b
+ if p.Kind == BlockIf && p.Controls[0].Op == OpIsNonNil && p.Succs[0].b == b {
+ if ptr := p.Controls[0].Args[0]; !nonNilValues[ptr.ID] {
+ nonNilValues[ptr.ID] = true
+ work = append(work, bp{op: ClearPtr, ptr: ptr})
+ }
+ }
+ }
+
+ // Next, order values in the current block w.r.t. stores.
+ b.Values = storeOrder(b.Values, sset, storeNumber)
+
+ pendingLines := f.cachedLineStarts // Holds statement boundaries that need to be moved to a new value/block
+ pendingLines.clear()
+
+ // Next, process values in the block.
+ i := 0
+ for _, v := range b.Values {
+ b.Values[i] = v
+ i++
+ switch v.Op {
+ case OpIsNonNil:
+ ptr := v.Args[0]
+ if nonNilValues[ptr.ID] {
+ if v.Pos.IsStmt() == src.PosIsStmt { // Boolean true is a terrible statement boundary.
+ pendingLines.add(v.Pos)
+ v.Pos = v.Pos.WithNotStmt()
+ }
+ // This is a redundant explicit nil check.
+ v.reset(OpConstBool)
+ v.AuxInt = 1 // true
+ }
+ case OpNilCheck:
+ ptr := v.Args[0]
+ if nonNilValues[ptr.ID] {
+ // This is a redundant implicit nil check.
+ // Logging in the style of the former compiler -- and omit line 1,
+ // which is usually in generated code.
+ if f.fe.Debug_checknil() && v.Pos.Line() > 1 {
+ f.Warnl(v.Pos, "removed nil check")
+ }
+ if v.Pos.IsStmt() == src.PosIsStmt { // About to lose a statement boundary
+ pendingLines.add(v.Pos)
+ }
+ v.reset(OpUnknown)
+ f.freeValue(v)
+ i--
+ continue
+ }
+ // Record the fact that we know ptr is non nil, and remember to
+ // undo that information when this dominator subtree is done.
+ nonNilValues[ptr.ID] = true
+ work = append(work, bp{op: ClearPtr, ptr: ptr})
+ fallthrough // a non-eliminated nil check might be a good place for a statement boundary.
+ default:
+ if v.Pos.IsStmt() != src.PosNotStmt && !isPoorStatementOp(v.Op) && pendingLines.contains(v.Pos) {
+ v.Pos = v.Pos.WithIsStmt()
+ pendingLines.remove(v.Pos)
+ }
+ }
+ }
+ // This reduces the lost statement count in "go" by 5 (out of 500 total).
+ for j := 0; j < i; j++ { // is this an ordering problem?
+ v := b.Values[j]
+ if v.Pos.IsStmt() != src.PosNotStmt && !isPoorStatementOp(v.Op) && pendingLines.contains(v.Pos) {
+ v.Pos = v.Pos.WithIsStmt()
+ pendingLines.remove(v.Pos)
+ }
+ }
+ if pendingLines.contains(b.Pos) {
+ b.Pos = b.Pos.WithIsStmt()
+ pendingLines.remove(b.Pos)
+ }
+ b.truncateValues(i)
+
+ // Add all dominated blocks to the work list.
+ for w := sdom[node.block.ID].child; w != nil; w = sdom[w.ID].sibling {
+ work = append(work, bp{op: Work, block: w})
+ }
+
+ case ClearPtr:
+ nonNilValues[node.ptr.ID] = false
+ continue
+ }
+ }
+}
+
+// All platforms are guaranteed to fault if we load/store to anything smaller than this address.
+//
+// This should agree with minLegalPointer in the runtime.
+const minZeroPage = 4096
+
+// faultOnLoad is true if a load to an address below minZeroPage will trigger a SIGSEGV.
+var faultOnLoad = objabi.GOOS != "aix"
+
+// nilcheckelim2 eliminates unnecessary nil checks.
+// Runs after lowering and scheduling.
+func nilcheckelim2(f *Func) {
+ unnecessary := f.newSparseMap(f.NumValues()) // map from pointer that will be dereferenced to index of dereferencing value in b.Values[]
+ defer f.retSparseMap(unnecessary)
+
+ pendingLines := f.cachedLineStarts // Holds statement boundaries that need to be moved to a new value/block
+
+ for _, b := range f.Blocks {
+ // Walk the block backwards. Find instructions that will fault if their
+ // input pointer is nil. Remove nil checks on those pointers, as the
+ // faulting instruction effectively does the nil check for free.
+ unnecessary.clear()
+ pendingLines.clear()
+ // Optimization: keep track of removed nilcheck with smallest index
+ firstToRemove := len(b.Values)
+ for i := len(b.Values) - 1; i >= 0; i-- {
+ v := b.Values[i]
+ if opcodeTable[v.Op].nilCheck && unnecessary.contains(v.Args[0].ID) {
+ if f.fe.Debug_checknil() && v.Pos.Line() > 1 {
+ f.Warnl(v.Pos, "removed nil check")
+ }
+ // For bug 33724, policy is that we might choose to bump an existing position
+ // off the faulting load/store in favor of the one from the nil check.
+
+ // Iteration order means that first nilcheck in the chain wins, others
+ // are bumped into the ordinary statement preservation algorithm.
+ u := b.Values[unnecessary.get(v.Args[0].ID)]
+ if !u.Pos.SameFileAndLine(v.Pos) {
+ if u.Pos.IsStmt() == src.PosIsStmt {
+ pendingLines.add(u.Pos)
+ }
+ u.Pos = v.Pos
+ } else if v.Pos.IsStmt() == src.PosIsStmt {
+ pendingLines.add(v.Pos)
+ }
+
+ v.reset(OpUnknown)
+ firstToRemove = i
+ continue
+ }
+ if v.Type.IsMemory() || v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() {
+ if v.Op == OpVarKill || v.Op == OpVarLive || (v.Op == OpVarDef && !v.Aux.(GCNode).Typ().HasPointers()) {
+ // These ops don't really change memory.
+ continue
+ // Note: OpVarDef requires that the defined variable not have pointers.
+ // We need to make sure that there's no possible faulting
+ // instruction between a VarDef and that variable being
+ // fully initialized. If there was, then anything scanning
+ // the stack during the handling of that fault will see
+ // a live but uninitialized pointer variable on the stack.
+ //
+ // If we have:
+ //
+ // NilCheck p
+ // VarDef x
+ // x = *p
+ //
+ // We can't rewrite that to
+ //
+ // VarDef x
+ // NilCheck p
+ // x = *p
+ //
+ // Particularly, even though *p faults on p==nil, we still
+ // have to do the explicit nil check before the VarDef.
+ // See issue #32288.
+ }
+ // This op changes memory. Any faulting instruction after v that
+ // we've recorded in the unnecessary map is now obsolete.
+ unnecessary.clear()
+ }
+
+ // Find any pointers that this op is guaranteed to fault on if nil.
+ var ptrstore [2]*Value
+ ptrs := ptrstore[:0]
+ if opcodeTable[v.Op].faultOnNilArg0 && (faultOnLoad || v.Type.IsMemory()) {
+ // On AIX, only writing will fault.
+ ptrs = append(ptrs, v.Args[0])
+ }
+ if opcodeTable[v.Op].faultOnNilArg1 && (faultOnLoad || (v.Type.IsMemory() && v.Op != OpPPC64LoweredMove)) {
+ // On AIX, only writing will fault.
+ // LoweredMove is a special case because it's considered as a "mem" as it stores on arg0 but arg1 is accessed as a load and should be checked.
+ ptrs = append(ptrs, v.Args[1])
+ }
+
+ for _, ptr := range ptrs {
+ // Check to make sure the offset is small.
+ switch opcodeTable[v.Op].auxType {
+ case auxSym:
+ if v.Aux != nil {
+ continue
+ }
+ case auxSymOff:
+ if v.Aux != nil || v.AuxInt < 0 || v.AuxInt >= minZeroPage {
+ continue
+ }
+ case auxSymValAndOff:
+ off := ValAndOff(v.AuxInt).Off()
+ if v.Aux != nil || off < 0 || off >= minZeroPage {
+ continue
+ }
+ case auxInt32:
+ // Mips uses this auxType for atomic add constant. It does not affect the effective address.
+ case auxInt64:
+ // ARM uses this auxType for duffcopy/duffzero/alignment info.
+ // It does not affect the effective address.
+ case auxNone:
+ // offset is zero.
+ default:
+ v.Fatalf("can't handle aux %s (type %d) yet\n", v.auxString(), int(opcodeTable[v.Op].auxType))
+ }
+ // This instruction is guaranteed to fault if ptr is nil.
+ // Any previous nil check op is unnecessary.
+ unnecessary.set(ptr.ID, int32(i), src.NoXPos)
+ }
+ }
+ // Remove values we've clobbered with OpUnknown.
+ i := firstToRemove
+ for j := i; j < len(b.Values); j++ {
+ v := b.Values[j]
+ if v.Op != OpUnknown {
+ if !notStmtBoundary(v.Op) && pendingLines.contains(v.Pos) { // Late in compilation, so any remaining NotStmt values are probably okay now.
+ v.Pos = v.Pos.WithIsStmt()
+ pendingLines.remove(v.Pos)
+ }
+ b.Values[i] = v
+ i++
+ }
+ }
+
+ if pendingLines.contains(b.Pos) {
+ b.Pos = b.Pos.WithIsStmt()
+ }
+
+ b.truncateValues(i)
+
+ // TODO: if b.Kind == BlockPlain, start the analysis in the subsequent block to find
+ // more unnecessary nil checks. Would fix test/nilptr3.go:159.
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/nilcheck_test.go b/src/cmd/compile/internal/ssa/nilcheck_test.go
new file mode 100644
index 0000000..16d9461
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/nilcheck_test.go
@@ -0,0 +1,434 @@
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "strconv"
+ "testing"
+)
+
+func BenchmarkNilCheckDeep1(b *testing.B) { benchmarkNilCheckDeep(b, 1) }
+func BenchmarkNilCheckDeep10(b *testing.B) { benchmarkNilCheckDeep(b, 10) }
+func BenchmarkNilCheckDeep100(b *testing.B) { benchmarkNilCheckDeep(b, 100) }
+func BenchmarkNilCheckDeep1000(b *testing.B) { benchmarkNilCheckDeep(b, 1000) }
+func BenchmarkNilCheckDeep10000(b *testing.B) { benchmarkNilCheckDeep(b, 10000) }
+
+// benchmarkNilCheckDeep is a stress test of nilcheckelim.
+// It uses the worst possible input: A linear string of
+// nil checks, none of which can be eliminated.
+// Run with multiple depths to observe big-O behavior.
+func benchmarkNilCheckDeep(b *testing.B, depth int) {
+ c := testConfig(b)
+ ptrType := c.config.Types.BytePtr
+
+ var blocs []bloc
+ blocs = append(blocs,
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto(blockn(0)),
+ ),
+ )
+ for i := 0; i < depth; i++ {
+ blocs = append(blocs,
+ Bloc(blockn(i),
+ Valu(ptrn(i), OpAddr, ptrType, 0, nil, "sb"),
+ Valu(booln(i), OpIsNonNil, c.config.Types.Bool, 0, nil, ptrn(i)),
+ If(booln(i), blockn(i+1), "exit"),
+ ),
+ )
+ }
+ blocs = append(blocs,
+ Bloc(blockn(depth), Goto("exit")),
+ Bloc("exit", Exit("mem")),
+ )
+
+ fun := c.Fun("entry", blocs...)
+
+ CheckFunc(fun.f)
+ b.SetBytes(int64(depth)) // helps for eyeballing linearity
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ nilcheckelim(fun.f)
+ }
+}
+
+func blockn(n int) string { return "b" + strconv.Itoa(n) }
+func ptrn(n int) string { return "p" + strconv.Itoa(n) }
+func booln(n int) string { return "c" + strconv.Itoa(n) }
+
+func isNilCheck(b *Block) bool {
+ return b.Kind == BlockIf && b.Controls[0].Op == OpIsNonNil
+}
+
+// TestNilcheckSimple verifies that a second repeated nilcheck is removed.
+func TestNilcheckSimple(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
+ Valu("bool1", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool1", "secondCheck", "exit")),
+ Bloc("secondCheck",
+ Valu("bool2", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool2", "extra", "exit")),
+ Bloc("extra",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ nilcheckelim(fun.f)
+
+ // clean up the removed nil check
+ fuse(fun.f, fuseTypePlain)
+ deadcode(fun.f)
+
+ CheckFunc(fun.f)
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["secondCheck"] && isNilCheck(b) {
+ t.Errorf("secondCheck was not eliminated")
+ }
+ }
+}
+
+// TestNilcheckDomOrder ensures that the nil check elimination isn't dependent
+// on the order of the dominees.
+func TestNilcheckDomOrder(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
+ Valu("bool1", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool1", "secondCheck", "exit")),
+ Bloc("exit",
+ Exit("mem")),
+ Bloc("secondCheck",
+ Valu("bool2", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool2", "extra", "exit")),
+ Bloc("extra",
+ Goto("exit")))
+
+ CheckFunc(fun.f)
+ nilcheckelim(fun.f)
+
+ // clean up the removed nil check
+ fuse(fun.f, fuseTypePlain)
+ deadcode(fun.f)
+
+ CheckFunc(fun.f)
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["secondCheck"] && isNilCheck(b) {
+ t.Errorf("secondCheck was not eliminated")
+ }
+ }
+}
+
+// TestNilcheckAddr verifies that nilchecks of OpAddr constructed values are removed.
+func TestNilcheckAddr(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("ptr1", OpAddr, ptrType, 0, nil, "sb"),
+ Valu("bool1", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool1", "extra", "exit")),
+ Bloc("extra",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ nilcheckelim(fun.f)
+
+ // clean up the removed nil check
+ fuse(fun.f, fuseTypePlain)
+ deadcode(fun.f)
+
+ CheckFunc(fun.f)
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["checkPtr"] && isNilCheck(b) {
+ t.Errorf("checkPtr was not eliminated")
+ }
+ }
+}
+
+// TestNilcheckAddPtr verifies that nilchecks of OpAddPtr constructed values are removed.
+func TestNilcheckAddPtr(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("off", OpConst64, c.config.Types.Int64, 20, nil),
+ Valu("ptr1", OpAddPtr, ptrType, 0, nil, "sb", "off"),
+ Valu("bool1", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool1", "extra", "exit")),
+ Bloc("extra",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ nilcheckelim(fun.f)
+
+ // clean up the removed nil check
+ fuse(fun.f, fuseTypePlain)
+ deadcode(fun.f)
+
+ CheckFunc(fun.f)
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["checkPtr"] && isNilCheck(b) {
+ t.Errorf("checkPtr was not eliminated")
+ }
+ }
+}
+
+// TestNilcheckPhi tests that nil checks of phis, for which all values are known to be
+// non-nil are removed.
+func TestNilcheckPhi(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
+ Valu("baddr", OpLocalAddr, c.config.Types.Bool, 0, "b", "sp", "mem"),
+ Valu("bool1", OpLoad, c.config.Types.Bool, 0, nil, "baddr", "mem"),
+ If("bool1", "b1", "b2")),
+ Bloc("b1",
+ Valu("ptr1", OpAddr, ptrType, 0, nil, "sb"),
+ Goto("checkPtr")),
+ Bloc("b2",
+ Valu("ptr2", OpAddr, ptrType, 0, nil, "sb"),
+ Goto("checkPtr")),
+ // both ptr1 and ptr2 are guaranteed non-nil here
+ Bloc("checkPtr",
+ Valu("phi", OpPhi, ptrType, 0, nil, "ptr1", "ptr2"),
+ Valu("bool2", OpIsNonNil, c.config.Types.Bool, 0, nil, "phi"),
+ If("bool2", "extra", "exit")),
+ Bloc("extra",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ nilcheckelim(fun.f)
+
+ // clean up the removed nil check
+ fuse(fun.f, fuseTypePlain)
+ deadcode(fun.f)
+
+ CheckFunc(fun.f)
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["checkPtr"] && isNilCheck(b) {
+ t.Errorf("checkPtr was not eliminated")
+ }
+ }
+}
+
+// TestNilcheckKeepRemove verifies that duplicate checks of the same pointer
+// are removed, but checks of different pointers are not.
+func TestNilcheckKeepRemove(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
+ Valu("bool1", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool1", "differentCheck", "exit")),
+ Bloc("differentCheck",
+ Valu("ptr2", OpLoad, ptrType, 0, nil, "sb", "mem"),
+ Valu("bool2", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr2"),
+ If("bool2", "secondCheck", "exit")),
+ Bloc("secondCheck",
+ Valu("bool3", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool3", "extra", "exit")),
+ Bloc("extra",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ nilcheckelim(fun.f)
+
+ // clean up the removed nil check
+ fuse(fun.f, fuseTypePlain)
+ deadcode(fun.f)
+
+ CheckFunc(fun.f)
+ foundDifferentCheck := false
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["secondCheck"] && isNilCheck(b) {
+ t.Errorf("secondCheck was not eliminated")
+ }
+ if b == fun.blocks["differentCheck"] && isNilCheck(b) {
+ foundDifferentCheck = true
+ }
+ }
+ if !foundDifferentCheck {
+ t.Errorf("removed differentCheck, but shouldn't have")
+ }
+}
+
+// TestNilcheckInFalseBranch tests that nil checks in the false branch of a nilcheck
+// block are *not* removed.
+func TestNilcheckInFalseBranch(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
+ Valu("bool1", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool1", "extra", "secondCheck")),
+ Bloc("secondCheck",
+ Valu("bool2", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool2", "extra", "thirdCheck")),
+ Bloc("thirdCheck",
+ Valu("bool3", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool3", "extra", "exit")),
+ Bloc("extra",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ nilcheckelim(fun.f)
+
+ // clean up the removed nil check
+ fuse(fun.f, fuseTypePlain)
+ deadcode(fun.f)
+
+ CheckFunc(fun.f)
+ foundSecondCheck := false
+ foundThirdCheck := false
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["secondCheck"] && isNilCheck(b) {
+ foundSecondCheck = true
+ }
+ if b == fun.blocks["thirdCheck"] && isNilCheck(b) {
+ foundThirdCheck = true
+ }
+ }
+ if !foundSecondCheck {
+ t.Errorf("removed secondCheck, but shouldn't have [false branch]")
+ }
+ if !foundThirdCheck {
+ t.Errorf("removed thirdCheck, but shouldn't have [false branch]")
+ }
+}
+
+// TestNilcheckUser verifies that a user nil check that dominates a generated nil check
+// wil remove the generated nil check.
+func TestNilcheckUser(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
+ Valu("nilptr", OpConstNil, ptrType, 0, nil),
+ Valu("bool1", OpNeqPtr, c.config.Types.Bool, 0, nil, "ptr1", "nilptr"),
+ If("bool1", "secondCheck", "exit")),
+ Bloc("secondCheck",
+ Valu("bool2", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool2", "extra", "exit")),
+ Bloc("extra",
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ // we need the opt here to rewrite the user nilcheck
+ opt(fun.f)
+ nilcheckelim(fun.f)
+
+ // clean up the removed nil check
+ fuse(fun.f, fuseTypePlain)
+ deadcode(fun.f)
+
+ CheckFunc(fun.f)
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["secondCheck"] && isNilCheck(b) {
+ t.Errorf("secondCheck was not eliminated")
+ }
+ }
+}
+
+// TestNilcheckBug reproduces a bug in nilcheckelim found by compiling math/big
+func TestNilcheckBug(t *testing.T) {
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Goto("checkPtr")),
+ Bloc("checkPtr",
+ Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
+ Valu("nilptr", OpConstNil, ptrType, 0, nil),
+ Valu("bool1", OpNeqPtr, c.config.Types.Bool, 0, nil, "ptr1", "nilptr"),
+ If("bool1", "secondCheck", "couldBeNil")),
+ Bloc("couldBeNil",
+ Goto("secondCheck")),
+ Bloc("secondCheck",
+ Valu("bool2", OpIsNonNil, c.config.Types.Bool, 0, nil, "ptr1"),
+ If("bool2", "extra", "exit")),
+ Bloc("extra",
+ // prevent fuse from eliminating this block
+ Valu("store", OpStore, types.TypeMem, 0, ptrType, "ptr1", "nilptr", "mem"),
+ Goto("exit")),
+ Bloc("exit",
+ Valu("phi", OpPhi, types.TypeMem, 0, nil, "mem", "store"),
+ Exit("phi")))
+
+ CheckFunc(fun.f)
+ // we need the opt here to rewrite the user nilcheck
+ opt(fun.f)
+ nilcheckelim(fun.f)
+
+ // clean up the removed nil check
+ fuse(fun.f, fuseTypePlain)
+ deadcode(fun.f)
+
+ CheckFunc(fun.f)
+ foundSecondCheck := false
+ for _, b := range fun.f.Blocks {
+ if b == fun.blocks["secondCheck"] && isNilCheck(b) {
+ foundSecondCheck = true
+ }
+ }
+ if !foundSecondCheck {
+ t.Errorf("secondCheck was eliminated, but shouldn't have")
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/numberlines.go b/src/cmd/compile/internal/ssa/numberlines.go
new file mode 100644
index 0000000..f4e62b8
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/numberlines.go
@@ -0,0 +1,271 @@
+// Copyright 2018 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 (
+ "cmd/internal/obj"
+ "cmd/internal/src"
+ "fmt"
+ "sort"
+)
+
+func isPoorStatementOp(op Op) bool {
+ switch op {
+ // Note that Nilcheck often vanishes, but when it doesn't, you'd love to start the statement there
+ // so that a debugger-user sees the stop before the panic, and can examine the value.
+ case OpAddr, OpLocalAddr, OpOffPtr, OpStructSelect, OpPhi, OpITab, OpIData,
+ OpIMake, OpStringMake, OpSliceMake, OpStructMake0, OpStructMake1, OpStructMake2, OpStructMake3, OpStructMake4,
+ OpConstBool, OpConst8, OpConst16, OpConst32, OpConst64, OpConst32F, OpConst64F:
+ return true
+ }
+ return false
+}
+
+// LosesStmtMark reports whether a prog with op as loses its statement mark on the way to DWARF.
+// The attributes from some opcodes are lost in translation.
+// TODO: this is an artifact of how funcpctab combines information for instructions at a single PC.
+// Should try to fix it there.
+func LosesStmtMark(as obj.As) bool {
+ // is_stmt does not work for these; it DOES for ANOP even though that generates no code.
+ return as == obj.APCDATA || as == obj.AFUNCDATA
+}
+
+// nextGoodStatementIndex returns an index at i or later that is believed
+// to be a good place to start the statement for b. This decision is
+// based on v's Op, the possibility of a better later operation, and
+// whether the values following i are the same line as v.
+// If a better statement index isn't found, then i is returned.
+func nextGoodStatementIndex(v *Value, i int, b *Block) int {
+ // If the value is the last one in the block, too bad, it will have to do
+ // (this assumes that the value ordering vaguely corresponds to the source
+ // program execution order, which tends to be true directly after ssa is
+ // first built.
+ if i >= len(b.Values)-1 {
+ return i
+ }
+ // Skip the likely-ephemeral/fragile opcodes expected to vanish in a rewrite.
+ if !isPoorStatementOp(v.Op) {
+ return i
+ }
+ // Look ahead to see what the line number is on the next thing that could be a boundary.
+ for j := i + 1; j < len(b.Values); j++ {
+ u := b.Values[j]
+ if u.Pos.IsStmt() == src.PosNotStmt { // ignore non-statements
+ continue
+ }
+ if u.Pos.SameFileAndLine(v.Pos) {
+ if isPoorStatementOp(u.Op) {
+ continue // Keep looking, this is also not a good statement op
+ }
+ return j
+ }
+ return i
+ }
+ return i
+}
+
+// notStmtBoundary reports whether a value with opcode op can never be a statement
+// boundary. Such values don't correspond to a user's understanding of a
+// statement boundary.
+func notStmtBoundary(op Op) bool {
+ switch op {
+ case OpCopy, OpPhi, OpVarKill, OpVarDef, OpVarLive, OpUnknown, OpFwdRef, OpArg:
+ return true
+ }
+ return false
+}
+
+func (b *Block) FirstPossibleStmtValue() *Value {
+ for _, v := range b.Values {
+ if notStmtBoundary(v.Op) {
+ continue
+ }
+ return v
+ }
+ return nil
+}
+
+func flc(p src.XPos) string {
+ if p == src.NoXPos {
+ return "none"
+ }
+ return fmt.Sprintf("(%d):%d:%d", p.FileIndex(), p.Line(), p.Col())
+}
+
+type fileAndPair struct {
+ f int32
+ lp lineRange
+}
+
+type fileAndPairs []fileAndPair
+
+func (fap fileAndPairs) Len() int {
+ return len(fap)
+}
+func (fap fileAndPairs) Less(i, j int) bool {
+ return fap[i].f < fap[j].f
+}
+func (fap fileAndPairs) Swap(i, j int) {
+ fap[i], fap[j] = fap[j], fap[i]
+}
+
+// -d=ssa/number_lines/stats=1 (that bit) for line and file distribution statistics
+// -d=ssa/number_lines/debug for information about why particular values are marked as statements.
+func numberLines(f *Func) {
+ po := f.Postorder()
+ endlines := make(map[ID]src.XPos)
+ ranges := make(map[int]lineRange)
+ note := func(p src.XPos) {
+ line := uint32(p.Line())
+ i := int(p.FileIndex())
+ lp, found := ranges[i]
+ change := false
+ if line < lp.first || !found {
+ lp.first = line
+ change = true
+ }
+ if line > lp.last {
+ lp.last = line
+ change = true
+ }
+ if change {
+ ranges[i] = lp
+ }
+ }
+
+ // Visit in reverse post order so that all non-loop predecessors come first.
+ for j := len(po) - 1; j >= 0; j-- {
+ b := po[j]
+ // Find the first interesting position and check to see if it differs from any predecessor
+ firstPos := src.NoXPos
+ firstPosIndex := -1
+ if b.Pos.IsStmt() != src.PosNotStmt {
+ note(b.Pos)
+ }
+ for i := 0; i < len(b.Values); i++ {
+ v := b.Values[i]
+ if v.Pos.IsStmt() != src.PosNotStmt {
+ note(v.Pos)
+ // skip ahead to better instruction for this line if possible
+ i = nextGoodStatementIndex(v, i, b)
+ v = b.Values[i]
+ firstPosIndex = i
+ firstPos = v.Pos
+ v.Pos = firstPos.WithDefaultStmt() // default to default
+ break
+ }
+ }
+
+ if firstPosIndex == -1 { // Effectively empty block, check block's own Pos, consider preds.
+ line := src.NoXPos
+ for _, p := range b.Preds {
+ pbi := p.Block().ID
+ if !endlines[pbi].SameFileAndLine(line) {
+ if line == src.NoXPos {
+ line = endlines[pbi]
+ continue
+ } else {
+ line = src.NoXPos
+ break
+ }
+
+ }
+ }
+ // If the block has no statement itself and is effectively empty, tag it w/ predecessor(s) but not as a statement
+ if b.Pos.IsStmt() == src.PosNotStmt {
+ b.Pos = line
+ endlines[b.ID] = line
+ continue
+ }
+ // If the block differs from its predecessors, mark it as a statement
+ if line == src.NoXPos || !line.SameFileAndLine(b.Pos) {
+ b.Pos = b.Pos.WithIsStmt()
+ if f.pass.debug > 0 {
+ fmt.Printf("Mark stmt effectively-empty-block %s %s %s\n", f.Name, b, flc(b.Pos))
+ }
+ }
+ endlines[b.ID] = b.Pos
+ continue
+ }
+ // check predecessors for any difference; if firstPos differs, then it is a boundary.
+ if len(b.Preds) == 0 { // Don't forget the entry block
+ b.Values[firstPosIndex].Pos = firstPos.WithIsStmt()
+ if f.pass.debug > 0 {
+ fmt.Printf("Mark stmt entry-block %s %s %s %s\n", f.Name, b, b.Values[firstPosIndex], flc(firstPos))
+ }
+ } else { // differing pred
+ for _, p := range b.Preds {
+ pbi := p.Block().ID
+ if !endlines[pbi].SameFileAndLine(firstPos) {
+ b.Values[firstPosIndex].Pos = firstPos.WithIsStmt()
+ if f.pass.debug > 0 {
+ fmt.Printf("Mark stmt differing-pred %s %s %s %s, different=%s ending %s\n",
+ f.Name, b, b.Values[firstPosIndex], flc(firstPos), p.Block(), flc(endlines[pbi]))
+ }
+ break
+ }
+ }
+ }
+ // iterate forward setting each new (interesting) position as a statement boundary.
+ for i := firstPosIndex + 1; i < len(b.Values); i++ {
+ v := b.Values[i]
+ if v.Pos.IsStmt() == src.PosNotStmt {
+ continue
+ }
+ note(v.Pos)
+ // skip ahead if possible
+ i = nextGoodStatementIndex(v, i, b)
+ v = b.Values[i]
+ if !v.Pos.SameFileAndLine(firstPos) {
+ if f.pass.debug > 0 {
+ fmt.Printf("Mark stmt new line %s %s %s %s prev pos = %s\n", f.Name, b, v, flc(v.Pos), flc(firstPos))
+ }
+ firstPos = v.Pos
+ v.Pos = v.Pos.WithIsStmt()
+ } else {
+ v.Pos = v.Pos.WithDefaultStmt()
+ }
+ }
+ if b.Pos.IsStmt() != src.PosNotStmt && !b.Pos.SameFileAndLine(firstPos) {
+ if f.pass.debug > 0 {
+ fmt.Printf("Mark stmt end of block differs %s %s %s prev pos = %s\n", f.Name, b, flc(b.Pos), flc(firstPos))
+ }
+ b.Pos = b.Pos.WithIsStmt()
+ firstPos = b.Pos
+ }
+ endlines[b.ID] = firstPos
+ }
+ if f.pass.stats&1 != 0 {
+ // Report summary statistics on the shape of the sparse map about to be constructed
+ // TODO use this information to make sparse maps faster.
+ var entries fileAndPairs
+ for k, v := range ranges {
+ entries = append(entries, fileAndPair{int32(k), v})
+ }
+ sort.Sort(entries)
+ total := uint64(0) // sum over files of maxline(file) - minline(file)
+ maxfile := int32(0) // max(file indices)
+ minline := uint32(0xffffffff) // min over files of minline(file)
+ maxline := uint32(0) // max over files of maxline(file)
+ for _, v := range entries {
+ if f.pass.stats > 1 {
+ f.LogStat("file", v.f, "low", v.lp.first, "high", v.lp.last)
+ }
+ total += uint64(v.lp.last - v.lp.first)
+ if maxfile < v.f {
+ maxfile = v.f
+ }
+ if minline > v.lp.first {
+ minline = v.lp.first
+ }
+ if maxline < v.lp.last {
+ maxline = v.lp.last
+ }
+ }
+ f.LogStat("SUM_LINE_RANGE", total, "MAXMIN_LINE_RANGE", maxline-minline, "MAXFILE", maxfile, "NFILES", len(entries))
+ }
+ // cachedLineStarts is an empty sparse map for values that are included within ranges.
+ f.cachedLineStarts = newXposmap(ranges)
+}
diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go
new file mode 100644
index 0000000..d167335
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/op.go
@@ -0,0 +1,405 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "cmd/internal/obj"
+ "fmt"
+)
+
+// An Op encodes the specific operation that a Value performs.
+// Opcodes' semantics can be modified by the type and aux fields of the Value.
+// For instance, OpAdd can be 32 or 64 bit, signed or unsigned, float or complex, depending on Value.Type.
+// Semantics of each op are described in the opcode files in gen/*Ops.go.
+// There is one file for generic (architecture-independent) ops and one file
+// for each architecture.
+type Op int32
+
+type opInfo struct {
+ name string
+ reg regInfo
+ auxType auxType
+ argLen int32 // the number of arguments, -1 if variable length
+ asm obj.As
+ generic bool // this is a generic (arch-independent) opcode
+ rematerializeable bool // this op is rematerializeable
+ commutative bool // this operation is commutative (e.g. addition)
+ resultInArg0 bool // (first, if a tuple) output of v and v.Args[0] must be allocated to the same register
+ resultNotInArgs bool // outputs must not be allocated to the same registers as inputs
+ clobberFlags bool // this op clobbers flags register
+ call bool // is a function call
+ nilCheck bool // this op is a nil check on arg0
+ faultOnNilArg0 bool // this op will fault if arg0 is nil (and aux encodes a small offset)
+ faultOnNilArg1 bool // this op will fault if arg1 is nil (and aux encodes a small offset)
+ usesScratch bool // this op requires scratch memory space
+ hasSideEffects bool // for "reasons", not to be eliminated. E.g., atomic store, #19182.
+ zeroWidth bool // op never translates into any machine code. example: copy, which may sometimes translate to machine code, is not zero-width.
+ unsafePoint bool // this op is an unsafe point, i.e. not safe for async preemption
+ symEffect SymEffect // effect this op has on symbol in aux
+ scale uint8 // amd64/386 indexed load scale
+}
+
+type inputInfo struct {
+ idx int // index in Args array
+ regs regMask // allowed input registers
+}
+
+type outputInfo struct {
+ idx int // index in output tuple
+ regs regMask // allowed output registers
+}
+
+type regInfo struct {
+ // inputs encodes the register restrictions for an instruction's inputs.
+ // Each entry specifies an allowed register set for a particular input.
+ // They are listed in the order in which regalloc should pick a register
+ // from the register set (most constrained first).
+ // Inputs which do not need registers are not listed.
+ inputs []inputInfo
+ // clobbers encodes the set of registers that are overwritten by
+ // the instruction (other than the output registers).
+ clobbers regMask
+ // outputs is the same as inputs, but for the outputs of the instruction.
+ outputs []outputInfo
+}
+
+type auxType int8
+
+type Param struct {
+ Type *types.Type
+ Offset int32 // TODO someday this will be a register
+}
+
+type AuxCall struct {
+ Fn *obj.LSym
+ args []Param // Includes receiver for method calls. Does NOT include hidden closure pointer.
+ results []Param
+}
+
+// ResultForOffset returns the index of the result at a particular offset among the results
+// This does not include the mem result for the call opcode.
+func (a *AuxCall) ResultForOffset(offset int64) int64 {
+ which := int64(-1)
+ for i := int64(0); i < a.NResults(); i++ { // note aux NResults does not include mem result.
+ if a.OffsetOfResult(i) == offset {
+ which = i
+ break
+ }
+ }
+ return which
+}
+
+// OffsetOfResult returns the SP offset of result which (indexed 0, 1, etc).
+func (a *AuxCall) OffsetOfResult(which int64) int64 {
+ return int64(a.results[which].Offset)
+}
+
+// OffsetOfArg returns the SP offset of argument which (indexed 0, 1, etc).
+func (a *AuxCall) OffsetOfArg(which int64) int64 {
+ return int64(a.args[which].Offset)
+}
+
+// TypeOfResult returns the type of result which (indexed 0, 1, etc).
+func (a *AuxCall) TypeOfResult(which int64) *types.Type {
+ return a.results[which].Type
+}
+
+// TypeOfArg returns the type of argument which (indexed 0, 1, etc).
+func (a *AuxCall) TypeOfArg(which int64) *types.Type {
+ return a.args[which].Type
+}
+
+// SizeOfResult returns the size of result which (indexed 0, 1, etc).
+func (a *AuxCall) SizeOfResult(which int64) int64 {
+ return a.TypeOfResult(which).Width
+}
+
+// SizeOfArg returns the size of argument which (indexed 0, 1, etc).
+func (a *AuxCall) SizeOfArg(which int64) int64 {
+ return a.TypeOfArg(which).Width
+}
+
+// NResults returns the number of results
+func (a *AuxCall) NResults() int64 {
+ return int64(len(a.results))
+}
+
+// LateExpansionResultType returns the result type (including trailing mem)
+// for a call that will be expanded later in the SSA phase.
+func (a *AuxCall) LateExpansionResultType() *types.Type {
+ var tys []*types.Type
+ for i := int64(0); i < a.NResults(); i++ {
+ tys = append(tys, a.TypeOfResult(i))
+ }
+ tys = append(tys, types.TypeMem)
+ return types.NewResults(tys)
+}
+
+// NArgs returns the number of arguments
+func (a *AuxCall) NArgs() int64 {
+ return int64(len(a.args))
+}
+
+// String returns
+// "AuxCall{<fn>(<args>)}" if len(results) == 0;
+// "AuxCall{<fn>(<args>)<results[0]>}" if len(results) == 1;
+// "AuxCall{<fn>(<args>)(<results>)}" otherwise.
+func (a *AuxCall) String() string {
+ var fn string
+ if a.Fn == nil {
+ fn = "AuxCall{nil" // could be interface/closure etc.
+ } else {
+ fn = fmt.Sprintf("AuxCall{%v", a.Fn)
+ }
+
+ if len(a.args) == 0 {
+ fn += "()"
+ } else {
+ s := "("
+ for _, arg := range a.args {
+ fn += fmt.Sprintf("%s[%v,%v]", s, arg.Type, arg.Offset)
+ s = ","
+ }
+ fn += ")"
+ }
+
+ if len(a.results) > 0 { // usual is zero or one; only some RT calls have more than one.
+ if len(a.results) == 1 {
+ fn += fmt.Sprintf("[%v,%v]", a.results[0].Type, a.results[0].Offset)
+ } else {
+ s := "("
+ for _, result := range a.results {
+ fn += fmt.Sprintf("%s[%v,%v]", s, result.Type, result.Offset)
+ s = ","
+ }
+ fn += ")"
+ }
+ }
+
+ return fn + "}"
+}
+
+// StaticAuxCall returns an AuxCall for a static call.
+func StaticAuxCall(sym *obj.LSym, args []Param, results []Param) *AuxCall {
+ return &AuxCall{Fn: sym, args: args, results: results}
+}
+
+// InterfaceAuxCall returns an AuxCall for an interface call.
+func InterfaceAuxCall(args []Param, results []Param) *AuxCall {
+ return &AuxCall{Fn: nil, args: args, results: results}
+}
+
+// ClosureAuxCall returns an AuxCall for a closure call.
+func ClosureAuxCall(args []Param, results []Param) *AuxCall {
+ return &AuxCall{Fn: nil, args: args, results: results}
+}
+
+const (
+ auxNone auxType = iota
+ auxBool // auxInt is 0/1 for false/true
+ auxInt8 // auxInt is an 8-bit integer
+ auxInt16 // auxInt is a 16-bit integer
+ auxInt32 // auxInt is a 32-bit integer
+ auxInt64 // auxInt is a 64-bit integer
+ auxInt128 // auxInt represents a 128-bit integer. Always 0.
+ auxUInt8 // auxInt is an 8-bit unsigned integer
+ auxFloat32 // auxInt is a float32 (encoded with math.Float64bits)
+ auxFloat64 // auxInt is a float64 (encoded with math.Float64bits)
+ auxFlagConstant // auxInt is a flagConstant
+ auxString // aux is a string
+ auxSym // aux is a symbol (a *gc.Node for locals, an *obj.LSym for globals, or nil for none)
+ auxSymOff // aux is a symbol, auxInt is an offset
+ auxSymValAndOff // aux is a symbol, auxInt is a ValAndOff
+ auxTyp // aux is a type
+ auxTypSize // aux is a type, auxInt is a size, must have Aux.(Type).Size() == AuxInt
+ auxCCop // aux is a ssa.Op that represents a flags-to-bool conversion (e.g. LessThan)
+ auxCall // aux is a *ssa.AuxCall
+ auxCallOff // aux is a *ssa.AuxCall, AuxInt is int64 param (in+out) size
+
+ // architecture specific aux types
+ auxARM64BitField // aux is an arm64 bitfield lsb and width packed into auxInt
+ auxS390XRotateParams // aux is a s390x rotate parameters object encoding start bit, end bit and rotate amount
+ auxS390XCCMask // aux is a s390x 4-bit condition code mask
+ auxS390XCCMaskInt8 // aux is a s390x 4-bit condition code mask, auxInt is a int8 immediate
+ auxS390XCCMaskUint8 // aux is a s390x 4-bit condition code mask, auxInt is a uint8 immediate
+)
+
+// A SymEffect describes the effect that an SSA Value has on the variable
+// identified by the symbol in its Aux field.
+type SymEffect int8
+
+const (
+ SymRead SymEffect = 1 << iota
+ SymWrite
+ SymAddr
+
+ SymRdWr = SymRead | SymWrite
+
+ SymNone SymEffect = 0
+)
+
+// A Sym represents a symbolic offset from a base register.
+// Currently a Sym can be one of 3 things:
+// - a *gc.Node, for an offset from SP (the stack pointer)
+// - a *obj.LSym, for an offset from SB (the global pointer)
+// - nil, for no offset
+type Sym interface {
+ String() string
+ CanBeAnSSASym()
+}
+
+// A ValAndOff is used by the several opcodes. It holds
+// both a value and a pointer offset.
+// A ValAndOff is intended to be encoded into an AuxInt field.
+// The zero ValAndOff encodes a value of 0 and an offset of 0.
+// The high 32 bits hold a value.
+// The low 32 bits hold a pointer offset.
+type ValAndOff int64
+
+func (x ValAndOff) Val() int64 { return int64(x) >> 32 }
+func (x ValAndOff) Val32() int32 { return int32(int64(x) >> 32) }
+func (x ValAndOff) Val16() int16 { return int16(int64(x) >> 32) }
+func (x ValAndOff) Val8() int8 { return int8(int64(x) >> 32) }
+
+func (x ValAndOff) Off() int64 { return int64(int32(x)) }
+func (x ValAndOff) Off32() int32 { return int32(x) }
+
+func (x ValAndOff) String() string {
+ return fmt.Sprintf("val=%d,off=%d", x.Val(), x.Off())
+}
+
+// validVal reports whether the value can be used
+// as an argument to makeValAndOff.
+func validVal(val int64) bool {
+ return val == int64(int32(val))
+}
+
+// validOff reports whether the offset can be used
+// as an argument to makeValAndOff.
+func validOff(off int64) bool {
+ return off == int64(int32(off))
+}
+
+// validValAndOff reports whether we can fit the value and offset into
+// a ValAndOff value.
+func validValAndOff(val, off int64) bool {
+ if !validVal(val) {
+ return false
+ }
+ if !validOff(off) {
+ return false
+ }
+ return true
+}
+
+func makeValAndOff32(val, off int32) ValAndOff {
+ return ValAndOff(int64(val)<<32 + int64(uint32(off)))
+}
+func makeValAndOff64(val, off int64) ValAndOff {
+ if !validValAndOff(val, off) {
+ panic("invalid makeValAndOff64")
+ }
+ return ValAndOff(val<<32 + int64(uint32(off)))
+}
+
+func (x ValAndOff) canAdd32(off int32) bool {
+ newoff := x.Off() + int64(off)
+ return newoff == int64(int32(newoff))
+}
+func (x ValAndOff) canAdd64(off int64) bool {
+ newoff := x.Off() + off
+ return newoff == int64(int32(newoff))
+}
+
+func (x ValAndOff) addOffset32(off int32) ValAndOff {
+ if !x.canAdd32(off) {
+ panic("invalid ValAndOff.addOffset32")
+ }
+ return makeValAndOff64(x.Val(), x.Off()+int64(off))
+}
+func (x ValAndOff) addOffset64(off int64) ValAndOff {
+ if !x.canAdd64(off) {
+ panic("invalid ValAndOff.addOffset64")
+ }
+ return makeValAndOff64(x.Val(), x.Off()+off)
+}
+
+// int128 is a type that stores a 128-bit constant.
+// The only allowed constant right now is 0, so we can cheat quite a bit.
+type int128 int64
+
+type BoundsKind uint8
+
+const (
+ BoundsIndex BoundsKind = iota // indexing operation, 0 <= idx < len failed
+ BoundsIndexU // ... with unsigned idx
+ BoundsSliceAlen // 2-arg slicing operation, 0 <= high <= len failed
+ BoundsSliceAlenU // ... with unsigned high
+ BoundsSliceAcap // 2-arg slicing operation, 0 <= high <= cap failed
+ BoundsSliceAcapU // ... with unsigned high
+ BoundsSliceB // 2-arg slicing operation, 0 <= low <= high failed
+ BoundsSliceBU // ... with unsigned low
+ BoundsSlice3Alen // 3-arg slicing operation, 0 <= max <= len failed
+ BoundsSlice3AlenU // ... with unsigned max
+ BoundsSlice3Acap // 3-arg slicing operation, 0 <= max <= cap failed
+ BoundsSlice3AcapU // ... with unsigned max
+ BoundsSlice3B // 3-arg slicing operation, 0 <= high <= max failed
+ BoundsSlice3BU // ... with unsigned high
+ BoundsSlice3C // 3-arg slicing operation, 0 <= low <= high failed
+ BoundsSlice3CU // ... with unsigned low
+ BoundsKindCount
+)
+
+// boundsAPI determines which register arguments a bounds check call should use. For an [a:b:c] slice, we do:
+// CMPQ c, cap
+// JA fail1
+// CMPQ b, c
+// JA fail2
+// CMPQ a, b
+// JA fail3
+//
+// fail1: CALL panicSlice3Acap (c, cap)
+// fail2: CALL panicSlice3B (b, c)
+// fail3: CALL panicSlice3C (a, b)
+//
+// When we register allocate that code, we want the same register to be used for
+// the first arg of panicSlice3Acap and the second arg to panicSlice3B. That way,
+// initializing that register once will satisfy both calls.
+// That desire ends up dividing the set of bounds check calls into 3 sets. This function
+// determines which set to use for a given panic call.
+// The first arg for set 0 should be the second arg for set 1.
+// The first arg for set 1 should be the second arg for set 2.
+func boundsABI(b int64) int {
+ switch BoundsKind(b) {
+ case BoundsSlice3Alen,
+ BoundsSlice3AlenU,
+ BoundsSlice3Acap,
+ BoundsSlice3AcapU:
+ return 0
+ case BoundsSliceAlen,
+ BoundsSliceAlenU,
+ BoundsSliceAcap,
+ BoundsSliceAcapU,
+ BoundsSlice3B,
+ BoundsSlice3BU:
+ return 1
+ case BoundsIndex,
+ BoundsIndexU,
+ BoundsSliceB,
+ BoundsSliceBU,
+ BoundsSlice3C,
+ BoundsSlice3CU:
+ return 2
+ default:
+ panic("bad BoundsKind")
+ }
+}
+
+// arm64BitFileld is the GO type of ARM64BitField auxInt.
+// if x is an ARM64BitField, then width=x&0xff, lsb=(x>>8)&0xff, and
+// width+lsb<64 for 64-bit variant, width+lsb<32 for 32-bit variant.
+// the meaning of width and lsb are instruction-dependent.
+type arm64BitField int16
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
new file mode 100644
index 0000000..a3f9a22
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -0,0 +1,36677 @@
+// Code generated from gen/*Ops.go; DO NOT EDIT.
+
+package ssa
+
+import (
+ "cmd/internal/obj"
+ "cmd/internal/obj/arm"
+ "cmd/internal/obj/arm64"
+ "cmd/internal/obj/mips"
+ "cmd/internal/obj/ppc64"
+ "cmd/internal/obj/riscv"
+ "cmd/internal/obj/s390x"
+ "cmd/internal/obj/wasm"
+ "cmd/internal/obj/x86"
+)
+
+const (
+ BlockInvalid BlockKind = iota
+
+ Block386EQ
+ Block386NE
+ Block386LT
+ Block386LE
+ Block386GT
+ Block386GE
+ Block386OS
+ Block386OC
+ Block386ULT
+ Block386ULE
+ Block386UGT
+ Block386UGE
+ Block386EQF
+ Block386NEF
+ Block386ORD
+ Block386NAN
+
+ BlockAMD64EQ
+ BlockAMD64NE
+ BlockAMD64LT
+ BlockAMD64LE
+ BlockAMD64GT
+ BlockAMD64GE
+ BlockAMD64OS
+ BlockAMD64OC
+ BlockAMD64ULT
+ BlockAMD64ULE
+ BlockAMD64UGT
+ BlockAMD64UGE
+ BlockAMD64EQF
+ BlockAMD64NEF
+ BlockAMD64ORD
+ BlockAMD64NAN
+
+ BlockARMEQ
+ BlockARMNE
+ BlockARMLT
+ BlockARMLE
+ BlockARMGT
+ BlockARMGE
+ BlockARMULT
+ BlockARMULE
+ BlockARMUGT
+ BlockARMUGE
+ BlockARMLTnoov
+ BlockARMLEnoov
+ BlockARMGTnoov
+ BlockARMGEnoov
+
+ BlockARM64EQ
+ BlockARM64NE
+ BlockARM64LT
+ BlockARM64LE
+ BlockARM64GT
+ BlockARM64GE
+ BlockARM64ULT
+ BlockARM64ULE
+ BlockARM64UGT
+ BlockARM64UGE
+ BlockARM64Z
+ BlockARM64NZ
+ BlockARM64ZW
+ BlockARM64NZW
+ BlockARM64TBZ
+ BlockARM64TBNZ
+ BlockARM64FLT
+ BlockARM64FLE
+ BlockARM64FGT
+ BlockARM64FGE
+ BlockARM64LTnoov
+ BlockARM64LEnoov
+ BlockARM64GTnoov
+ BlockARM64GEnoov
+
+ BlockMIPSEQ
+ BlockMIPSNE
+ BlockMIPSLTZ
+ BlockMIPSLEZ
+ BlockMIPSGTZ
+ BlockMIPSGEZ
+ BlockMIPSFPT
+ BlockMIPSFPF
+
+ BlockMIPS64EQ
+ BlockMIPS64NE
+ BlockMIPS64LTZ
+ BlockMIPS64LEZ
+ BlockMIPS64GTZ
+ BlockMIPS64GEZ
+ BlockMIPS64FPT
+ BlockMIPS64FPF
+
+ BlockPPC64EQ
+ BlockPPC64NE
+ BlockPPC64LT
+ BlockPPC64LE
+ BlockPPC64GT
+ BlockPPC64GE
+ BlockPPC64FLT
+ BlockPPC64FLE
+ BlockPPC64FGT
+ BlockPPC64FGE
+
+ BlockRISCV64BEQ
+ BlockRISCV64BNE
+ BlockRISCV64BLT
+ BlockRISCV64BGE
+ BlockRISCV64BLTU
+ BlockRISCV64BGEU
+ BlockRISCV64BEQZ
+ BlockRISCV64BNEZ
+ BlockRISCV64BLEZ
+ BlockRISCV64BGEZ
+ BlockRISCV64BLTZ
+ BlockRISCV64BGTZ
+
+ BlockS390XBRC
+ BlockS390XCRJ
+ BlockS390XCGRJ
+ BlockS390XCLRJ
+ BlockS390XCLGRJ
+ BlockS390XCIJ
+ BlockS390XCGIJ
+ BlockS390XCLIJ
+ BlockS390XCLGIJ
+
+ BlockPlain
+ BlockIf
+ BlockDefer
+ BlockRet
+ BlockRetJmp
+ BlockExit
+ BlockFirst
+)
+
+var blockString = [...]string{
+ BlockInvalid: "BlockInvalid",
+
+ Block386EQ: "EQ",
+ Block386NE: "NE",
+ Block386LT: "LT",
+ Block386LE: "LE",
+ Block386GT: "GT",
+ Block386GE: "GE",
+ Block386OS: "OS",
+ Block386OC: "OC",
+ Block386ULT: "ULT",
+ Block386ULE: "ULE",
+ Block386UGT: "UGT",
+ Block386UGE: "UGE",
+ Block386EQF: "EQF",
+ Block386NEF: "NEF",
+ Block386ORD: "ORD",
+ Block386NAN: "NAN",
+
+ BlockAMD64EQ: "EQ",
+ BlockAMD64NE: "NE",
+ BlockAMD64LT: "LT",
+ BlockAMD64LE: "LE",
+ BlockAMD64GT: "GT",
+ BlockAMD64GE: "GE",
+ BlockAMD64OS: "OS",
+ BlockAMD64OC: "OC",
+ BlockAMD64ULT: "ULT",
+ BlockAMD64ULE: "ULE",
+ BlockAMD64UGT: "UGT",
+ BlockAMD64UGE: "UGE",
+ BlockAMD64EQF: "EQF",
+ BlockAMD64NEF: "NEF",
+ BlockAMD64ORD: "ORD",
+ BlockAMD64NAN: "NAN",
+
+ BlockARMEQ: "EQ",
+ BlockARMNE: "NE",
+ BlockARMLT: "LT",
+ BlockARMLE: "LE",
+ BlockARMGT: "GT",
+ BlockARMGE: "GE",
+ BlockARMULT: "ULT",
+ BlockARMULE: "ULE",
+ BlockARMUGT: "UGT",
+ BlockARMUGE: "UGE",
+ BlockARMLTnoov: "LTnoov",
+ BlockARMLEnoov: "LEnoov",
+ BlockARMGTnoov: "GTnoov",
+ BlockARMGEnoov: "GEnoov",
+
+ BlockARM64EQ: "EQ",
+ BlockARM64NE: "NE",
+ BlockARM64LT: "LT",
+ BlockARM64LE: "LE",
+ BlockARM64GT: "GT",
+ BlockARM64GE: "GE",
+ BlockARM64ULT: "ULT",
+ BlockARM64ULE: "ULE",
+ BlockARM64UGT: "UGT",
+ BlockARM64UGE: "UGE",
+ BlockARM64Z: "Z",
+ BlockARM64NZ: "NZ",
+ BlockARM64ZW: "ZW",
+ BlockARM64NZW: "NZW",
+ BlockARM64TBZ: "TBZ",
+ BlockARM64TBNZ: "TBNZ",
+ BlockARM64FLT: "FLT",
+ BlockARM64FLE: "FLE",
+ BlockARM64FGT: "FGT",
+ BlockARM64FGE: "FGE",
+ BlockARM64LTnoov: "LTnoov",
+ BlockARM64LEnoov: "LEnoov",
+ BlockARM64GTnoov: "GTnoov",
+ BlockARM64GEnoov: "GEnoov",
+
+ BlockMIPSEQ: "EQ",
+ BlockMIPSNE: "NE",
+ BlockMIPSLTZ: "LTZ",
+ BlockMIPSLEZ: "LEZ",
+ BlockMIPSGTZ: "GTZ",
+ BlockMIPSGEZ: "GEZ",
+ BlockMIPSFPT: "FPT",
+ BlockMIPSFPF: "FPF",
+
+ BlockMIPS64EQ: "EQ",
+ BlockMIPS64NE: "NE",
+ BlockMIPS64LTZ: "LTZ",
+ BlockMIPS64LEZ: "LEZ",
+ BlockMIPS64GTZ: "GTZ",
+ BlockMIPS64GEZ: "GEZ",
+ BlockMIPS64FPT: "FPT",
+ BlockMIPS64FPF: "FPF",
+
+ BlockPPC64EQ: "EQ",
+ BlockPPC64NE: "NE",
+ BlockPPC64LT: "LT",
+ BlockPPC64LE: "LE",
+ BlockPPC64GT: "GT",
+ BlockPPC64GE: "GE",
+ BlockPPC64FLT: "FLT",
+ BlockPPC64FLE: "FLE",
+ BlockPPC64FGT: "FGT",
+ BlockPPC64FGE: "FGE",
+
+ BlockRISCV64BEQ: "BEQ",
+ BlockRISCV64BNE: "BNE",
+ BlockRISCV64BLT: "BLT",
+ BlockRISCV64BGE: "BGE",
+ BlockRISCV64BLTU: "BLTU",
+ BlockRISCV64BGEU: "BGEU",
+ BlockRISCV64BEQZ: "BEQZ",
+ BlockRISCV64BNEZ: "BNEZ",
+ BlockRISCV64BLEZ: "BLEZ",
+ BlockRISCV64BGEZ: "BGEZ",
+ BlockRISCV64BLTZ: "BLTZ",
+ BlockRISCV64BGTZ: "BGTZ",
+
+ BlockS390XBRC: "BRC",
+ BlockS390XCRJ: "CRJ",
+ BlockS390XCGRJ: "CGRJ",
+ BlockS390XCLRJ: "CLRJ",
+ BlockS390XCLGRJ: "CLGRJ",
+ BlockS390XCIJ: "CIJ",
+ BlockS390XCGIJ: "CGIJ",
+ BlockS390XCLIJ: "CLIJ",
+ BlockS390XCLGIJ: "CLGIJ",
+
+ BlockPlain: "Plain",
+ BlockIf: "If",
+ BlockDefer: "Defer",
+ BlockRet: "Ret",
+ BlockRetJmp: "RetJmp",
+ BlockExit: "Exit",
+ BlockFirst: "First",
+}
+
+func (k BlockKind) String() string { return blockString[k] }
+func (k BlockKind) AuxIntType() string {
+ switch k {
+ case BlockARM64TBZ:
+ return "int64"
+ case BlockARM64TBNZ:
+ return "int64"
+ case BlockS390XCIJ:
+ return "int8"
+ case BlockS390XCGIJ:
+ return "int8"
+ case BlockS390XCLIJ:
+ return "uint8"
+ case BlockS390XCLGIJ:
+ return "uint8"
+ }
+ return ""
+}
+
+const (
+ OpInvalid Op = iota
+
+ Op386ADDSS
+ Op386ADDSD
+ Op386SUBSS
+ Op386SUBSD
+ Op386MULSS
+ Op386MULSD
+ Op386DIVSS
+ Op386DIVSD
+ Op386MOVSSload
+ Op386MOVSDload
+ Op386MOVSSconst
+ Op386MOVSDconst
+ Op386MOVSSloadidx1
+ Op386MOVSSloadidx4
+ Op386MOVSDloadidx1
+ Op386MOVSDloadidx8
+ Op386MOVSSstore
+ Op386MOVSDstore
+ Op386MOVSSstoreidx1
+ Op386MOVSSstoreidx4
+ Op386MOVSDstoreidx1
+ Op386MOVSDstoreidx8
+ Op386ADDSSload
+ Op386ADDSDload
+ Op386SUBSSload
+ Op386SUBSDload
+ Op386MULSSload
+ Op386MULSDload
+ Op386DIVSSload
+ Op386DIVSDload
+ Op386ADDL
+ Op386ADDLconst
+ Op386ADDLcarry
+ Op386ADDLconstcarry
+ Op386ADCL
+ Op386ADCLconst
+ Op386SUBL
+ Op386SUBLconst
+ Op386SUBLcarry
+ Op386SUBLconstcarry
+ Op386SBBL
+ Op386SBBLconst
+ Op386MULL
+ Op386MULLconst
+ Op386MULLU
+ Op386HMULL
+ Op386HMULLU
+ Op386MULLQU
+ Op386AVGLU
+ Op386DIVL
+ Op386DIVW
+ Op386DIVLU
+ Op386DIVWU
+ Op386MODL
+ Op386MODW
+ Op386MODLU
+ Op386MODWU
+ Op386ANDL
+ Op386ANDLconst
+ Op386ORL
+ Op386ORLconst
+ Op386XORL
+ Op386XORLconst
+ Op386CMPL
+ Op386CMPW
+ Op386CMPB
+ Op386CMPLconst
+ Op386CMPWconst
+ Op386CMPBconst
+ Op386CMPLload
+ Op386CMPWload
+ Op386CMPBload
+ Op386CMPLconstload
+ Op386CMPWconstload
+ Op386CMPBconstload
+ Op386UCOMISS
+ Op386UCOMISD
+ Op386TESTL
+ Op386TESTW
+ Op386TESTB
+ Op386TESTLconst
+ Op386TESTWconst
+ Op386TESTBconst
+ Op386SHLL
+ Op386SHLLconst
+ Op386SHRL
+ Op386SHRW
+ Op386SHRB
+ Op386SHRLconst
+ Op386SHRWconst
+ Op386SHRBconst
+ Op386SARL
+ Op386SARW
+ Op386SARB
+ Op386SARLconst
+ Op386SARWconst
+ Op386SARBconst
+ Op386ROLLconst
+ Op386ROLWconst
+ Op386ROLBconst
+ Op386ADDLload
+ Op386SUBLload
+ Op386MULLload
+ Op386ANDLload
+ Op386ORLload
+ Op386XORLload
+ Op386ADDLloadidx4
+ Op386SUBLloadidx4
+ Op386MULLloadidx4
+ Op386ANDLloadidx4
+ Op386ORLloadidx4
+ Op386XORLloadidx4
+ Op386NEGL
+ Op386NOTL
+ Op386BSFL
+ Op386BSFW
+ Op386BSRL
+ Op386BSRW
+ Op386BSWAPL
+ Op386SQRTSD
+ Op386SBBLcarrymask
+ Op386SETEQ
+ Op386SETNE
+ Op386SETL
+ Op386SETLE
+ Op386SETG
+ Op386SETGE
+ Op386SETB
+ Op386SETBE
+ Op386SETA
+ Op386SETAE
+ Op386SETO
+ Op386SETEQF
+ Op386SETNEF
+ Op386SETORD
+ Op386SETNAN
+ Op386SETGF
+ Op386SETGEF
+ Op386MOVBLSX
+ Op386MOVBLZX
+ Op386MOVWLSX
+ Op386MOVWLZX
+ Op386MOVLconst
+ Op386CVTTSD2SL
+ Op386CVTTSS2SL
+ Op386CVTSL2SS
+ Op386CVTSL2SD
+ Op386CVTSD2SS
+ Op386CVTSS2SD
+ Op386PXOR
+ Op386LEAL
+ Op386LEAL1
+ Op386LEAL2
+ Op386LEAL4
+ Op386LEAL8
+ Op386MOVBload
+ Op386MOVBLSXload
+ Op386MOVWload
+ Op386MOVWLSXload
+ Op386MOVLload
+ Op386MOVBstore
+ Op386MOVWstore
+ Op386MOVLstore
+ Op386ADDLmodify
+ Op386SUBLmodify
+ Op386ANDLmodify
+ Op386ORLmodify
+ Op386XORLmodify
+ Op386ADDLmodifyidx4
+ Op386SUBLmodifyidx4
+ Op386ANDLmodifyidx4
+ Op386ORLmodifyidx4
+ Op386XORLmodifyidx4
+ Op386ADDLconstmodify
+ Op386ANDLconstmodify
+ Op386ORLconstmodify
+ Op386XORLconstmodify
+ Op386ADDLconstmodifyidx4
+ Op386ANDLconstmodifyidx4
+ Op386ORLconstmodifyidx4
+ Op386XORLconstmodifyidx4
+ Op386MOVBloadidx1
+ Op386MOVWloadidx1
+ Op386MOVWloadidx2
+ Op386MOVLloadidx1
+ Op386MOVLloadidx4
+ Op386MOVBstoreidx1
+ Op386MOVWstoreidx1
+ Op386MOVWstoreidx2
+ Op386MOVLstoreidx1
+ Op386MOVLstoreidx4
+ Op386MOVBstoreconst
+ Op386MOVWstoreconst
+ Op386MOVLstoreconst
+ Op386MOVBstoreconstidx1
+ Op386MOVWstoreconstidx1
+ Op386MOVWstoreconstidx2
+ Op386MOVLstoreconstidx1
+ Op386MOVLstoreconstidx4
+ Op386DUFFZERO
+ Op386REPSTOSL
+ Op386CALLstatic
+ Op386CALLclosure
+ Op386CALLinter
+ Op386DUFFCOPY
+ Op386REPMOVSL
+ Op386InvertFlags
+ Op386LoweredGetG
+ Op386LoweredGetClosurePtr
+ Op386LoweredGetCallerPC
+ Op386LoweredGetCallerSP
+ Op386LoweredNilCheck
+ Op386LoweredWB
+ Op386LoweredPanicBoundsA
+ Op386LoweredPanicBoundsB
+ Op386LoweredPanicBoundsC
+ Op386LoweredPanicExtendA
+ Op386LoweredPanicExtendB
+ Op386LoweredPanicExtendC
+ Op386FlagEQ
+ Op386FlagLT_ULT
+ Op386FlagLT_UGT
+ Op386FlagGT_UGT
+ Op386FlagGT_ULT
+ Op386MOVSSconst1
+ Op386MOVSDconst1
+ Op386MOVSSconst2
+ Op386MOVSDconst2
+
+ OpAMD64ADDSS
+ OpAMD64ADDSD
+ OpAMD64SUBSS
+ OpAMD64SUBSD
+ OpAMD64MULSS
+ OpAMD64MULSD
+ OpAMD64DIVSS
+ OpAMD64DIVSD
+ OpAMD64MOVSSload
+ OpAMD64MOVSDload
+ OpAMD64MOVSSconst
+ OpAMD64MOVSDconst
+ OpAMD64MOVSSloadidx1
+ OpAMD64MOVSSloadidx4
+ OpAMD64MOVSDloadidx1
+ OpAMD64MOVSDloadidx8
+ OpAMD64MOVSSstore
+ OpAMD64MOVSDstore
+ OpAMD64MOVSSstoreidx1
+ OpAMD64MOVSSstoreidx4
+ OpAMD64MOVSDstoreidx1
+ OpAMD64MOVSDstoreidx8
+ OpAMD64ADDSSload
+ OpAMD64ADDSDload
+ OpAMD64SUBSSload
+ OpAMD64SUBSDload
+ OpAMD64MULSSload
+ OpAMD64MULSDload
+ OpAMD64DIVSSload
+ OpAMD64DIVSDload
+ OpAMD64ADDSSloadidx1
+ OpAMD64ADDSSloadidx4
+ OpAMD64ADDSDloadidx1
+ OpAMD64ADDSDloadidx8
+ OpAMD64SUBSSloadidx1
+ OpAMD64SUBSSloadidx4
+ OpAMD64SUBSDloadidx1
+ OpAMD64SUBSDloadidx8
+ OpAMD64MULSSloadidx1
+ OpAMD64MULSSloadidx4
+ OpAMD64MULSDloadidx1
+ OpAMD64MULSDloadidx8
+ OpAMD64DIVSSloadidx1
+ OpAMD64DIVSSloadidx4
+ OpAMD64DIVSDloadidx1
+ OpAMD64DIVSDloadidx8
+ OpAMD64ADDQ
+ OpAMD64ADDL
+ OpAMD64ADDQconst
+ OpAMD64ADDLconst
+ OpAMD64ADDQconstmodify
+ OpAMD64ADDLconstmodify
+ OpAMD64SUBQ
+ OpAMD64SUBL
+ OpAMD64SUBQconst
+ OpAMD64SUBLconst
+ OpAMD64MULQ
+ OpAMD64MULL
+ OpAMD64MULQconst
+ OpAMD64MULLconst
+ OpAMD64MULLU
+ OpAMD64MULQU
+ OpAMD64HMULQ
+ OpAMD64HMULL
+ OpAMD64HMULQU
+ OpAMD64HMULLU
+ OpAMD64AVGQU
+ OpAMD64DIVQ
+ OpAMD64DIVL
+ OpAMD64DIVW
+ OpAMD64DIVQU
+ OpAMD64DIVLU
+ OpAMD64DIVWU
+ OpAMD64NEGLflags
+ OpAMD64ADDQcarry
+ OpAMD64ADCQ
+ OpAMD64ADDQconstcarry
+ OpAMD64ADCQconst
+ OpAMD64SUBQborrow
+ OpAMD64SBBQ
+ OpAMD64SUBQconstborrow
+ OpAMD64SBBQconst
+ OpAMD64MULQU2
+ OpAMD64DIVQU2
+ OpAMD64ANDQ
+ OpAMD64ANDL
+ OpAMD64ANDQconst
+ OpAMD64ANDLconst
+ OpAMD64ANDQconstmodify
+ OpAMD64ANDLconstmodify
+ OpAMD64ORQ
+ OpAMD64ORL
+ OpAMD64ORQconst
+ OpAMD64ORLconst
+ OpAMD64ORQconstmodify
+ OpAMD64ORLconstmodify
+ OpAMD64XORQ
+ OpAMD64XORL
+ OpAMD64XORQconst
+ OpAMD64XORLconst
+ OpAMD64XORQconstmodify
+ OpAMD64XORLconstmodify
+ OpAMD64CMPQ
+ OpAMD64CMPL
+ OpAMD64CMPW
+ OpAMD64CMPB
+ OpAMD64CMPQconst
+ OpAMD64CMPLconst
+ OpAMD64CMPWconst
+ OpAMD64CMPBconst
+ OpAMD64CMPQload
+ OpAMD64CMPLload
+ OpAMD64CMPWload
+ OpAMD64CMPBload
+ OpAMD64CMPQconstload
+ OpAMD64CMPLconstload
+ OpAMD64CMPWconstload
+ OpAMD64CMPBconstload
+ OpAMD64CMPQloadidx8
+ OpAMD64CMPQloadidx1
+ OpAMD64CMPLloadidx4
+ OpAMD64CMPLloadidx1
+ OpAMD64CMPWloadidx2
+ OpAMD64CMPWloadidx1
+ OpAMD64CMPBloadidx1
+ OpAMD64CMPQconstloadidx8
+ OpAMD64CMPQconstloadidx1
+ OpAMD64CMPLconstloadidx4
+ OpAMD64CMPLconstloadidx1
+ OpAMD64CMPWconstloadidx2
+ OpAMD64CMPWconstloadidx1
+ OpAMD64CMPBconstloadidx1
+ OpAMD64UCOMISS
+ OpAMD64UCOMISD
+ OpAMD64BTL
+ OpAMD64BTQ
+ OpAMD64BTCL
+ OpAMD64BTCQ
+ OpAMD64BTRL
+ OpAMD64BTRQ
+ OpAMD64BTSL
+ OpAMD64BTSQ
+ OpAMD64BTLconst
+ OpAMD64BTQconst
+ OpAMD64BTCLconst
+ OpAMD64BTCQconst
+ OpAMD64BTRLconst
+ OpAMD64BTRQconst
+ OpAMD64BTSLconst
+ OpAMD64BTSQconst
+ OpAMD64BTCQmodify
+ OpAMD64BTCLmodify
+ OpAMD64BTSQmodify
+ OpAMD64BTSLmodify
+ OpAMD64BTRQmodify
+ OpAMD64BTRLmodify
+ OpAMD64BTCQconstmodify
+ OpAMD64BTCLconstmodify
+ OpAMD64BTSQconstmodify
+ OpAMD64BTSLconstmodify
+ OpAMD64BTRQconstmodify
+ OpAMD64BTRLconstmodify
+ OpAMD64TESTQ
+ OpAMD64TESTL
+ OpAMD64TESTW
+ OpAMD64TESTB
+ OpAMD64TESTQconst
+ OpAMD64TESTLconst
+ OpAMD64TESTWconst
+ OpAMD64TESTBconst
+ OpAMD64SHLQ
+ OpAMD64SHLL
+ OpAMD64SHLQconst
+ OpAMD64SHLLconst
+ OpAMD64SHRQ
+ OpAMD64SHRL
+ OpAMD64SHRW
+ OpAMD64SHRB
+ OpAMD64SHRQconst
+ OpAMD64SHRLconst
+ OpAMD64SHRWconst
+ OpAMD64SHRBconst
+ OpAMD64SARQ
+ OpAMD64SARL
+ OpAMD64SARW
+ OpAMD64SARB
+ OpAMD64SARQconst
+ OpAMD64SARLconst
+ OpAMD64SARWconst
+ OpAMD64SARBconst
+ OpAMD64ROLQ
+ OpAMD64ROLL
+ OpAMD64ROLW
+ OpAMD64ROLB
+ OpAMD64RORQ
+ OpAMD64RORL
+ OpAMD64RORW
+ OpAMD64RORB
+ OpAMD64ROLQconst
+ OpAMD64ROLLconst
+ OpAMD64ROLWconst
+ OpAMD64ROLBconst
+ OpAMD64ADDLload
+ OpAMD64ADDQload
+ OpAMD64SUBQload
+ OpAMD64SUBLload
+ OpAMD64ANDLload
+ OpAMD64ANDQload
+ OpAMD64ORQload
+ OpAMD64ORLload
+ OpAMD64XORQload
+ OpAMD64XORLload
+ OpAMD64ADDLloadidx1
+ OpAMD64ADDLloadidx4
+ OpAMD64ADDLloadidx8
+ OpAMD64ADDQloadidx1
+ OpAMD64ADDQloadidx8
+ OpAMD64SUBLloadidx1
+ OpAMD64SUBLloadidx4
+ OpAMD64SUBLloadidx8
+ OpAMD64SUBQloadidx1
+ OpAMD64SUBQloadidx8
+ OpAMD64ANDLloadidx1
+ OpAMD64ANDLloadidx4
+ OpAMD64ANDLloadidx8
+ OpAMD64ANDQloadidx1
+ OpAMD64ANDQloadidx8
+ OpAMD64ORLloadidx1
+ OpAMD64ORLloadidx4
+ OpAMD64ORLloadidx8
+ OpAMD64ORQloadidx1
+ OpAMD64ORQloadidx8
+ OpAMD64XORLloadidx1
+ OpAMD64XORLloadidx4
+ OpAMD64XORLloadidx8
+ OpAMD64XORQloadidx1
+ OpAMD64XORQloadidx8
+ OpAMD64ADDQmodify
+ OpAMD64SUBQmodify
+ OpAMD64ANDQmodify
+ OpAMD64ORQmodify
+ OpAMD64XORQmodify
+ OpAMD64ADDLmodify
+ OpAMD64SUBLmodify
+ OpAMD64ANDLmodify
+ OpAMD64ORLmodify
+ OpAMD64XORLmodify
+ OpAMD64ADDQmodifyidx1
+ OpAMD64ADDQmodifyidx8
+ OpAMD64SUBQmodifyidx1
+ OpAMD64SUBQmodifyidx8
+ OpAMD64ANDQmodifyidx1
+ OpAMD64ANDQmodifyidx8
+ OpAMD64ORQmodifyidx1
+ OpAMD64ORQmodifyidx8
+ OpAMD64XORQmodifyidx1
+ OpAMD64XORQmodifyidx8
+ OpAMD64ADDLmodifyidx1
+ OpAMD64ADDLmodifyidx4
+ OpAMD64ADDLmodifyidx8
+ OpAMD64SUBLmodifyidx1
+ OpAMD64SUBLmodifyidx4
+ OpAMD64SUBLmodifyidx8
+ OpAMD64ANDLmodifyidx1
+ OpAMD64ANDLmodifyidx4
+ OpAMD64ANDLmodifyidx8
+ OpAMD64ORLmodifyidx1
+ OpAMD64ORLmodifyidx4
+ OpAMD64ORLmodifyidx8
+ OpAMD64XORLmodifyidx1
+ OpAMD64XORLmodifyidx4
+ OpAMD64XORLmodifyidx8
+ OpAMD64ADDQconstmodifyidx1
+ OpAMD64ADDQconstmodifyidx8
+ OpAMD64ANDQconstmodifyidx1
+ OpAMD64ANDQconstmodifyidx8
+ OpAMD64ORQconstmodifyidx1
+ OpAMD64ORQconstmodifyidx8
+ OpAMD64XORQconstmodifyidx1
+ OpAMD64XORQconstmodifyidx8
+ OpAMD64ADDLconstmodifyidx1
+ OpAMD64ADDLconstmodifyidx4
+ OpAMD64ADDLconstmodifyidx8
+ OpAMD64ANDLconstmodifyidx1
+ OpAMD64ANDLconstmodifyidx4
+ OpAMD64ANDLconstmodifyidx8
+ OpAMD64ORLconstmodifyidx1
+ OpAMD64ORLconstmodifyidx4
+ OpAMD64ORLconstmodifyidx8
+ OpAMD64XORLconstmodifyidx1
+ OpAMD64XORLconstmodifyidx4
+ OpAMD64XORLconstmodifyidx8
+ OpAMD64NEGQ
+ OpAMD64NEGL
+ OpAMD64NOTQ
+ OpAMD64NOTL
+ OpAMD64BSFQ
+ OpAMD64BSFL
+ OpAMD64BSRQ
+ OpAMD64BSRL
+ OpAMD64CMOVQEQ
+ OpAMD64CMOVQNE
+ OpAMD64CMOVQLT
+ OpAMD64CMOVQGT
+ OpAMD64CMOVQLE
+ OpAMD64CMOVQGE
+ OpAMD64CMOVQLS
+ OpAMD64CMOVQHI
+ OpAMD64CMOVQCC
+ OpAMD64CMOVQCS
+ OpAMD64CMOVLEQ
+ OpAMD64CMOVLNE
+ OpAMD64CMOVLLT
+ OpAMD64CMOVLGT
+ OpAMD64CMOVLLE
+ OpAMD64CMOVLGE
+ OpAMD64CMOVLLS
+ OpAMD64CMOVLHI
+ OpAMD64CMOVLCC
+ OpAMD64CMOVLCS
+ OpAMD64CMOVWEQ
+ OpAMD64CMOVWNE
+ OpAMD64CMOVWLT
+ OpAMD64CMOVWGT
+ OpAMD64CMOVWLE
+ OpAMD64CMOVWGE
+ OpAMD64CMOVWLS
+ OpAMD64CMOVWHI
+ OpAMD64CMOVWCC
+ OpAMD64CMOVWCS
+ OpAMD64CMOVQEQF
+ OpAMD64CMOVQNEF
+ OpAMD64CMOVQGTF
+ OpAMD64CMOVQGEF
+ OpAMD64CMOVLEQF
+ OpAMD64CMOVLNEF
+ OpAMD64CMOVLGTF
+ OpAMD64CMOVLGEF
+ OpAMD64CMOVWEQF
+ OpAMD64CMOVWNEF
+ OpAMD64CMOVWGTF
+ OpAMD64CMOVWGEF
+ OpAMD64BSWAPQ
+ OpAMD64BSWAPL
+ OpAMD64POPCNTQ
+ OpAMD64POPCNTL
+ OpAMD64SQRTSD
+ OpAMD64ROUNDSD
+ OpAMD64VFMADD231SD
+ OpAMD64SBBQcarrymask
+ OpAMD64SBBLcarrymask
+ OpAMD64SETEQ
+ OpAMD64SETNE
+ OpAMD64SETL
+ OpAMD64SETLE
+ OpAMD64SETG
+ OpAMD64SETGE
+ OpAMD64SETB
+ OpAMD64SETBE
+ OpAMD64SETA
+ OpAMD64SETAE
+ OpAMD64SETO
+ OpAMD64SETEQstore
+ OpAMD64SETNEstore
+ OpAMD64SETLstore
+ OpAMD64SETLEstore
+ OpAMD64SETGstore
+ OpAMD64SETGEstore
+ OpAMD64SETBstore
+ OpAMD64SETBEstore
+ OpAMD64SETAstore
+ OpAMD64SETAEstore
+ OpAMD64SETEQF
+ OpAMD64SETNEF
+ OpAMD64SETORD
+ OpAMD64SETNAN
+ OpAMD64SETGF
+ OpAMD64SETGEF
+ OpAMD64MOVBQSX
+ OpAMD64MOVBQZX
+ OpAMD64MOVWQSX
+ OpAMD64MOVWQZX
+ OpAMD64MOVLQSX
+ OpAMD64MOVLQZX
+ OpAMD64MOVLconst
+ OpAMD64MOVQconst
+ OpAMD64CVTTSD2SL
+ OpAMD64CVTTSD2SQ
+ OpAMD64CVTTSS2SL
+ OpAMD64CVTTSS2SQ
+ OpAMD64CVTSL2SS
+ OpAMD64CVTSL2SD
+ OpAMD64CVTSQ2SS
+ OpAMD64CVTSQ2SD
+ OpAMD64CVTSD2SS
+ OpAMD64CVTSS2SD
+ OpAMD64MOVQi2f
+ OpAMD64MOVQf2i
+ OpAMD64MOVLi2f
+ OpAMD64MOVLf2i
+ OpAMD64PXOR
+ OpAMD64LEAQ
+ OpAMD64LEAL
+ OpAMD64LEAW
+ OpAMD64LEAQ1
+ OpAMD64LEAL1
+ OpAMD64LEAW1
+ OpAMD64LEAQ2
+ OpAMD64LEAL2
+ OpAMD64LEAW2
+ OpAMD64LEAQ4
+ OpAMD64LEAL4
+ OpAMD64LEAW4
+ OpAMD64LEAQ8
+ OpAMD64LEAL8
+ OpAMD64LEAW8
+ OpAMD64MOVBload
+ OpAMD64MOVBQSXload
+ OpAMD64MOVWload
+ OpAMD64MOVWQSXload
+ OpAMD64MOVLload
+ OpAMD64MOVLQSXload
+ OpAMD64MOVQload
+ OpAMD64MOVBstore
+ OpAMD64MOVWstore
+ OpAMD64MOVLstore
+ OpAMD64MOVQstore
+ OpAMD64MOVOload
+ OpAMD64MOVOstore
+ OpAMD64MOVBloadidx1
+ OpAMD64MOVWloadidx1
+ OpAMD64MOVWloadidx2
+ OpAMD64MOVLloadidx1
+ OpAMD64MOVLloadidx4
+ OpAMD64MOVLloadidx8
+ OpAMD64MOVQloadidx1
+ OpAMD64MOVQloadidx8
+ OpAMD64MOVBstoreidx1
+ OpAMD64MOVWstoreidx1
+ OpAMD64MOVWstoreidx2
+ OpAMD64MOVLstoreidx1
+ OpAMD64MOVLstoreidx4
+ OpAMD64MOVLstoreidx8
+ OpAMD64MOVQstoreidx1
+ OpAMD64MOVQstoreidx8
+ OpAMD64MOVBstoreconst
+ OpAMD64MOVWstoreconst
+ OpAMD64MOVLstoreconst
+ OpAMD64MOVQstoreconst
+ OpAMD64MOVBstoreconstidx1
+ OpAMD64MOVWstoreconstidx1
+ OpAMD64MOVWstoreconstidx2
+ OpAMD64MOVLstoreconstidx1
+ OpAMD64MOVLstoreconstidx4
+ OpAMD64MOVQstoreconstidx1
+ OpAMD64MOVQstoreconstidx8
+ OpAMD64DUFFZERO
+ OpAMD64MOVOconst
+ OpAMD64REPSTOSQ
+ OpAMD64CALLstatic
+ OpAMD64CALLclosure
+ OpAMD64CALLinter
+ OpAMD64DUFFCOPY
+ OpAMD64REPMOVSQ
+ OpAMD64InvertFlags
+ OpAMD64LoweredGetG
+ OpAMD64LoweredGetClosurePtr
+ OpAMD64LoweredGetCallerPC
+ OpAMD64LoweredGetCallerSP
+ OpAMD64LoweredNilCheck
+ OpAMD64LoweredWB
+ OpAMD64LoweredHasCPUFeature
+ OpAMD64LoweredPanicBoundsA
+ OpAMD64LoweredPanicBoundsB
+ OpAMD64LoweredPanicBoundsC
+ OpAMD64FlagEQ
+ OpAMD64FlagLT_ULT
+ OpAMD64FlagLT_UGT
+ OpAMD64FlagGT_UGT
+ OpAMD64FlagGT_ULT
+ OpAMD64MOVBatomicload
+ OpAMD64MOVLatomicload
+ OpAMD64MOVQatomicload
+ OpAMD64XCHGB
+ OpAMD64XCHGL
+ OpAMD64XCHGQ
+ OpAMD64XADDLlock
+ OpAMD64XADDQlock
+ OpAMD64AddTupleFirst32
+ OpAMD64AddTupleFirst64
+ OpAMD64CMPXCHGLlock
+ OpAMD64CMPXCHGQlock
+ OpAMD64ANDBlock
+ OpAMD64ANDLlock
+ OpAMD64ORBlock
+ OpAMD64ORLlock
+
+ OpARMADD
+ OpARMADDconst
+ OpARMSUB
+ OpARMSUBconst
+ OpARMRSB
+ OpARMRSBconst
+ OpARMMUL
+ OpARMHMUL
+ OpARMHMULU
+ OpARMCALLudiv
+ OpARMADDS
+ OpARMADDSconst
+ OpARMADC
+ OpARMADCconst
+ OpARMSUBS
+ OpARMSUBSconst
+ OpARMRSBSconst
+ OpARMSBC
+ OpARMSBCconst
+ OpARMRSCconst
+ OpARMMULLU
+ OpARMMULA
+ OpARMMULS
+ OpARMADDF
+ OpARMADDD
+ OpARMSUBF
+ OpARMSUBD
+ OpARMMULF
+ OpARMMULD
+ OpARMNMULF
+ OpARMNMULD
+ OpARMDIVF
+ OpARMDIVD
+ OpARMMULAF
+ OpARMMULAD
+ OpARMMULSF
+ OpARMMULSD
+ OpARMFMULAD
+ OpARMAND
+ OpARMANDconst
+ OpARMOR
+ OpARMORconst
+ OpARMXOR
+ OpARMXORconst
+ OpARMBIC
+ OpARMBICconst
+ OpARMBFX
+ OpARMBFXU
+ OpARMMVN
+ OpARMNEGF
+ OpARMNEGD
+ OpARMSQRTD
+ OpARMABSD
+ OpARMCLZ
+ OpARMREV
+ OpARMREV16
+ OpARMRBIT
+ OpARMSLL
+ OpARMSLLconst
+ OpARMSRL
+ OpARMSRLconst
+ OpARMSRA
+ OpARMSRAconst
+ OpARMSRR
+ OpARMSRRconst
+ OpARMADDshiftLL
+ OpARMADDshiftRL
+ OpARMADDshiftRA
+ OpARMSUBshiftLL
+ OpARMSUBshiftRL
+ OpARMSUBshiftRA
+ OpARMRSBshiftLL
+ OpARMRSBshiftRL
+ OpARMRSBshiftRA
+ OpARMANDshiftLL
+ OpARMANDshiftRL
+ OpARMANDshiftRA
+ OpARMORshiftLL
+ OpARMORshiftRL
+ OpARMORshiftRA
+ OpARMXORshiftLL
+ OpARMXORshiftRL
+ OpARMXORshiftRA
+ OpARMXORshiftRR
+ OpARMBICshiftLL
+ OpARMBICshiftRL
+ OpARMBICshiftRA
+ OpARMMVNshiftLL
+ OpARMMVNshiftRL
+ OpARMMVNshiftRA
+ OpARMADCshiftLL
+ OpARMADCshiftRL
+ OpARMADCshiftRA
+ OpARMSBCshiftLL
+ OpARMSBCshiftRL
+ OpARMSBCshiftRA
+ OpARMRSCshiftLL
+ OpARMRSCshiftRL
+ OpARMRSCshiftRA
+ OpARMADDSshiftLL
+ OpARMADDSshiftRL
+ OpARMADDSshiftRA
+ OpARMSUBSshiftLL
+ OpARMSUBSshiftRL
+ OpARMSUBSshiftRA
+ OpARMRSBSshiftLL
+ OpARMRSBSshiftRL
+ OpARMRSBSshiftRA
+ OpARMADDshiftLLreg
+ OpARMADDshiftRLreg
+ OpARMADDshiftRAreg
+ OpARMSUBshiftLLreg
+ OpARMSUBshiftRLreg
+ OpARMSUBshiftRAreg
+ OpARMRSBshiftLLreg
+ OpARMRSBshiftRLreg
+ OpARMRSBshiftRAreg
+ OpARMANDshiftLLreg
+ OpARMANDshiftRLreg
+ OpARMANDshiftRAreg
+ OpARMORshiftLLreg
+ OpARMORshiftRLreg
+ OpARMORshiftRAreg
+ OpARMXORshiftLLreg
+ OpARMXORshiftRLreg
+ OpARMXORshiftRAreg
+ OpARMBICshiftLLreg
+ OpARMBICshiftRLreg
+ OpARMBICshiftRAreg
+ OpARMMVNshiftLLreg
+ OpARMMVNshiftRLreg
+ OpARMMVNshiftRAreg
+ OpARMADCshiftLLreg
+ OpARMADCshiftRLreg
+ OpARMADCshiftRAreg
+ OpARMSBCshiftLLreg
+ OpARMSBCshiftRLreg
+ OpARMSBCshiftRAreg
+ OpARMRSCshiftLLreg
+ OpARMRSCshiftRLreg
+ OpARMRSCshiftRAreg
+ OpARMADDSshiftLLreg
+ OpARMADDSshiftRLreg
+ OpARMADDSshiftRAreg
+ OpARMSUBSshiftLLreg
+ OpARMSUBSshiftRLreg
+ OpARMSUBSshiftRAreg
+ OpARMRSBSshiftLLreg
+ OpARMRSBSshiftRLreg
+ OpARMRSBSshiftRAreg
+ OpARMCMP
+ OpARMCMPconst
+ OpARMCMN
+ OpARMCMNconst
+ OpARMTST
+ OpARMTSTconst
+ OpARMTEQ
+ OpARMTEQconst
+ OpARMCMPF
+ OpARMCMPD
+ OpARMCMPshiftLL
+ OpARMCMPshiftRL
+ OpARMCMPshiftRA
+ OpARMCMNshiftLL
+ OpARMCMNshiftRL
+ OpARMCMNshiftRA
+ OpARMTSTshiftLL
+ OpARMTSTshiftRL
+ OpARMTSTshiftRA
+ OpARMTEQshiftLL
+ OpARMTEQshiftRL
+ OpARMTEQshiftRA
+ OpARMCMPshiftLLreg
+ OpARMCMPshiftRLreg
+ OpARMCMPshiftRAreg
+ OpARMCMNshiftLLreg
+ OpARMCMNshiftRLreg
+ OpARMCMNshiftRAreg
+ OpARMTSTshiftLLreg
+ OpARMTSTshiftRLreg
+ OpARMTSTshiftRAreg
+ OpARMTEQshiftLLreg
+ OpARMTEQshiftRLreg
+ OpARMTEQshiftRAreg
+ OpARMCMPF0
+ OpARMCMPD0
+ OpARMMOVWconst
+ OpARMMOVFconst
+ OpARMMOVDconst
+ OpARMMOVWaddr
+ OpARMMOVBload
+ OpARMMOVBUload
+ OpARMMOVHload
+ OpARMMOVHUload
+ OpARMMOVWload
+ OpARMMOVFload
+ OpARMMOVDload
+ OpARMMOVBstore
+ OpARMMOVHstore
+ OpARMMOVWstore
+ OpARMMOVFstore
+ OpARMMOVDstore
+ OpARMMOVWloadidx
+ OpARMMOVWloadshiftLL
+ OpARMMOVWloadshiftRL
+ OpARMMOVWloadshiftRA
+ OpARMMOVBUloadidx
+ OpARMMOVBloadidx
+ OpARMMOVHUloadidx
+ OpARMMOVHloadidx
+ OpARMMOVWstoreidx
+ OpARMMOVWstoreshiftLL
+ OpARMMOVWstoreshiftRL
+ OpARMMOVWstoreshiftRA
+ OpARMMOVBstoreidx
+ OpARMMOVHstoreidx
+ OpARMMOVBreg
+ OpARMMOVBUreg
+ OpARMMOVHreg
+ OpARMMOVHUreg
+ OpARMMOVWreg
+ OpARMMOVWnop
+ OpARMMOVWF
+ OpARMMOVWD
+ OpARMMOVWUF
+ OpARMMOVWUD
+ OpARMMOVFW
+ OpARMMOVDW
+ OpARMMOVFWU
+ OpARMMOVDWU
+ OpARMMOVFD
+ OpARMMOVDF
+ OpARMCMOVWHSconst
+ OpARMCMOVWLSconst
+ OpARMSRAcond
+ OpARMCALLstatic
+ OpARMCALLclosure
+ OpARMCALLinter
+ OpARMLoweredNilCheck
+ OpARMEqual
+ OpARMNotEqual
+ OpARMLessThan
+ OpARMLessEqual
+ OpARMGreaterThan
+ OpARMGreaterEqual
+ OpARMLessThanU
+ OpARMLessEqualU
+ OpARMGreaterThanU
+ OpARMGreaterEqualU
+ OpARMDUFFZERO
+ OpARMDUFFCOPY
+ OpARMLoweredZero
+ OpARMLoweredMove
+ OpARMLoweredGetClosurePtr
+ OpARMLoweredGetCallerSP
+ OpARMLoweredGetCallerPC
+ OpARMLoweredPanicBoundsA
+ OpARMLoweredPanicBoundsB
+ OpARMLoweredPanicBoundsC
+ OpARMLoweredPanicExtendA
+ OpARMLoweredPanicExtendB
+ OpARMLoweredPanicExtendC
+ OpARMFlagConstant
+ OpARMInvertFlags
+ OpARMLoweredWB
+
+ OpARM64ADCSflags
+ OpARM64ADCzerocarry
+ OpARM64ADD
+ OpARM64ADDconst
+ OpARM64ADDSconstflags
+ OpARM64ADDSflags
+ OpARM64SUB
+ OpARM64SUBconst
+ OpARM64SBCSflags
+ OpARM64SUBSflags
+ OpARM64MUL
+ OpARM64MULW
+ OpARM64MNEG
+ OpARM64MNEGW
+ OpARM64MULH
+ OpARM64UMULH
+ OpARM64MULL
+ OpARM64UMULL
+ OpARM64DIV
+ OpARM64UDIV
+ OpARM64DIVW
+ OpARM64UDIVW
+ OpARM64MOD
+ OpARM64UMOD
+ OpARM64MODW
+ OpARM64UMODW
+ OpARM64FADDS
+ OpARM64FADDD
+ OpARM64FSUBS
+ OpARM64FSUBD
+ OpARM64FMULS
+ OpARM64FMULD
+ OpARM64FNMULS
+ OpARM64FNMULD
+ OpARM64FDIVS
+ OpARM64FDIVD
+ OpARM64AND
+ OpARM64ANDconst
+ OpARM64OR
+ OpARM64ORconst
+ OpARM64XOR
+ OpARM64XORconst
+ OpARM64BIC
+ OpARM64EON
+ OpARM64ORN
+ OpARM64LoweredMuluhilo
+ OpARM64MVN
+ OpARM64NEG
+ OpARM64NEGSflags
+ OpARM64NGCzerocarry
+ OpARM64FABSD
+ OpARM64FNEGS
+ OpARM64FNEGD
+ OpARM64FSQRTD
+ OpARM64REV
+ OpARM64REVW
+ OpARM64REV16W
+ OpARM64RBIT
+ OpARM64RBITW
+ OpARM64CLZ
+ OpARM64CLZW
+ OpARM64VCNT
+ OpARM64VUADDLV
+ OpARM64LoweredRound32F
+ OpARM64LoweredRound64F
+ OpARM64FMADDS
+ OpARM64FMADDD
+ OpARM64FNMADDS
+ OpARM64FNMADDD
+ OpARM64FMSUBS
+ OpARM64FMSUBD
+ OpARM64FNMSUBS
+ OpARM64FNMSUBD
+ OpARM64MADD
+ OpARM64MADDW
+ OpARM64MSUB
+ OpARM64MSUBW
+ OpARM64SLL
+ OpARM64SLLconst
+ OpARM64SRL
+ OpARM64SRLconst
+ OpARM64SRA
+ OpARM64SRAconst
+ OpARM64ROR
+ OpARM64RORW
+ OpARM64RORconst
+ OpARM64RORWconst
+ OpARM64EXTRconst
+ OpARM64EXTRWconst
+ OpARM64CMP
+ OpARM64CMPconst
+ OpARM64CMPW
+ OpARM64CMPWconst
+ OpARM64CMN
+ OpARM64CMNconst
+ OpARM64CMNW
+ OpARM64CMNWconst
+ OpARM64TST
+ OpARM64TSTconst
+ OpARM64TSTW
+ OpARM64TSTWconst
+ OpARM64FCMPS
+ OpARM64FCMPD
+ OpARM64FCMPS0
+ OpARM64FCMPD0
+ OpARM64MVNshiftLL
+ OpARM64MVNshiftRL
+ OpARM64MVNshiftRA
+ OpARM64NEGshiftLL
+ OpARM64NEGshiftRL
+ OpARM64NEGshiftRA
+ OpARM64ADDshiftLL
+ OpARM64ADDshiftRL
+ OpARM64ADDshiftRA
+ OpARM64SUBshiftLL
+ OpARM64SUBshiftRL
+ OpARM64SUBshiftRA
+ OpARM64ANDshiftLL
+ OpARM64ANDshiftRL
+ OpARM64ANDshiftRA
+ OpARM64ORshiftLL
+ OpARM64ORshiftRL
+ OpARM64ORshiftRA
+ OpARM64XORshiftLL
+ OpARM64XORshiftRL
+ OpARM64XORshiftRA
+ OpARM64BICshiftLL
+ OpARM64BICshiftRL
+ OpARM64BICshiftRA
+ OpARM64EONshiftLL
+ OpARM64EONshiftRL
+ OpARM64EONshiftRA
+ OpARM64ORNshiftLL
+ OpARM64ORNshiftRL
+ OpARM64ORNshiftRA
+ OpARM64CMPshiftLL
+ OpARM64CMPshiftRL
+ OpARM64CMPshiftRA
+ OpARM64CMNshiftLL
+ OpARM64CMNshiftRL
+ OpARM64CMNshiftRA
+ OpARM64TSTshiftLL
+ OpARM64TSTshiftRL
+ OpARM64TSTshiftRA
+ OpARM64BFI
+ OpARM64BFXIL
+ OpARM64SBFIZ
+ OpARM64SBFX
+ OpARM64UBFIZ
+ OpARM64UBFX
+ OpARM64MOVDconst
+ OpARM64FMOVSconst
+ OpARM64FMOVDconst
+ OpARM64MOVDaddr
+ OpARM64MOVBload
+ OpARM64MOVBUload
+ OpARM64MOVHload
+ OpARM64MOVHUload
+ OpARM64MOVWload
+ OpARM64MOVWUload
+ OpARM64MOVDload
+ OpARM64FMOVSload
+ OpARM64FMOVDload
+ OpARM64MOVDloadidx
+ OpARM64MOVWloadidx
+ OpARM64MOVWUloadidx
+ OpARM64MOVHloadidx
+ OpARM64MOVHUloadidx
+ OpARM64MOVBloadidx
+ OpARM64MOVBUloadidx
+ OpARM64FMOVSloadidx
+ OpARM64FMOVDloadidx
+ OpARM64MOVHloadidx2
+ OpARM64MOVHUloadidx2
+ OpARM64MOVWloadidx4
+ OpARM64MOVWUloadidx4
+ OpARM64MOVDloadidx8
+ OpARM64MOVBstore
+ OpARM64MOVHstore
+ OpARM64MOVWstore
+ OpARM64MOVDstore
+ OpARM64STP
+ OpARM64FMOVSstore
+ OpARM64FMOVDstore
+ OpARM64MOVBstoreidx
+ OpARM64MOVHstoreidx
+ OpARM64MOVWstoreidx
+ OpARM64MOVDstoreidx
+ OpARM64FMOVSstoreidx
+ OpARM64FMOVDstoreidx
+ OpARM64MOVHstoreidx2
+ OpARM64MOVWstoreidx4
+ OpARM64MOVDstoreidx8
+ OpARM64MOVBstorezero
+ OpARM64MOVHstorezero
+ OpARM64MOVWstorezero
+ OpARM64MOVDstorezero
+ OpARM64MOVQstorezero
+ OpARM64MOVBstorezeroidx
+ OpARM64MOVHstorezeroidx
+ OpARM64MOVWstorezeroidx
+ OpARM64MOVDstorezeroidx
+ OpARM64MOVHstorezeroidx2
+ OpARM64MOVWstorezeroidx4
+ OpARM64MOVDstorezeroidx8
+ OpARM64FMOVDgpfp
+ OpARM64FMOVDfpgp
+ OpARM64FMOVSgpfp
+ OpARM64FMOVSfpgp
+ OpARM64MOVBreg
+ OpARM64MOVBUreg
+ OpARM64MOVHreg
+ OpARM64MOVHUreg
+ OpARM64MOVWreg
+ OpARM64MOVWUreg
+ OpARM64MOVDreg
+ OpARM64MOVDnop
+ OpARM64SCVTFWS
+ OpARM64SCVTFWD
+ OpARM64UCVTFWS
+ OpARM64UCVTFWD
+ OpARM64SCVTFS
+ OpARM64SCVTFD
+ OpARM64UCVTFS
+ OpARM64UCVTFD
+ OpARM64FCVTZSSW
+ OpARM64FCVTZSDW
+ OpARM64FCVTZUSW
+ OpARM64FCVTZUDW
+ OpARM64FCVTZSS
+ OpARM64FCVTZSD
+ OpARM64FCVTZUS
+ OpARM64FCVTZUD
+ OpARM64FCVTSD
+ OpARM64FCVTDS
+ OpARM64FRINTAD
+ OpARM64FRINTMD
+ OpARM64FRINTND
+ OpARM64FRINTPD
+ OpARM64FRINTZD
+ OpARM64CSEL
+ OpARM64CSEL0
+ OpARM64CALLstatic
+ OpARM64CALLclosure
+ OpARM64CALLinter
+ OpARM64LoweredNilCheck
+ OpARM64Equal
+ OpARM64NotEqual
+ OpARM64LessThan
+ OpARM64LessEqual
+ OpARM64GreaterThan
+ OpARM64GreaterEqual
+ OpARM64LessThanU
+ OpARM64LessEqualU
+ OpARM64GreaterThanU
+ OpARM64GreaterEqualU
+ OpARM64LessThanF
+ OpARM64LessEqualF
+ OpARM64GreaterThanF
+ OpARM64GreaterEqualF
+ OpARM64NotLessThanF
+ OpARM64NotLessEqualF
+ OpARM64NotGreaterThanF
+ OpARM64NotGreaterEqualF
+ OpARM64DUFFZERO
+ OpARM64LoweredZero
+ OpARM64DUFFCOPY
+ OpARM64LoweredMove
+ OpARM64LoweredGetClosurePtr
+ OpARM64LoweredGetCallerSP
+ OpARM64LoweredGetCallerPC
+ OpARM64FlagConstant
+ OpARM64InvertFlags
+ OpARM64LDAR
+ OpARM64LDARB
+ OpARM64LDARW
+ OpARM64STLRB
+ OpARM64STLR
+ OpARM64STLRW
+ OpARM64LoweredAtomicExchange64
+ OpARM64LoweredAtomicExchange32
+ OpARM64LoweredAtomicExchange64Variant
+ OpARM64LoweredAtomicExchange32Variant
+ OpARM64LoweredAtomicAdd64
+ OpARM64LoweredAtomicAdd32
+ OpARM64LoweredAtomicAdd64Variant
+ OpARM64LoweredAtomicAdd32Variant
+ OpARM64LoweredAtomicCas64
+ OpARM64LoweredAtomicCas32
+ OpARM64LoweredAtomicCas64Variant
+ OpARM64LoweredAtomicCas32Variant
+ OpARM64LoweredAtomicAnd8
+ OpARM64LoweredAtomicAnd32
+ OpARM64LoweredAtomicOr8
+ OpARM64LoweredAtomicOr32
+ OpARM64LoweredAtomicAnd8Variant
+ OpARM64LoweredAtomicAnd32Variant
+ OpARM64LoweredAtomicOr8Variant
+ OpARM64LoweredAtomicOr32Variant
+ OpARM64LoweredWB
+ OpARM64LoweredPanicBoundsA
+ OpARM64LoweredPanicBoundsB
+ OpARM64LoweredPanicBoundsC
+
+ OpMIPSADD
+ OpMIPSADDconst
+ OpMIPSSUB
+ OpMIPSSUBconst
+ OpMIPSMUL
+ OpMIPSMULT
+ OpMIPSMULTU
+ OpMIPSDIV
+ OpMIPSDIVU
+ OpMIPSADDF
+ OpMIPSADDD
+ OpMIPSSUBF
+ OpMIPSSUBD
+ OpMIPSMULF
+ OpMIPSMULD
+ OpMIPSDIVF
+ OpMIPSDIVD
+ OpMIPSAND
+ OpMIPSANDconst
+ OpMIPSOR
+ OpMIPSORconst
+ OpMIPSXOR
+ OpMIPSXORconst
+ OpMIPSNOR
+ OpMIPSNORconst
+ OpMIPSNEG
+ OpMIPSNEGF
+ OpMIPSNEGD
+ OpMIPSSQRTD
+ OpMIPSSLL
+ OpMIPSSLLconst
+ OpMIPSSRL
+ OpMIPSSRLconst
+ OpMIPSSRA
+ OpMIPSSRAconst
+ OpMIPSCLZ
+ OpMIPSSGT
+ OpMIPSSGTconst
+ OpMIPSSGTzero
+ OpMIPSSGTU
+ OpMIPSSGTUconst
+ OpMIPSSGTUzero
+ OpMIPSCMPEQF
+ OpMIPSCMPEQD
+ OpMIPSCMPGEF
+ OpMIPSCMPGED
+ OpMIPSCMPGTF
+ OpMIPSCMPGTD
+ OpMIPSMOVWconst
+ OpMIPSMOVFconst
+ OpMIPSMOVDconst
+ OpMIPSMOVWaddr
+ OpMIPSMOVBload
+ OpMIPSMOVBUload
+ OpMIPSMOVHload
+ OpMIPSMOVHUload
+ OpMIPSMOVWload
+ OpMIPSMOVFload
+ OpMIPSMOVDload
+ OpMIPSMOVBstore
+ OpMIPSMOVHstore
+ OpMIPSMOVWstore
+ OpMIPSMOVFstore
+ OpMIPSMOVDstore
+ OpMIPSMOVBstorezero
+ OpMIPSMOVHstorezero
+ OpMIPSMOVWstorezero
+ OpMIPSMOVBreg
+ OpMIPSMOVBUreg
+ OpMIPSMOVHreg
+ OpMIPSMOVHUreg
+ OpMIPSMOVWreg
+ OpMIPSMOVWnop
+ OpMIPSCMOVZ
+ OpMIPSCMOVZzero
+ OpMIPSMOVWF
+ OpMIPSMOVWD
+ OpMIPSTRUNCFW
+ OpMIPSTRUNCDW
+ OpMIPSMOVFD
+ OpMIPSMOVDF
+ OpMIPSCALLstatic
+ OpMIPSCALLclosure
+ OpMIPSCALLinter
+ OpMIPSLoweredAtomicLoad8
+ OpMIPSLoweredAtomicLoad32
+ OpMIPSLoweredAtomicStore8
+ OpMIPSLoweredAtomicStore32
+ OpMIPSLoweredAtomicStorezero
+ OpMIPSLoweredAtomicExchange
+ OpMIPSLoweredAtomicAdd
+ OpMIPSLoweredAtomicAddconst
+ OpMIPSLoweredAtomicCas
+ OpMIPSLoweredAtomicAnd
+ OpMIPSLoweredAtomicOr
+ OpMIPSLoweredZero
+ OpMIPSLoweredMove
+ OpMIPSLoweredNilCheck
+ OpMIPSFPFlagTrue
+ OpMIPSFPFlagFalse
+ OpMIPSLoweredGetClosurePtr
+ OpMIPSLoweredGetCallerSP
+ OpMIPSLoweredGetCallerPC
+ OpMIPSLoweredWB
+ OpMIPSLoweredPanicBoundsA
+ OpMIPSLoweredPanicBoundsB
+ OpMIPSLoweredPanicBoundsC
+ OpMIPSLoweredPanicExtendA
+ OpMIPSLoweredPanicExtendB
+ OpMIPSLoweredPanicExtendC
+
+ OpMIPS64ADDV
+ OpMIPS64ADDVconst
+ OpMIPS64SUBV
+ OpMIPS64SUBVconst
+ OpMIPS64MULV
+ OpMIPS64MULVU
+ OpMIPS64DIVV
+ OpMIPS64DIVVU
+ OpMIPS64ADDF
+ OpMIPS64ADDD
+ OpMIPS64SUBF
+ OpMIPS64SUBD
+ OpMIPS64MULF
+ OpMIPS64MULD
+ OpMIPS64DIVF
+ OpMIPS64DIVD
+ OpMIPS64AND
+ OpMIPS64ANDconst
+ OpMIPS64OR
+ OpMIPS64ORconst
+ OpMIPS64XOR
+ OpMIPS64XORconst
+ OpMIPS64NOR
+ OpMIPS64NORconst
+ OpMIPS64NEGV
+ OpMIPS64NEGF
+ OpMIPS64NEGD
+ OpMIPS64SQRTD
+ OpMIPS64SLLV
+ OpMIPS64SLLVconst
+ OpMIPS64SRLV
+ OpMIPS64SRLVconst
+ OpMIPS64SRAV
+ OpMIPS64SRAVconst
+ OpMIPS64SGT
+ OpMIPS64SGTconst
+ OpMIPS64SGTU
+ OpMIPS64SGTUconst
+ OpMIPS64CMPEQF
+ OpMIPS64CMPEQD
+ OpMIPS64CMPGEF
+ OpMIPS64CMPGED
+ OpMIPS64CMPGTF
+ OpMIPS64CMPGTD
+ OpMIPS64MOVVconst
+ OpMIPS64MOVFconst
+ OpMIPS64MOVDconst
+ OpMIPS64MOVVaddr
+ OpMIPS64MOVBload
+ OpMIPS64MOVBUload
+ OpMIPS64MOVHload
+ OpMIPS64MOVHUload
+ OpMIPS64MOVWload
+ OpMIPS64MOVWUload
+ OpMIPS64MOVVload
+ OpMIPS64MOVFload
+ OpMIPS64MOVDload
+ OpMIPS64MOVBstore
+ OpMIPS64MOVHstore
+ OpMIPS64MOVWstore
+ OpMIPS64MOVVstore
+ OpMIPS64MOVFstore
+ OpMIPS64MOVDstore
+ OpMIPS64MOVBstorezero
+ OpMIPS64MOVHstorezero
+ OpMIPS64MOVWstorezero
+ OpMIPS64MOVVstorezero
+ OpMIPS64MOVBreg
+ OpMIPS64MOVBUreg
+ OpMIPS64MOVHreg
+ OpMIPS64MOVHUreg
+ OpMIPS64MOVWreg
+ OpMIPS64MOVWUreg
+ OpMIPS64MOVVreg
+ OpMIPS64MOVVnop
+ OpMIPS64MOVWF
+ OpMIPS64MOVWD
+ OpMIPS64MOVVF
+ OpMIPS64MOVVD
+ OpMIPS64TRUNCFW
+ OpMIPS64TRUNCDW
+ OpMIPS64TRUNCFV
+ OpMIPS64TRUNCDV
+ OpMIPS64MOVFD
+ OpMIPS64MOVDF
+ OpMIPS64CALLstatic
+ OpMIPS64CALLclosure
+ OpMIPS64CALLinter
+ OpMIPS64DUFFZERO
+ OpMIPS64DUFFCOPY
+ OpMIPS64LoweredZero
+ OpMIPS64LoweredMove
+ OpMIPS64LoweredAtomicLoad8
+ OpMIPS64LoweredAtomicLoad32
+ OpMIPS64LoweredAtomicLoad64
+ OpMIPS64LoweredAtomicStore8
+ OpMIPS64LoweredAtomicStore32
+ OpMIPS64LoweredAtomicStore64
+ OpMIPS64LoweredAtomicStorezero32
+ OpMIPS64LoweredAtomicStorezero64
+ OpMIPS64LoweredAtomicExchange32
+ OpMIPS64LoweredAtomicExchange64
+ OpMIPS64LoweredAtomicAdd32
+ OpMIPS64LoweredAtomicAdd64
+ OpMIPS64LoweredAtomicAddconst32
+ OpMIPS64LoweredAtomicAddconst64
+ OpMIPS64LoweredAtomicCas32
+ OpMIPS64LoweredAtomicCas64
+ OpMIPS64LoweredNilCheck
+ OpMIPS64FPFlagTrue
+ OpMIPS64FPFlagFalse
+ OpMIPS64LoweredGetClosurePtr
+ OpMIPS64LoweredGetCallerSP
+ OpMIPS64LoweredGetCallerPC
+ OpMIPS64LoweredWB
+ OpMIPS64LoweredPanicBoundsA
+ OpMIPS64LoweredPanicBoundsB
+ OpMIPS64LoweredPanicBoundsC
+
+ OpPPC64ADD
+ OpPPC64ADDconst
+ OpPPC64FADD
+ OpPPC64FADDS
+ OpPPC64SUB
+ OpPPC64SUBFCconst
+ OpPPC64FSUB
+ OpPPC64FSUBS
+ OpPPC64MULLD
+ OpPPC64MULLW
+ OpPPC64MULLDconst
+ OpPPC64MULLWconst
+ OpPPC64MADDLD
+ OpPPC64MULHD
+ OpPPC64MULHW
+ OpPPC64MULHDU
+ OpPPC64MULHWU
+ OpPPC64LoweredMuluhilo
+ OpPPC64FMUL
+ OpPPC64FMULS
+ OpPPC64FMADD
+ OpPPC64FMADDS
+ OpPPC64FMSUB
+ OpPPC64FMSUBS
+ OpPPC64SRAD
+ OpPPC64SRAW
+ OpPPC64SRD
+ OpPPC64SRW
+ OpPPC64SLD
+ OpPPC64SLW
+ OpPPC64ROTL
+ OpPPC64ROTLW
+ OpPPC64RLDICL
+ OpPPC64CLRLSLWI
+ OpPPC64CLRLSLDI
+ OpPPC64LoweredAdd64Carry
+ OpPPC64SRADconst
+ OpPPC64SRAWconst
+ OpPPC64SRDconst
+ OpPPC64SRWconst
+ OpPPC64SLDconst
+ OpPPC64SLWconst
+ OpPPC64ROTLconst
+ OpPPC64ROTLWconst
+ OpPPC64EXTSWSLconst
+ OpPPC64RLWINM
+ OpPPC64RLWNM
+ OpPPC64RLWMI
+ OpPPC64CNTLZD
+ OpPPC64CNTLZW
+ OpPPC64CNTTZD
+ OpPPC64CNTTZW
+ OpPPC64POPCNTD
+ OpPPC64POPCNTW
+ OpPPC64POPCNTB
+ OpPPC64FDIV
+ OpPPC64FDIVS
+ OpPPC64DIVD
+ OpPPC64DIVW
+ OpPPC64DIVDU
+ OpPPC64DIVWU
+ OpPPC64MODUD
+ OpPPC64MODSD
+ OpPPC64MODUW
+ OpPPC64MODSW
+ OpPPC64FCTIDZ
+ OpPPC64FCTIWZ
+ OpPPC64FCFID
+ OpPPC64FCFIDS
+ OpPPC64FRSP
+ OpPPC64MFVSRD
+ OpPPC64MTVSRD
+ OpPPC64AND
+ OpPPC64ANDN
+ OpPPC64ANDCC
+ OpPPC64OR
+ OpPPC64ORN
+ OpPPC64ORCC
+ OpPPC64NOR
+ OpPPC64XOR
+ OpPPC64XORCC
+ OpPPC64EQV
+ OpPPC64NEG
+ OpPPC64FNEG
+ OpPPC64FSQRT
+ OpPPC64FSQRTS
+ OpPPC64FFLOOR
+ OpPPC64FCEIL
+ OpPPC64FTRUNC
+ OpPPC64FROUND
+ OpPPC64FABS
+ OpPPC64FNABS
+ OpPPC64FCPSGN
+ OpPPC64ORconst
+ OpPPC64XORconst
+ OpPPC64ANDconst
+ OpPPC64ANDCCconst
+ OpPPC64MOVBreg
+ OpPPC64MOVBZreg
+ OpPPC64MOVHreg
+ OpPPC64MOVHZreg
+ OpPPC64MOVWreg
+ OpPPC64MOVWZreg
+ OpPPC64MOVBZload
+ OpPPC64MOVHload
+ OpPPC64MOVHZload
+ OpPPC64MOVWload
+ OpPPC64MOVWZload
+ OpPPC64MOVDload
+ OpPPC64MOVDBRload
+ OpPPC64MOVWBRload
+ OpPPC64MOVHBRload
+ OpPPC64MOVBZloadidx
+ OpPPC64MOVHloadidx
+ OpPPC64MOVHZloadidx
+ OpPPC64MOVWloadidx
+ OpPPC64MOVWZloadidx
+ OpPPC64MOVDloadidx
+ OpPPC64MOVHBRloadidx
+ OpPPC64MOVWBRloadidx
+ OpPPC64MOVDBRloadidx
+ OpPPC64FMOVDloadidx
+ OpPPC64FMOVSloadidx
+ OpPPC64MOVDBRstore
+ OpPPC64MOVWBRstore
+ OpPPC64MOVHBRstore
+ OpPPC64FMOVDload
+ OpPPC64FMOVSload
+ OpPPC64MOVBstore
+ OpPPC64MOVHstore
+ OpPPC64MOVWstore
+ OpPPC64MOVDstore
+ OpPPC64FMOVDstore
+ OpPPC64FMOVSstore
+ OpPPC64MOVBstoreidx
+ OpPPC64MOVHstoreidx
+ OpPPC64MOVWstoreidx
+ OpPPC64MOVDstoreidx
+ OpPPC64FMOVDstoreidx
+ OpPPC64FMOVSstoreidx
+ OpPPC64MOVHBRstoreidx
+ OpPPC64MOVWBRstoreidx
+ OpPPC64MOVDBRstoreidx
+ OpPPC64MOVBstorezero
+ OpPPC64MOVHstorezero
+ OpPPC64MOVWstorezero
+ OpPPC64MOVDstorezero
+ OpPPC64MOVDaddr
+ OpPPC64MOVDconst
+ OpPPC64FMOVDconst
+ OpPPC64FMOVSconst
+ OpPPC64FCMPU
+ OpPPC64CMP
+ OpPPC64CMPU
+ OpPPC64CMPW
+ OpPPC64CMPWU
+ OpPPC64CMPconst
+ OpPPC64CMPUconst
+ OpPPC64CMPWconst
+ OpPPC64CMPWUconst
+ OpPPC64ISEL
+ OpPPC64ISELB
+ OpPPC64Equal
+ OpPPC64NotEqual
+ OpPPC64LessThan
+ OpPPC64FLessThan
+ OpPPC64LessEqual
+ OpPPC64FLessEqual
+ OpPPC64GreaterThan
+ OpPPC64FGreaterThan
+ OpPPC64GreaterEqual
+ OpPPC64FGreaterEqual
+ OpPPC64LoweredGetClosurePtr
+ OpPPC64LoweredGetCallerSP
+ OpPPC64LoweredGetCallerPC
+ OpPPC64LoweredNilCheck
+ OpPPC64LoweredRound32F
+ OpPPC64LoweredRound64F
+ OpPPC64CALLstatic
+ OpPPC64CALLclosure
+ OpPPC64CALLinter
+ OpPPC64LoweredZero
+ OpPPC64LoweredZeroShort
+ OpPPC64LoweredQuadZeroShort
+ OpPPC64LoweredQuadZero
+ OpPPC64LoweredMove
+ OpPPC64LoweredMoveShort
+ OpPPC64LoweredQuadMove
+ OpPPC64LoweredQuadMoveShort
+ OpPPC64LoweredAtomicStore8
+ OpPPC64LoweredAtomicStore32
+ OpPPC64LoweredAtomicStore64
+ OpPPC64LoweredAtomicLoad8
+ OpPPC64LoweredAtomicLoad32
+ OpPPC64LoweredAtomicLoad64
+ OpPPC64LoweredAtomicLoadPtr
+ OpPPC64LoweredAtomicAdd32
+ OpPPC64LoweredAtomicAdd64
+ OpPPC64LoweredAtomicExchange32
+ OpPPC64LoweredAtomicExchange64
+ OpPPC64LoweredAtomicCas64
+ OpPPC64LoweredAtomicCas32
+ OpPPC64LoweredAtomicAnd8
+ OpPPC64LoweredAtomicAnd32
+ OpPPC64LoweredAtomicOr8
+ OpPPC64LoweredAtomicOr32
+ OpPPC64LoweredWB
+ OpPPC64LoweredPanicBoundsA
+ OpPPC64LoweredPanicBoundsB
+ OpPPC64LoweredPanicBoundsC
+ OpPPC64InvertFlags
+ OpPPC64FlagEQ
+ OpPPC64FlagLT
+ OpPPC64FlagGT
+
+ OpRISCV64ADD
+ OpRISCV64ADDI
+ OpRISCV64ADDIW
+ OpRISCV64NEG
+ OpRISCV64NEGW
+ OpRISCV64SUB
+ OpRISCV64SUBW
+ OpRISCV64MUL
+ OpRISCV64MULW
+ OpRISCV64MULH
+ OpRISCV64MULHU
+ OpRISCV64DIV
+ OpRISCV64DIVU
+ OpRISCV64DIVW
+ OpRISCV64DIVUW
+ OpRISCV64REM
+ OpRISCV64REMU
+ OpRISCV64REMW
+ OpRISCV64REMUW
+ OpRISCV64MOVaddr
+ OpRISCV64MOVBconst
+ OpRISCV64MOVHconst
+ OpRISCV64MOVWconst
+ OpRISCV64MOVDconst
+ OpRISCV64MOVBload
+ OpRISCV64MOVHload
+ OpRISCV64MOVWload
+ OpRISCV64MOVDload
+ OpRISCV64MOVBUload
+ OpRISCV64MOVHUload
+ OpRISCV64MOVWUload
+ OpRISCV64MOVBstore
+ OpRISCV64MOVHstore
+ OpRISCV64MOVWstore
+ OpRISCV64MOVDstore
+ OpRISCV64MOVBstorezero
+ OpRISCV64MOVHstorezero
+ OpRISCV64MOVWstorezero
+ OpRISCV64MOVDstorezero
+ OpRISCV64MOVBreg
+ OpRISCV64MOVHreg
+ OpRISCV64MOVWreg
+ OpRISCV64MOVDreg
+ OpRISCV64MOVBUreg
+ OpRISCV64MOVHUreg
+ OpRISCV64MOVWUreg
+ OpRISCV64MOVDnop
+ OpRISCV64SLL
+ OpRISCV64SRA
+ OpRISCV64SRL
+ OpRISCV64SLLI
+ OpRISCV64SRAI
+ OpRISCV64SRLI
+ OpRISCV64XOR
+ OpRISCV64XORI
+ OpRISCV64OR
+ OpRISCV64ORI
+ OpRISCV64AND
+ OpRISCV64ANDI
+ OpRISCV64NOT
+ OpRISCV64SEQZ
+ OpRISCV64SNEZ
+ OpRISCV64SLT
+ OpRISCV64SLTI
+ OpRISCV64SLTU
+ OpRISCV64SLTIU
+ OpRISCV64MOVconvert
+ OpRISCV64CALLstatic
+ OpRISCV64CALLclosure
+ OpRISCV64CALLinter
+ OpRISCV64DUFFZERO
+ OpRISCV64DUFFCOPY
+ OpRISCV64LoweredZero
+ OpRISCV64LoweredMove
+ OpRISCV64LoweredAtomicLoad8
+ OpRISCV64LoweredAtomicLoad32
+ OpRISCV64LoweredAtomicLoad64
+ OpRISCV64LoweredAtomicStore8
+ OpRISCV64LoweredAtomicStore32
+ OpRISCV64LoweredAtomicStore64
+ OpRISCV64LoweredAtomicExchange32
+ OpRISCV64LoweredAtomicExchange64
+ OpRISCV64LoweredAtomicAdd32
+ OpRISCV64LoweredAtomicAdd64
+ OpRISCV64LoweredAtomicCas32
+ OpRISCV64LoweredAtomicCas64
+ OpRISCV64LoweredNilCheck
+ OpRISCV64LoweredGetClosurePtr
+ OpRISCV64LoweredGetCallerSP
+ OpRISCV64LoweredGetCallerPC
+ OpRISCV64LoweredWB
+ OpRISCV64LoweredPanicBoundsA
+ OpRISCV64LoweredPanicBoundsB
+ OpRISCV64LoweredPanicBoundsC
+ OpRISCV64FADDS
+ OpRISCV64FSUBS
+ OpRISCV64FMULS
+ OpRISCV64FDIVS
+ OpRISCV64FSQRTS
+ OpRISCV64FNEGS
+ OpRISCV64FMVSX
+ OpRISCV64FCVTSW
+ OpRISCV64FCVTSL
+ OpRISCV64FCVTWS
+ OpRISCV64FCVTLS
+ OpRISCV64FMOVWload
+ OpRISCV64FMOVWstore
+ OpRISCV64FEQS
+ OpRISCV64FNES
+ OpRISCV64FLTS
+ OpRISCV64FLES
+ OpRISCV64FADDD
+ OpRISCV64FSUBD
+ OpRISCV64FMULD
+ OpRISCV64FDIVD
+ OpRISCV64FSQRTD
+ OpRISCV64FNEGD
+ OpRISCV64FMVDX
+ OpRISCV64FCVTDW
+ OpRISCV64FCVTDL
+ OpRISCV64FCVTWD
+ OpRISCV64FCVTLD
+ OpRISCV64FCVTDS
+ OpRISCV64FCVTSD
+ OpRISCV64FMOVDload
+ OpRISCV64FMOVDstore
+ OpRISCV64FEQD
+ OpRISCV64FNED
+ OpRISCV64FLTD
+ OpRISCV64FLED
+
+ OpS390XFADDS
+ OpS390XFADD
+ OpS390XFSUBS
+ OpS390XFSUB
+ OpS390XFMULS
+ OpS390XFMUL
+ OpS390XFDIVS
+ OpS390XFDIV
+ OpS390XFNEGS
+ OpS390XFNEG
+ OpS390XFMADDS
+ OpS390XFMADD
+ OpS390XFMSUBS
+ OpS390XFMSUB
+ OpS390XLPDFR
+ OpS390XLNDFR
+ OpS390XCPSDR
+ OpS390XFIDBR
+ OpS390XFMOVSload
+ OpS390XFMOVDload
+ OpS390XFMOVSconst
+ OpS390XFMOVDconst
+ OpS390XFMOVSloadidx
+ OpS390XFMOVDloadidx
+ OpS390XFMOVSstore
+ OpS390XFMOVDstore
+ OpS390XFMOVSstoreidx
+ OpS390XFMOVDstoreidx
+ OpS390XADD
+ OpS390XADDW
+ OpS390XADDconst
+ OpS390XADDWconst
+ OpS390XADDload
+ OpS390XADDWload
+ OpS390XSUB
+ OpS390XSUBW
+ OpS390XSUBconst
+ OpS390XSUBWconst
+ OpS390XSUBload
+ OpS390XSUBWload
+ OpS390XMULLD
+ OpS390XMULLW
+ OpS390XMULLDconst
+ OpS390XMULLWconst
+ OpS390XMULLDload
+ OpS390XMULLWload
+ OpS390XMULHD
+ OpS390XMULHDU
+ OpS390XDIVD
+ OpS390XDIVW
+ OpS390XDIVDU
+ OpS390XDIVWU
+ OpS390XMODD
+ OpS390XMODW
+ OpS390XMODDU
+ OpS390XMODWU
+ OpS390XAND
+ OpS390XANDW
+ OpS390XANDconst
+ OpS390XANDWconst
+ OpS390XANDload
+ OpS390XANDWload
+ OpS390XOR
+ OpS390XORW
+ OpS390XORconst
+ OpS390XORWconst
+ OpS390XORload
+ OpS390XORWload
+ OpS390XXOR
+ OpS390XXORW
+ OpS390XXORconst
+ OpS390XXORWconst
+ OpS390XXORload
+ OpS390XXORWload
+ OpS390XADDC
+ OpS390XADDCconst
+ OpS390XADDE
+ OpS390XSUBC
+ OpS390XSUBE
+ OpS390XCMP
+ OpS390XCMPW
+ OpS390XCMPU
+ OpS390XCMPWU
+ OpS390XCMPconst
+ OpS390XCMPWconst
+ OpS390XCMPUconst
+ OpS390XCMPWUconst
+ OpS390XFCMPS
+ OpS390XFCMP
+ OpS390XLTDBR
+ OpS390XLTEBR
+ OpS390XSLD
+ OpS390XSLW
+ OpS390XSLDconst
+ OpS390XSLWconst
+ OpS390XSRD
+ OpS390XSRW
+ OpS390XSRDconst
+ OpS390XSRWconst
+ OpS390XSRAD
+ OpS390XSRAW
+ OpS390XSRADconst
+ OpS390XSRAWconst
+ OpS390XRLLG
+ OpS390XRLL
+ OpS390XRLLconst
+ OpS390XRXSBG
+ OpS390XRISBGZ
+ OpS390XNEG
+ OpS390XNEGW
+ OpS390XNOT
+ OpS390XNOTW
+ OpS390XFSQRT
+ OpS390XLOCGR
+ OpS390XMOVBreg
+ OpS390XMOVBZreg
+ OpS390XMOVHreg
+ OpS390XMOVHZreg
+ OpS390XMOVWreg
+ OpS390XMOVWZreg
+ OpS390XMOVDconst
+ OpS390XLDGR
+ OpS390XLGDR
+ OpS390XCFDBRA
+ OpS390XCGDBRA
+ OpS390XCFEBRA
+ OpS390XCGEBRA
+ OpS390XCEFBRA
+ OpS390XCDFBRA
+ OpS390XCEGBRA
+ OpS390XCDGBRA
+ OpS390XCLFEBR
+ OpS390XCLFDBR
+ OpS390XCLGEBR
+ OpS390XCLGDBR
+ OpS390XCELFBR
+ OpS390XCDLFBR
+ OpS390XCELGBR
+ OpS390XCDLGBR
+ OpS390XLEDBR
+ OpS390XLDEBR
+ OpS390XMOVDaddr
+ OpS390XMOVDaddridx
+ OpS390XMOVBZload
+ OpS390XMOVBload
+ OpS390XMOVHZload
+ OpS390XMOVHload
+ OpS390XMOVWZload
+ OpS390XMOVWload
+ OpS390XMOVDload
+ OpS390XMOVWBR
+ OpS390XMOVDBR
+ OpS390XMOVHBRload
+ OpS390XMOVWBRload
+ OpS390XMOVDBRload
+ OpS390XMOVBstore
+ OpS390XMOVHstore
+ OpS390XMOVWstore
+ OpS390XMOVDstore
+ OpS390XMOVHBRstore
+ OpS390XMOVWBRstore
+ OpS390XMOVDBRstore
+ OpS390XMVC
+ OpS390XMOVBZloadidx
+ OpS390XMOVBloadidx
+ OpS390XMOVHZloadidx
+ OpS390XMOVHloadidx
+ OpS390XMOVWZloadidx
+ OpS390XMOVWloadidx
+ OpS390XMOVDloadidx
+ OpS390XMOVHBRloadidx
+ OpS390XMOVWBRloadidx
+ OpS390XMOVDBRloadidx
+ OpS390XMOVBstoreidx
+ OpS390XMOVHstoreidx
+ OpS390XMOVWstoreidx
+ OpS390XMOVDstoreidx
+ OpS390XMOVHBRstoreidx
+ OpS390XMOVWBRstoreidx
+ OpS390XMOVDBRstoreidx
+ OpS390XMOVBstoreconst
+ OpS390XMOVHstoreconst
+ OpS390XMOVWstoreconst
+ OpS390XMOVDstoreconst
+ OpS390XCLEAR
+ OpS390XCALLstatic
+ OpS390XCALLclosure
+ OpS390XCALLinter
+ OpS390XInvertFlags
+ OpS390XLoweredGetG
+ OpS390XLoweredGetClosurePtr
+ OpS390XLoweredGetCallerSP
+ OpS390XLoweredGetCallerPC
+ OpS390XLoweredNilCheck
+ OpS390XLoweredRound32F
+ OpS390XLoweredRound64F
+ OpS390XLoweredWB
+ OpS390XLoweredPanicBoundsA
+ OpS390XLoweredPanicBoundsB
+ OpS390XLoweredPanicBoundsC
+ OpS390XFlagEQ
+ OpS390XFlagLT
+ OpS390XFlagGT
+ OpS390XFlagOV
+ OpS390XSYNC
+ OpS390XMOVBZatomicload
+ OpS390XMOVWZatomicload
+ OpS390XMOVDatomicload
+ OpS390XMOVBatomicstore
+ OpS390XMOVWatomicstore
+ OpS390XMOVDatomicstore
+ OpS390XLAA
+ OpS390XLAAG
+ OpS390XAddTupleFirst32
+ OpS390XAddTupleFirst64
+ OpS390XLAN
+ OpS390XLANfloor
+ OpS390XLAO
+ OpS390XLAOfloor
+ OpS390XLoweredAtomicCas32
+ OpS390XLoweredAtomicCas64
+ OpS390XLoweredAtomicExchange32
+ OpS390XLoweredAtomicExchange64
+ OpS390XFLOGR
+ OpS390XPOPCNT
+ OpS390XMLGR
+ OpS390XSumBytes2
+ OpS390XSumBytes4
+ OpS390XSumBytes8
+ OpS390XSTMG2
+ OpS390XSTMG3
+ OpS390XSTMG4
+ OpS390XSTM2
+ OpS390XSTM3
+ OpS390XSTM4
+ OpS390XLoweredMove
+ OpS390XLoweredZero
+
+ OpWasmLoweredStaticCall
+ OpWasmLoweredClosureCall
+ OpWasmLoweredInterCall
+ OpWasmLoweredAddr
+ OpWasmLoweredMove
+ OpWasmLoweredZero
+ OpWasmLoweredGetClosurePtr
+ OpWasmLoweredGetCallerPC
+ OpWasmLoweredGetCallerSP
+ OpWasmLoweredNilCheck
+ OpWasmLoweredWB
+ OpWasmLoweredConvert
+ OpWasmSelect
+ OpWasmI64Load8U
+ OpWasmI64Load8S
+ OpWasmI64Load16U
+ OpWasmI64Load16S
+ OpWasmI64Load32U
+ OpWasmI64Load32S
+ OpWasmI64Load
+ OpWasmI64Store8
+ OpWasmI64Store16
+ OpWasmI64Store32
+ OpWasmI64Store
+ OpWasmF32Load
+ OpWasmF64Load
+ OpWasmF32Store
+ OpWasmF64Store
+ OpWasmI64Const
+ OpWasmF32Const
+ OpWasmF64Const
+ OpWasmI64Eqz
+ OpWasmI64Eq
+ OpWasmI64Ne
+ OpWasmI64LtS
+ OpWasmI64LtU
+ OpWasmI64GtS
+ OpWasmI64GtU
+ OpWasmI64LeS
+ OpWasmI64LeU
+ OpWasmI64GeS
+ OpWasmI64GeU
+ OpWasmF32Eq
+ OpWasmF32Ne
+ OpWasmF32Lt
+ OpWasmF32Gt
+ OpWasmF32Le
+ OpWasmF32Ge
+ OpWasmF64Eq
+ OpWasmF64Ne
+ OpWasmF64Lt
+ OpWasmF64Gt
+ OpWasmF64Le
+ OpWasmF64Ge
+ OpWasmI64Add
+ OpWasmI64AddConst
+ OpWasmI64Sub
+ OpWasmI64Mul
+ OpWasmI64DivS
+ OpWasmI64DivU
+ OpWasmI64RemS
+ OpWasmI64RemU
+ OpWasmI64And
+ OpWasmI64Or
+ OpWasmI64Xor
+ OpWasmI64Shl
+ OpWasmI64ShrS
+ OpWasmI64ShrU
+ OpWasmF32Neg
+ OpWasmF32Add
+ OpWasmF32Sub
+ OpWasmF32Mul
+ OpWasmF32Div
+ OpWasmF64Neg
+ OpWasmF64Add
+ OpWasmF64Sub
+ OpWasmF64Mul
+ OpWasmF64Div
+ OpWasmI64TruncSatF64S
+ OpWasmI64TruncSatF64U
+ OpWasmI64TruncSatF32S
+ OpWasmI64TruncSatF32U
+ OpWasmF32ConvertI64S
+ OpWasmF32ConvertI64U
+ OpWasmF64ConvertI64S
+ OpWasmF64ConvertI64U
+ OpWasmF32DemoteF64
+ OpWasmF64PromoteF32
+ OpWasmI64Extend8S
+ OpWasmI64Extend16S
+ OpWasmI64Extend32S
+ OpWasmF32Sqrt
+ OpWasmF32Trunc
+ OpWasmF32Ceil
+ OpWasmF32Floor
+ OpWasmF32Nearest
+ OpWasmF32Abs
+ OpWasmF32Copysign
+ OpWasmF64Sqrt
+ OpWasmF64Trunc
+ OpWasmF64Ceil
+ OpWasmF64Floor
+ OpWasmF64Nearest
+ OpWasmF64Abs
+ OpWasmF64Copysign
+ OpWasmI64Ctz
+ OpWasmI64Clz
+ OpWasmI32Rotl
+ OpWasmI64Rotl
+ OpWasmI64Popcnt
+
+ OpAdd8
+ OpAdd16
+ OpAdd32
+ OpAdd64
+ OpAddPtr
+ OpAdd32F
+ OpAdd64F
+ OpSub8
+ OpSub16
+ OpSub32
+ OpSub64
+ OpSubPtr
+ OpSub32F
+ OpSub64F
+ OpMul8
+ OpMul16
+ OpMul32
+ OpMul64
+ OpMul32F
+ OpMul64F
+ OpDiv32F
+ OpDiv64F
+ OpHmul32
+ OpHmul32u
+ OpHmul64
+ OpHmul64u
+ OpMul32uhilo
+ OpMul64uhilo
+ OpMul32uover
+ OpMul64uover
+ OpAvg32u
+ OpAvg64u
+ OpDiv8
+ OpDiv8u
+ OpDiv16
+ OpDiv16u
+ OpDiv32
+ OpDiv32u
+ OpDiv64
+ OpDiv64u
+ OpDiv128u
+ 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
+ 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
+ OpCondSelect
+ OpAndB
+ OpOrB
+ OpEqB
+ OpNeqB
+ OpNot
+ OpNeg8
+ OpNeg16
+ OpNeg32
+ OpNeg64
+ OpNeg32F
+ OpNeg64F
+ OpCom8
+ OpCom16
+ OpCom32
+ OpCom64
+ OpCtz8
+ OpCtz16
+ OpCtz32
+ OpCtz64
+ OpCtz8NonZero
+ OpCtz16NonZero
+ OpCtz32NonZero
+ OpCtz64NonZero
+ OpBitLen8
+ OpBitLen16
+ OpBitLen32
+ OpBitLen64
+ OpBswap32
+ OpBswap64
+ OpBitRev8
+ OpBitRev16
+ OpBitRev32
+ OpBitRev64
+ OpPopCount8
+ OpPopCount16
+ OpPopCount32
+ OpPopCount64
+ OpRotateLeft8
+ OpRotateLeft16
+ OpRotateLeft32
+ OpRotateLeft64
+ OpSqrt
+ OpFloor
+ OpCeil
+ OpTrunc
+ OpRound
+ OpRoundToEven
+ OpAbs
+ OpCopysign
+ OpFMA
+ OpPhi
+ OpCopy
+ OpConvert
+ OpConstBool
+ OpConstString
+ OpConstNil
+ OpConst8
+ OpConst16
+ OpConst32
+ OpConst64
+ OpConst32F
+ OpConst64F
+ OpConstInterface
+ OpConstSlice
+ OpInitMem
+ OpArg
+ OpAddr
+ OpLocalAddr
+ OpSP
+ OpSB
+ OpLoad
+ OpDereference
+ OpStore
+ OpMove
+ OpZero
+ OpStoreWB
+ OpMoveWB
+ OpZeroWB
+ OpWB
+ OpHasCPUFeature
+ OpPanicBounds
+ OpPanicExtend
+ OpClosureCall
+ OpStaticCall
+ OpInterCall
+ OpClosureLECall
+ OpStaticLECall
+ OpInterLECall
+ 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
+ OpCvtBoolToUint8
+ OpRound32F
+ OpRound64F
+ OpIsNonNil
+ OpIsInBounds
+ OpIsSliceInBounds
+ OpNilCheck
+ OpGetG
+ OpGetClosurePtr
+ OpGetCallerPC
+ OpGetCallerSP
+ OpPtrIndex
+ OpOffPtr
+ OpSliceMake
+ OpSlicePtr
+ OpSliceLen
+ OpSliceCap
+ OpComplexMake
+ OpComplexReal
+ OpComplexImag
+ OpStringMake
+ OpStringPtr
+ OpStringLen
+ OpIMake
+ OpITab
+ OpIData
+ OpStructMake0
+ OpStructMake1
+ OpStructMake2
+ OpStructMake3
+ OpStructMake4
+ OpStructSelect
+ OpArrayMake0
+ OpArrayMake1
+ OpArraySelect
+ OpStoreReg
+ OpLoadReg
+ OpFwdRef
+ OpUnknown
+ OpVarDef
+ OpVarKill
+ OpVarLive
+ OpKeepAlive
+ OpInlMark
+ OpInt64Make
+ OpInt64Hi
+ OpInt64Lo
+ OpAdd32carry
+ OpAdd32withcarry
+ OpSub32carry
+ OpSub32withcarry
+ OpAdd64carry
+ OpSub64borrow
+ OpSignmask
+ OpZeromask
+ OpSlicemask
+ OpSpectreIndex
+ OpSpectreSliceIndex
+ OpCvt32Uto32F
+ OpCvt32Uto64F
+ OpCvt32Fto32U
+ OpCvt64Fto32U
+ OpCvt64Uto32F
+ OpCvt64Uto64F
+ OpCvt32Fto64U
+ OpCvt64Fto64U
+ OpSelect0
+ OpSelect1
+ OpSelectN
+ OpSelectNAddr
+ OpMakeResult
+ OpAtomicLoad8
+ OpAtomicLoad32
+ OpAtomicLoad64
+ OpAtomicLoadPtr
+ OpAtomicLoadAcq32
+ OpAtomicLoadAcq64
+ OpAtomicStore8
+ OpAtomicStore32
+ OpAtomicStore64
+ OpAtomicStorePtrNoWB
+ OpAtomicStoreRel32
+ OpAtomicStoreRel64
+ OpAtomicExchange32
+ OpAtomicExchange64
+ OpAtomicAdd32
+ OpAtomicAdd64
+ OpAtomicCompareAndSwap32
+ OpAtomicCompareAndSwap64
+ OpAtomicCompareAndSwapRel32
+ OpAtomicAnd8
+ OpAtomicAnd32
+ OpAtomicOr8
+ OpAtomicOr32
+ OpAtomicAdd32Variant
+ OpAtomicAdd64Variant
+ OpAtomicExchange32Variant
+ OpAtomicExchange64Variant
+ OpAtomicCompareAndSwap32Variant
+ OpAtomicCompareAndSwap64Variant
+ OpAtomicAnd8Variant
+ OpAtomicAnd32Variant
+ OpAtomicOr8Variant
+ OpAtomicOr32Variant
+ OpClobber
+)
+
+var opcodeTable = [...]opInfo{
+ {name: "OpInvalid"},
+
+ {
+ name: "ADDSS",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ usesScratch: true,
+ asm: x86.AADDSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "ADDSD",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ asm: x86.AADDSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "SUBSS",
+ argLen: 2,
+ resultInArg0: true,
+ usesScratch: true,
+ asm: x86.ASUBSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "SUBSD",
+ argLen: 2,
+ resultInArg0: true,
+ asm: x86.ASUBSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MULSS",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ usesScratch: true,
+ asm: x86.AMULSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MULSD",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ asm: x86.AMULSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "DIVSS",
+ argLen: 2,
+ resultInArg0: true,
+ usesScratch: true,
+ asm: x86.ADIVSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "DIVSD",
+ argLen: 2,
+ resultInArg0: true,
+ asm: x86.ADIVSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MOVSSload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MOVSDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MOVSSconst",
+ auxType: auxFloat32,
+ argLen: 0,
+ rematerializeable: true,
+ asm: x86.AMOVSS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MOVSDconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: x86.AMOVSD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MOVSSloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MOVSSloadidx4",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MOVSDloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MOVSDloadidx8",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MOVSSstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVSDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVSSstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVSSstoreidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVSDstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVSDstoreidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ADDSSload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AADDSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "ADDSDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AADDSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "SUBSSload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "SUBSDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MULSSload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AMULSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MULSDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AMULSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "DIVSSload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "DIVSDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "ADDL",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 239}, // AX CX DX BX BP SI DI
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ADDLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ADDLcarry",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ADDLconstcarry",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ADCL",
+ argLen: 3,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AADCL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ADCLconst",
+ auxType: auxInt32,
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AADCL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SUBL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SUBLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SUBLcarry",
+ argLen: 2,
+ resultInArg0: true,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SUBLconstcarry",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SBBL",
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASBBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SBBLconst",
+ auxType: auxInt32,
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASBBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MULL",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AIMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MULLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.AIMUL3L,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MULLU",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: x86.AMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ },
+ clobbers: 4, // DX
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 1}, // AX
+ },
+ },
+ },
+ {
+ name: "HMULL",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: x86.AIMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "HMULLU",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: x86.AMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "MULLQU",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: x86.AMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ {1, 1}, // AX
+ },
+ },
+ },
+ {
+ name: "AVGLU",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "DIVL",
+ auxType: auxBool,
+ argLen: 2,
+ clobberFlags: true,
+ asm: x86.AIDIVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 251}, // AX CX BX SP BP SI DI
+ },
+ clobbers: 4, // DX
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ },
+ },
+ },
+ {
+ name: "DIVW",
+ auxType: auxBool,
+ argLen: 2,
+ clobberFlags: true,
+ asm: x86.AIDIVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 251}, // AX CX BX SP BP SI DI
+ },
+ clobbers: 4, // DX
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ },
+ },
+ },
+ {
+ name: "DIVLU",
+ argLen: 2,
+ clobberFlags: true,
+ asm: x86.ADIVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 251}, // AX CX BX SP BP SI DI
+ },
+ clobbers: 4, // DX
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ },
+ },
+ },
+ {
+ name: "DIVWU",
+ argLen: 2,
+ clobberFlags: true,
+ asm: x86.ADIVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 251}, // AX CX BX SP BP SI DI
+ },
+ clobbers: 4, // DX
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ },
+ },
+ },
+ {
+ name: "MODL",
+ auxType: auxBool,
+ argLen: 2,
+ clobberFlags: true,
+ asm: x86.AIDIVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 251}, // AX CX BX SP BP SI DI
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "MODW",
+ auxType: auxBool,
+ argLen: 2,
+ clobberFlags: true,
+ asm: x86.AIDIVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 251}, // AX CX BX SP BP SI DI
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "MODLU",
+ argLen: 2,
+ clobberFlags: true,
+ asm: x86.ADIVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 251}, // AX CX BX SP BP SI DI
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "MODWU",
+ argLen: 2,
+ clobberFlags: true,
+ asm: x86.ADIVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 251}, // AX CX BX SP BP SI DI
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "ANDL",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ANDLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ORL",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ORLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "XORL",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "XORLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "CMPL",
+ argLen: 2,
+ asm: x86.ACMPL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "CMPW",
+ argLen: 2,
+ asm: x86.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "CMPB",
+ argLen: 2,
+ asm: x86.ACMPB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "CMPLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: x86.ACMPL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "CMPWconst",
+ auxType: auxInt16,
+ argLen: 1,
+ asm: x86.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "CMPBconst",
+ auxType: auxInt8,
+ argLen: 1,
+ asm: x86.ACMPB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "CMPLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "CMPWload",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "CMPBload",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "CMPLconstload",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "CMPWconstload",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "CMPBconstload",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "UCOMISS",
+ argLen: 2,
+ usesScratch: true,
+ asm: x86.AUCOMISS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "UCOMISD",
+ argLen: 2,
+ usesScratch: true,
+ asm: x86.AUCOMISD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "TESTL",
+ argLen: 2,
+ commutative: true,
+ asm: x86.ATESTL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "TESTW",
+ argLen: 2,
+ commutative: true,
+ asm: x86.ATESTW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "TESTB",
+ argLen: 2,
+ commutative: true,
+ asm: x86.ATESTB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "TESTLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: x86.ATESTL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "TESTWconst",
+ auxType: auxInt16,
+ argLen: 1,
+ asm: x86.ATESTW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "TESTBconst",
+ auxType: auxInt8,
+ argLen: 1,
+ asm: x86.ATESTB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "SHLL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SHLLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SHRL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SHRW",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SHRB",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SHRLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SHRWconst",
+ auxType: auxInt16,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SHRBconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SARL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SARW",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SARB",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SARLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SARWconst",
+ auxType: auxInt16,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SARBconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ROLLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ROLWconst",
+ auxType: auxInt16,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ROLBconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ADDLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SUBLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MULLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AIMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ANDLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ORLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "XORLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ADDLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SUBLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MULLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AIMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ANDLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "ORLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "XORLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {1, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "NEGL",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ANEGL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "NOTL",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ANOTL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "BSFL",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.ABSFL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "BSFW",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.ABSFW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "BSRL",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.ABSRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "BSRW",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.ABSRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "BSWAPL",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABSWAPL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SQRTSD",
+ argLen: 1,
+ asm: x86.ASQRTSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "SBBLcarrymask",
+ argLen: 1,
+ asm: x86.ASBBL,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETEQ",
+ argLen: 1,
+ asm: x86.ASETEQ,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETNE",
+ argLen: 1,
+ asm: x86.ASETNE,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETL",
+ argLen: 1,
+ asm: x86.ASETLT,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETLE",
+ argLen: 1,
+ asm: x86.ASETLE,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETG",
+ argLen: 1,
+ asm: x86.ASETGT,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETGE",
+ argLen: 1,
+ asm: x86.ASETGE,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETB",
+ argLen: 1,
+ asm: x86.ASETCS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETBE",
+ argLen: 1,
+ asm: x86.ASETLS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETA",
+ argLen: 1,
+ asm: x86.ASETHI,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETAE",
+ argLen: 1,
+ asm: x86.ASETCC,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETO",
+ argLen: 1,
+ asm: x86.ASETOS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETEQF",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.ASETEQ,
+ reg: regInfo{
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 238}, // CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETNEF",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.ASETNE,
+ reg: regInfo{
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 238}, // CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETORD",
+ argLen: 1,
+ asm: x86.ASETPC,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETNAN",
+ argLen: 1,
+ asm: x86.ASETPS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETGF",
+ argLen: 1,
+ asm: x86.ASETHI,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "SETGEF",
+ argLen: 1,
+ asm: x86.ASETCC,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVBLSX",
+ argLen: 1,
+ asm: x86.AMOVBLSX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVBLZX",
+ argLen: 1,
+ asm: x86.AMOVBLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVWLSX",
+ argLen: 1,
+ asm: x86.AMOVWLSX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVWLZX",
+ argLen: 1,
+ asm: x86.AMOVWLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVLconst",
+ auxType: auxInt32,
+ argLen: 0,
+ rematerializeable: true,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "CVTTSD2SL",
+ argLen: 1,
+ usesScratch: true,
+ asm: x86.ACVTTSD2SL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "CVTTSS2SL",
+ argLen: 1,
+ usesScratch: true,
+ asm: x86.ACVTTSS2SL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "CVTSL2SS",
+ argLen: 1,
+ usesScratch: true,
+ asm: x86.ACVTSL2SS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "CVTSL2SD",
+ argLen: 1,
+ usesScratch: true,
+ asm: x86.ACVTSL2SD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "CVTSD2SS",
+ argLen: 1,
+ usesScratch: true,
+ asm: x86.ACVTSD2SS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "CVTSS2SD",
+ argLen: 1,
+ asm: x86.ACVTSS2SD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "PXOR",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ asm: x86.APXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "LEAL",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymAddr,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "LEAL1",
+ auxType: auxSymOff,
+ argLen: 2,
+ commutative: true,
+ symEffect: SymAddr,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "LEAL2",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "LEAL4",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "LEAL8",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVBload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVBLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVBLSXload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVBLSX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVWload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVWLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVWLSXload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVWLSX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVLload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVBstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVWstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVLstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ADDLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "SUBLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ANDLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ORLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "XORLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ADDLmodifyidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "SUBLmodifyidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ANDLmodifyidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ORLmodifyidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "XORLmodifyidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ADDLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ANDLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ORLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "XORLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ADDLconstmodifyidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ANDLconstmodifyidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "ORLconstmodifyidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "XORLconstmodifyidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVBloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.AMOVBLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVWloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.AMOVWLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVWloadidx2",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVWLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVLloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVLloadidx4",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVBstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreidx2",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVLstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVLstoreidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {2, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVBstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVLstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVBstoreconstidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymWrite,
+ asm: x86.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreconstidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymWrite,
+ asm: x86.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreconstidx2",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymWrite,
+ asm: x86.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVLstoreconstidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "MOVLstoreconstidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 255}, // AX CX DX BX SP BP SI DI
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "DUFFZERO",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 128}, // DI
+ {1, 1}, // AX
+ },
+ clobbers: 130, // CX DI
+ },
+ },
+ {
+ name: "REPSTOSL",
+ argLen: 4,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 128}, // DI
+ {1, 2}, // CX
+ {2, 1}, // AX
+ },
+ clobbers: 130, // CX DI
+ },
+ },
+ {
+ name: "CALLstatic",
+ auxType: auxCallOff,
+ argLen: 1,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ {
+ name: "CALLclosure",
+ auxType: auxCallOff,
+ argLen: 3,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 4}, // DX
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ },
+ clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ {
+ name: "CALLinter",
+ auxType: auxCallOff,
+ argLen: 2,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ {
+ name: "DUFFCOPY",
+ auxType: auxInt64,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 128}, // DI
+ {1, 64}, // SI
+ },
+ clobbers: 194, // CX SI DI
+ },
+ },
+ {
+ name: "REPMOVSL",
+ argLen: 4,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 128}, // DI
+ {1, 64}, // SI
+ {2, 2}, // CX
+ },
+ clobbers: 194, // CX SI DI
+ },
+ },
+ {
+ name: "InvertFlags",
+ argLen: 1,
+ reg: regInfo{},
+ },
+ {
+ name: "LoweredGetG",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "LoweredGetClosurePtr",
+ argLen: 0,
+ zeroWidth: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerPC",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerSP",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "LoweredNilCheck",
+ argLen: 2,
+ clobberFlags: true,
+ nilCheck: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 255}, // AX CX DX BX SP BP SI DI
+ },
+ },
+ },
+ {
+ name: "LoweredWB",
+ auxType: auxSym,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymNone,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 128}, // DI
+ {1, 1}, // AX
+ },
+ clobbers: 65280, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ {
+ name: "LoweredPanicBoundsA",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // DX
+ {1, 8}, // BX
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsB",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // CX
+ {1, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsC",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 2}, // CX
+ },
+ },
+ },
+ {
+ name: "LoweredPanicExtendA",
+ auxType: auxInt64,
+ argLen: 4,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 64}, // SI
+ {1, 4}, // DX
+ {2, 8}, // BX
+ },
+ },
+ },
+ {
+ name: "LoweredPanicExtendB",
+ auxType: auxInt64,
+ argLen: 4,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 64}, // SI
+ {1, 2}, // CX
+ {2, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "LoweredPanicExtendC",
+ auxType: auxInt64,
+ argLen: 4,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 64}, // SI
+ {1, 1}, // AX
+ {2, 2}, // CX
+ },
+ },
+ },
+ {
+ name: "FlagEQ",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagLT_ULT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagLT_UGT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagGT_UGT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagGT_ULT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "MOVSSconst1",
+ auxType: auxFloat32,
+ argLen: 0,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVSDconst1",
+ auxType: auxFloat64,
+ argLen: 0,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ },
+ },
+ {
+ name: "MOVSSconst2",
+ argLen: 1,
+ asm: x86.AMOVSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+ {
+ name: "MOVSDconst2",
+ argLen: 1,
+ asm: x86.AMOVSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 239}, // AX CX DX BX BP SI DI
+ },
+ outputs: []outputInfo{
+ {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
+ },
+ },
+ },
+
+ {
+ name: "ADDSS",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDSD",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSS",
+ argLen: 2,
+ resultInArg0: true,
+ asm: x86.ASUBSS,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSD",
+ argLen: 2,
+ resultInArg0: true,
+ asm: x86.ASUBSD,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSS",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSD",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSS",
+ argLen: 2,
+ resultInArg0: true,
+ asm: x86.ADIVSS,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSD",
+ argLen: 2,
+ resultInArg0: true,
+ asm: x86.ADIVSD,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVSSload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVSDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVSSconst",
+ auxType: auxFloat32,
+ argLen: 0,
+ rematerializeable: true,
+ asm: x86.AMOVSS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVSDconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: x86.AMOVSD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVSSloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVSS,
+ scale: 1,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVSSloadidx4",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVSS,
+ scale: 4,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVSDloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVSD,
+ scale: 1,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVSDloadidx8",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVSD,
+ scale: 8,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVSSstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ 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",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ 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: "MOVSSstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVSS,
+ scale: 1,
+ 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: "MOVSSstoreidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVSS,
+ scale: 4,
+ 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: "MOVSDstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVSD,
+ scale: 1,
+ 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",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVSD,
+ scale: 8,
+ 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: "ADDSSload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ 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, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDSDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ 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, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSSload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSSload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ 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, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ 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, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSSload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDSSloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AADDSS,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDSSloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AADDSS,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDSDloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AADDSD,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDSDloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AADDSD,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSSloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSS,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSSloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSS,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSDloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSD,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSDloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSD,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSSloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMULSS,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSSloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMULSS,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSDloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMULSD,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSDloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMULSD,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSSloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSS,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSSloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSS,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSDloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSD,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSDloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSD,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDQ",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: x86.AADDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {0, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDL",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {0, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDQconst",
+ auxType: auxInt32,
+ argLen: 1,
+ clobberFlags: true,
+ 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
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ clobberFlags: true,
+ 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
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDQconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "ADDLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SUBQ",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASUBQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBQconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASUBQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MULQ",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AIMULQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MULL",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AIMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MULQconst",
+ auxType: auxInt32,
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.AIMUL3Q,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MULLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.AIMUL3L,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MULLU",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ 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: 4, // DX
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 1}, // AX
+ },
+ },
+ },
+ {
+ name: "MULQU",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: x86.AMULQ,
+ 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: 4, // DX
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 1}, // AX
+ },
+ },
+ },
+ {
+ name: "HMULQ",
+ argLen: 2,
+ clobberFlags: true,
+ asm: x86.AIMULQ,
+ 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: 1, // AX
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "HMULL",
+ argLen: 2,
+ clobberFlags: true,
+ 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: 1, // AX
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "HMULQU",
+ argLen: 2,
+ clobberFlags: true,
+ asm: x86.AMULQ,
+ 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: 1, // AX
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "HMULLU",
+ argLen: 2,
+ clobberFlags: true,
+ 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: 1, // AX
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "AVGQU",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "DIVQ",
+ auxType: auxBool,
+ argLen: 2,
+ clobberFlags: true,
+ 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
+ },
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ {1, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "DIVL",
+ auxType: auxBool,
+ argLen: 2,
+ clobberFlags: true,
+ 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
+ },
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ {1, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "DIVW",
+ auxType: auxBool,
+ argLen: 2,
+ clobberFlags: true,
+ 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
+ },
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ {1, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "DIVQU",
+ argLen: 2,
+ clobberFlags: true,
+ 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
+ },
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ {1, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "DIVLU",
+ argLen: 2,
+ clobberFlags: true,
+ 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
+ },
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ {1, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "DIVWU",
+ argLen: 2,
+ clobberFlags: true,
+ 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
+ },
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ {1, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "NEGLflags",
+ argLen: 1,
+ resultInArg0: true,
+ asm: x86.ANEGL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDQcarry",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ asm: x86.AADDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADCQ",
+ argLen: 3,
+ commutative: true,
+ resultInArg0: true,
+ asm: x86.AADCQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDQconstcarry",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ asm: x86.AADDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADCQconst",
+ auxType: auxInt32,
+ argLen: 2,
+ resultInArg0: true,
+ asm: x86.AADCQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBQborrow",
+ argLen: 2,
+ resultInArg0: true,
+ asm: x86.ASUBQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SBBQ",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ASBBQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBQconstborrow",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ asm: x86.ASUBQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SBBQconst",
+ auxType: auxInt32,
+ argLen: 2,
+ resultInArg0: true,
+ asm: x86.ASBBQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MULQU2",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: x86.AMULQ,
+ 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
+ },
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ {1, 1}, // AX
+ },
+ },
+ },
+ {
+ name: "DIVQU2",
+ argLen: 3,
+ clobberFlags: true,
+ asm: x86.ADIVQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // DX
+ {1, 1}, // AX
+ {2, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 1}, // AX
+ {1, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "ANDQ",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AANDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDL",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDQconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AANDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDQconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "ANDLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "ORQ",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AORQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORL",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORQconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AORQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORQconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "ORLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "XORQ",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AXORQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORL",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORQconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AXORQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORQconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "XORLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "CMPQ",
+ argLen: 2,
+ 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
+ },
+ },
+ },
+ {
+ name: "CMPL",
+ argLen: 2,
+ 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
+ },
+ },
+ },
+ {
+ name: "CMPW",
+ argLen: 2,
+ 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
+ },
+ },
+ },
+ {
+ name: "CMPB",
+ argLen: 2,
+ 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
+ },
+ },
+ },
+ {
+ name: "CMPQconst",
+ auxType: auxInt32,
+ argLen: 1,
+ 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
+ },
+ },
+ },
+ {
+ name: "CMPLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ 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
+ },
+ },
+ },
+ {
+ name: "CMPWconst",
+ auxType: auxInt16,
+ argLen: 1,
+ 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
+ },
+ },
+ },
+ {
+ name: "CMPBconst",
+ auxType: auxInt8,
+ argLen: 1,
+ 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
+ },
+ },
+ },
+ {
+ name: "CMPQload",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPQ,
+ 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: "CMPLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPL,
+ 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: "CMPWload",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPW,
+ 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: "CMPBload",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPB,
+ 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: "CMPQconstload",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "CMPLconstload",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "CMPWconstload",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "CMPBconstload",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "CMPQloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymRead,
+ asm: x86.ACMPQ,
+ scale: 8,
+ 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: "CMPQloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.ACMPQ,
+ scale: 1,
+ 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: "CMPLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymRead,
+ asm: x86.ACMPL,
+ scale: 4,
+ 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: "CMPLloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.ACMPL,
+ scale: 1,
+ 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: "CMPWloadidx2",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymRead,
+ asm: x86.ACMPW,
+ scale: 2,
+ 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: "CMPWloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.ACMPW,
+ scale: 1,
+ 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: "CMPBloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.ACMPB,
+ scale: 1,
+ 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: "CMPQconstloadidx8",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.ACMPQ,
+ scale: 8,
+ 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: "CMPQconstloadidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.ACMPQ,
+ scale: 1,
+ 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: "CMPLconstloadidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.ACMPL,
+ scale: 4,
+ 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: "CMPLconstloadidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.ACMPL,
+ scale: 1,
+ 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: "CMPWconstloadidx2",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.ACMPW,
+ scale: 2,
+ 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: "CMPWconstloadidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.ACMPW,
+ scale: 1,
+ 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: "CMPBconstloadidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.ACMPB,
+ scale: 1,
+ 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: "UCOMISS",
+ argLen: 2,
+ 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
+ },
+ },
+ },
+ {
+ name: "UCOMISD",
+ argLen: 2,
+ 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
+ },
+ },
+ },
+ {
+ name: "BTL",
+ argLen: 2,
+ asm: x86.ABTL,
+ 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
+ },
+ },
+ },
+ {
+ name: "BTQ",
+ argLen: 2,
+ asm: x86.ABTQ,
+ 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
+ },
+ },
+ },
+ {
+ name: "BTCL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTCL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTCQ",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTCQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTRL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTRQ",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTRQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTSL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTSL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTSQ",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTSQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTLconst",
+ auxType: auxInt8,
+ argLen: 1,
+ asm: x86.ABTL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTQconst",
+ auxType: auxInt8,
+ argLen: 1,
+ asm: x86.ABTQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTCLconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTCL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTCQconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTCQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTRLconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTRQconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTRQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTSLconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTSL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTSQconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABTSQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BTCQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTCQ,
+ 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: "BTCLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTCL,
+ 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: "BTSQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTSQ,
+ 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: "BTSLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTSL,
+ 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: "BTRQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTRQ,
+ 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: "BTRLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTRL,
+ 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: "BTCQconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTCQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTCLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTCL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTSQconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTSQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTSLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTSL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTRQconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTRQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTRLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "TESTQ",
+ argLen: 2,
+ commutative: true,
+ 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
+ },
+ },
+ },
+ {
+ name: "TESTL",
+ argLen: 2,
+ commutative: true,
+ 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
+ },
+ },
+ },
+ {
+ name: "TESTW",
+ argLen: 2,
+ commutative: true,
+ 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
+ },
+ },
+ },
+ {
+ name: "TESTB",
+ argLen: 2,
+ commutative: true,
+ 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
+ },
+ },
+ },
+ {
+ name: "TESTQconst",
+ auxType: auxInt32,
+ argLen: 1,
+ 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
+ },
+ },
+ },
+ {
+ name: "TESTLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ 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
+ },
+ },
+ },
+ {
+ name: "TESTWconst",
+ auxType: auxInt16,
+ argLen: 1,
+ 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
+ },
+ },
+ },
+ {
+ name: "TESTBconst",
+ auxType: auxInt8,
+ argLen: 1,
+ 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
+ },
+ },
+ },
+ {
+ name: "SHLQ",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHLQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHLL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHLQconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHLQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHLLconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHRQ",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHRL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHRW",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHRB",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHRQconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHRLconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHRWconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SHRBconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASHRB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SARQ",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SARL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SARW",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SARB",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SARQconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SARLconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SARWconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SARBconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ASARB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ROLQ",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ROLL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ROLW",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ROLB",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "RORQ",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ARORQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "RORL",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ARORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "RORW",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ARORW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "RORB",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ARORB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // CX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ROLQconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ROLLconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ROLWconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ROLBconst",
+ auxType: auxInt8,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.AROLB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDQload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AADDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBQload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ASUBQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.ASUBL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AANDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDQload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AANDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORQload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AORQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORQload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AXORQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: x86.AXORL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDLloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AADDL,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AADDL,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDLloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AADDL,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDQloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AADDQ,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDQloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AADDQ,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBLloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.ASUBL,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.ASUBL,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBLloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.ASUBL,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBQloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.ASUBQ,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SUBQloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.ASUBQ,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDLloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AANDL,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AANDL,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDLloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AANDL,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDQloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AANDQ,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDQloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AANDQ,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORLloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AORL,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AORL,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORLloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AORL,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORQloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AORQ,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ORQloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AORQ,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORLloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AXORL,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORLloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AXORL,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORLloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AXORL,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORQloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AXORQ,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XORQloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ clobberFlags: true,
+ symEffect: SymRead,
+ asm: x86.AXORQ,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX 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
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ADDQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDQ,
+ 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: "SUBQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ASUBQ,
+ 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: "ANDQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDQ,
+ 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: "ORQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORQ,
+ 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: "XORQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORQ,
+ 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: "ADDLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ 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: "SUBLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ASUBL,
+ 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: "ANDLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ 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: "ORLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ 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: "XORLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ 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: "ADDQmodifyidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDQ,
+ scale: 1,
+ 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: "ADDQmodifyidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDQ,
+ scale: 8,
+ 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: "SUBQmodifyidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ASUBQ,
+ scale: 1,
+ 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: "SUBQmodifyidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ASUBQ,
+ scale: 8,
+ 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: "ANDQmodifyidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDQ,
+ scale: 1,
+ 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: "ANDQmodifyidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDQ,
+ scale: 8,
+ 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: "ORQmodifyidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORQ,
+ scale: 1,
+ 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: "ORQmodifyidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORQ,
+ scale: 8,
+ 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: "XORQmodifyidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORQ,
+ scale: 1,
+ 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: "XORQmodifyidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORQ,
+ scale: 8,
+ 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: "ADDLmodifyidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ scale: 1,
+ 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: "ADDLmodifyidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ scale: 4,
+ 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: "ADDLmodifyidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ scale: 8,
+ 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: "SUBLmodifyidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ASUBL,
+ scale: 1,
+ 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: "SUBLmodifyidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ASUBL,
+ scale: 4,
+ 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: "SUBLmodifyidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ASUBL,
+ scale: 8,
+ 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: "ANDLmodifyidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ scale: 1,
+ 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: "ANDLmodifyidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ scale: 4,
+ 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: "ANDLmodifyidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ scale: 8,
+ 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: "ORLmodifyidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ scale: 1,
+ 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: "ORLmodifyidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ scale: 4,
+ 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: "ORLmodifyidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ scale: 8,
+ 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: "XORLmodifyidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ scale: 1,
+ 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: "XORLmodifyidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ scale: 4,
+ 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: "XORLmodifyidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ scale: 8,
+ 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: "ADDQconstmodifyidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDQ,
+ scale: 1,
+ 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: "ADDQconstmodifyidx8",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDQ,
+ scale: 8,
+ 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: "ANDQconstmodifyidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDQ,
+ scale: 1,
+ 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: "ANDQconstmodifyidx8",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDQ,
+ scale: 8,
+ 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: "ORQconstmodifyidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORQ,
+ scale: 1,
+ 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: "ORQconstmodifyidx8",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORQ,
+ scale: 8,
+ 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: "XORQconstmodifyidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORQ,
+ scale: 1,
+ 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: "XORQconstmodifyidx8",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORQ,
+ scale: 8,
+ 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: "ADDLconstmodifyidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ scale: 1,
+ 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: "ADDLconstmodifyidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ scale: 4,
+ 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: "ADDLconstmodifyidx8",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AADDL,
+ scale: 8,
+ 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: "ANDLconstmodifyidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ scale: 1,
+ 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: "ANDLconstmodifyidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ scale: 4,
+ 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: "ANDLconstmodifyidx8",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AANDL,
+ scale: 8,
+ 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: "ORLconstmodifyidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ scale: 1,
+ 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: "ORLconstmodifyidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ scale: 4,
+ 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: "ORLconstmodifyidx8",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AORL,
+ scale: 8,
+ 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: "XORLconstmodifyidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ scale: 1,
+ 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: "XORLconstmodifyidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ scale: 4,
+ 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: "XORLconstmodifyidx8",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.AXORL,
+ scale: 8,
+ 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: "NEGQ",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ANEGQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "NEGL",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ANEGL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "NOTQ",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ANOTQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "NOTL",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ANOTL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BSFQ",
+ argLen: 1,
+ asm: x86.ABSFQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BSFL",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.ABSFL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BSRQ",
+ argLen: 1,
+ asm: x86.ABSRQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BSRL",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.ABSRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQEQ",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQNE",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQNE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQLT",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQLT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQGT",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQGT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQLE",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQLE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQGE",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQGE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQLS",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQLS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQHI",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQHI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQCC",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQCS",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQCS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLEQ",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLNE",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLNE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLLT",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLLT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLGT",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLGT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLLE",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLLE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLGE",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLGE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLLS",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLLS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLHI",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLHI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLCC",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLCS",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLCS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWEQ",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWNE",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWNE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWLT",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWLT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWGT",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWGT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWLE",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWLE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWGE",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWGE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWLS",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWLS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWHI",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWHI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWCC",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWCS",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWCS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQEQF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQNE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQNEF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQNE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQGTF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQHI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVQGEF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVQCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLEQF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLNE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLNEF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLNE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLGTF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLHI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVLGEF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVLCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWEQF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWNE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWNEF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWNE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWGTF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWHI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMOVWGEF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.ACMOVWCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BSWAPQ",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABSWAPQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "BSWAPL",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: x86.ABSWAPL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "POPCNTQ",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.APOPCNTQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "POPCNTL",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.APOPCNTL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SQRTSD",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ROUNDSD",
+ auxType: auxInt8,
+ argLen: 1,
+ asm: x86.AROUNDSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "VFMADD231SD",
+ argLen: 3,
+ resultInArg0: true,
+ asm: x86.AVFMADD231SD,
+ 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
+ {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SBBQcarrymask",
+ argLen: 1,
+ asm: x86.ASBBQ,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SBBLcarrymask",
+ argLen: 1,
+ asm: x86.ASBBL,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETEQ",
+ argLen: 1,
+ asm: x86.ASETEQ,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETNE",
+ argLen: 1,
+ asm: x86.ASETNE,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETL",
+ argLen: 1,
+ asm: x86.ASETLT,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETLE",
+ argLen: 1,
+ asm: x86.ASETLE,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETG",
+ argLen: 1,
+ asm: x86.ASETGT,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETGE",
+ argLen: 1,
+ asm: x86.ASETGE,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETB",
+ argLen: 1,
+ asm: x86.ASETCS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETBE",
+ argLen: 1,
+ asm: x86.ASETLS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETA",
+ argLen: 1,
+ asm: x86.ASETHI,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETAE",
+ argLen: 1,
+ asm: x86.ASETCC,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETO",
+ argLen: 1,
+ asm: x86.ASETOS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETEQstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.ASETEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SETNEstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.ASETNE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SETLstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.ASETLT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SETLEstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.ASETLE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SETGstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.ASETGT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SETGEstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.ASETGE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SETBstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.ASETCS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SETBEstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.ASETLS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SETAstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.ASETHI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SETAEstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.ASETCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "SETEQF",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.ASETEQ,
+ reg: regInfo{
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETNEF",
+ argLen: 1,
+ clobberFlags: true,
+ asm: x86.ASETNE,
+ reg: regInfo{
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETORD",
+ argLen: 1,
+ asm: x86.ASETPC,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETNAN",
+ argLen: 1,
+ asm: x86.ASETPS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETGF",
+ argLen: 1,
+ asm: x86.ASETHI,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "SETGEF",
+ argLen: 1,
+ asm: x86.ASETCC,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVBQSX",
+ argLen: 1,
+ asm: x86.AMOVBQSX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVBQZX",
+ argLen: 1,
+ asm: x86.AMOVBLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVWQSX",
+ argLen: 1,
+ asm: x86.AMOVWQSX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVWQZX",
+ argLen: 1,
+ asm: x86.AMOVWLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVLQSX",
+ argLen: 1,
+ asm: x86.AMOVLQSX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVLQZX",
+ argLen: 1,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVLconst",
+ auxType: auxInt32,
+ argLen: 0,
+ rematerializeable: true,
+ asm: x86.AMOVL,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVQconst",
+ auxType: auxInt64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: x86.AMOVQ,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CVTTSD2SL",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CVTTSD2SQ",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CVTTSS2SL",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CVTTSS2SQ",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CVTSL2SS",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "CVTSL2SD",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "CVTSQ2SS",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "CVTSQ2SD",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "CVTSD2SS",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "CVTSS2SD",
+ argLen: 1,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVQi2f",
+ argLen: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVQf2i",
+ argLen: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVLi2f",
+ argLen: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVLf2i",
+ argLen: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "PXOR",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ 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: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "LEAQ",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymAddr,
+ asm: x86.ALEAQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAL",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymAddr,
+ asm: x86.ALEAL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAW",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymAddr,
+ asm: x86.ALEAW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAQ1",
+ auxType: auxSymOff,
+ argLen: 2,
+ commutative: true,
+ symEffect: SymAddr,
+ asm: x86.ALEAQ,
+ scale: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAL1",
+ auxType: auxSymOff,
+ argLen: 2,
+ commutative: true,
+ symEffect: SymAddr,
+ asm: x86.ALEAL,
+ scale: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAW1",
+ auxType: auxSymOff,
+ argLen: 2,
+ commutative: true,
+ symEffect: SymAddr,
+ asm: x86.ALEAW,
+ scale: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAQ2",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ asm: x86.ALEAQ,
+ scale: 2,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAL2",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ asm: x86.ALEAL,
+ scale: 2,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAW2",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ asm: x86.ALEAW,
+ scale: 2,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAQ4",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ asm: x86.ALEAQ,
+ scale: 4,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAL4",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ asm: x86.ALEAL,
+ scale: 4,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAW4",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ asm: x86.ALEAW,
+ scale: 4,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAQ8",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ asm: x86.ALEAQ,
+ scale: 8,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAL8",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ asm: x86.ALEAL,
+ scale: 8,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LEAW8",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymAddr,
+ asm: x86.ALEAW,
+ scale: 8,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVBload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVBLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVBQSXload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVWload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVWLZX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVWQSXload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVWQSX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVLload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVLQSXload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVLQSX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVQload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVBstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ 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",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ 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",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ 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",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ 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: "MOVOload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMOVUPS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MOVOstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVUPS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "MOVBloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.AMOVBLZX,
+ scale: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVWloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.AMOVWLZX,
+ scale: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVWloadidx2",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVWLZX,
+ scale: 2,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVLloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.AMOVL,
+ scale: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVLloadidx4",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVL,
+ scale: 4,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVLloadidx8",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVL,
+ scale: 8,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVQloadidx1",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: x86.AMOVQ,
+ scale: 1,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVQloadidx8",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: x86.AMOVQ,
+ scale: 8,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVBstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVB,
+ scale: 1,
+ 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: "MOVWstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVW,
+ scale: 1,
+ 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: "MOVWstoreidx2",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVW,
+ scale: 2,
+ 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: "MOVLstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ scale: 1,
+ 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: "MOVLstoreidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ scale: 4,
+ 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: "MOVLstoreidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ scale: 8,
+ 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: "MOVQstoreidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVQ,
+ scale: 1,
+ 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: "MOVQstoreidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: x86.AMOVQ,
+ scale: 8,
+ 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: "MOVBstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ 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
+ },
+ },
+ },
+ {
+ name: "MOVWstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ 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
+ },
+ },
+ },
+ {
+ name: "MOVLstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ 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
+ },
+ },
+ },
+ {
+ name: "MOVQstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ 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
+ },
+ },
+ },
+ {
+ name: "MOVBstoreconstidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVB,
+ scale: 1,
+ 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: "MOVWstoreconstidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVW,
+ scale: 1,
+ 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: "MOVWstoreconstidx2",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymWrite,
+ asm: x86.AMOVW,
+ scale: 2,
+ 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: "MOVLstoreconstidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ scale: 1,
+ 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: "MOVLstoreconstidx4",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymWrite,
+ asm: x86.AMOVL,
+ scale: 4,
+ 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: "MOVQstoreconstidx1",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: x86.AMOVQ,
+ scale: 1,
+ 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: "MOVQstoreconstidx8",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ symEffect: SymWrite,
+ asm: x86.AMOVQ,
+ scale: 8,
+ 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: "DUFFZERO",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 128}, // DI
+ {1, 65536}, // X0
+ },
+ clobbers: 128, // DI
+ },
+ },
+ {
+ name: "MOVOconst",
+ auxType: auxInt128,
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "REPSTOSQ",
+ argLen: 4,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 128}, // DI
+ {1, 2}, // CX
+ {2, 1}, // AX
+ },
+ clobbers: 130, // CX DI
+ },
+ },
+ {
+ name: "CALLstatic",
+ auxType: auxCallOff,
+ argLen: 1,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ clobbers: 4294967279, // 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
+ },
+ },
+ {
+ name: "CALLclosure",
+ auxType: auxCallOff,
+ argLen: 3,
+ clobberFlags: true,
+ call: true,
+ 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: 4294967279, // 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
+ },
+ },
+ {
+ name: "CALLinter",
+ auxType: auxCallOff,
+ argLen: 2,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ clobbers: 4294967279, // 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
+ },
+ },
+ {
+ name: "DUFFCOPY",
+ auxType: auxInt64,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 128}, // DI
+ {1, 64}, // SI
+ },
+ clobbers: 65728, // SI DI X0
+ },
+ },
+ {
+ name: "REPMOVSQ",
+ argLen: 4,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 128}, // DI
+ {1, 64}, // SI
+ {2, 2}, // CX
+ },
+ clobbers: 194, // CX SI DI
+ },
+ },
+ {
+ name: "InvertFlags",
+ argLen: 1,
+ reg: regInfo{},
+ },
+ {
+ name: "LoweredGetG",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredGetClosurePtr",
+ argLen: 0,
+ zeroWidth: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerPC",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerSP",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredNilCheck",
+ argLen: 2,
+ clobberFlags: true,
+ nilCheck: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredWB",
+ auxType: auxSym,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymNone,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 128}, // DI
+ {1, 879}, // AX CX DX BX BP SI R8 R9
+ },
+ clobbers: 4294901760, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ {
+ name: "LoweredHasCPUFeature",
+ auxType: auxSym,
+ argLen: 0,
+ rematerializeable: true,
+ symEffect: SymNone,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsA",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // DX
+ {1, 8}, // BX
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsB",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // CX
+ {1, 4}, // DX
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsC",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // AX
+ {1, 2}, // CX
+ },
+ },
+ },
+ {
+ name: "FlagEQ",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagLT_ULT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagLT_UGT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagGT_UGT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagGT_ULT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "MOVBatomicload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVLatomicload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "MOVQatomicload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ 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: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XCHGB",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.AXCHGB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XCHGL",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.AXCHGL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XCHGQ",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ faultOnNilArg1: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.AXCHGQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XADDLlock",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.AXADDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "XADDQlock",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.AXADDQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "AddTupleFirst32",
+ argLen: 2,
+ reg: regInfo{},
+ },
+ {
+ name: "AddTupleFirst64",
+ argLen: 2,
+ reg: regInfo{},
+ },
+ {
+ name: "CMPXCHGLlock",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.ACMPXCHGL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1}, // AX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {2, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "CMPXCHGQlock",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.ACMPXCHGQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1}, // AX
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {2, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ clobbers: 1, // AX
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "ANDBlock",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.AANDB,
+ 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: "ANDLlock",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.AANDL,
+ 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: "ORBlock",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.AORB,
+ 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: "ORLlock",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: x86.AORL,
+ 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: "ADD",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 30719}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUB",
+ argLen: 2,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSB",
+ argLen: 2,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MUL",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AMUL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "HMUL",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "HMULU",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AMULLU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "CALLudiv",
+ argLen: 2,
+ clobberFlags: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 1}, // R0
+ },
+ clobbers: 16396, // R2 R3 R14
+ outputs: []outputInfo{
+ {0, 1}, // R0
+ {1, 2}, // R1
+ },
+ },
+ },
+ {
+ name: "ADDS",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDSconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADC",
+ argLen: 3,
+ commutative: true,
+ asm: arm.AADC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADCconst",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AADC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBS",
+ argLen: 2,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBSconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBSconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SBC",
+ argLen: 3,
+ asm: arm.ASBC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SBCconst",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ASBC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSCconst",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ARSC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULLU",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AMULLU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULA",
+ argLen: 3,
+ asm: arm.AMULA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULS",
+ argLen: 3,
+ asm: arm.AMULS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDF",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AADDF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "ADDD",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AADDD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "SUBF",
+ argLen: 2,
+ asm: arm.ASUBF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "SUBD",
+ argLen: 2,
+ asm: arm.ASUBD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MULF",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AMULF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MULD",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AMULD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "NMULF",
+ argLen: 2,
+ commutative: true,
+ asm: arm.ANMULF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "NMULD",
+ argLen: 2,
+ commutative: true,
+ asm: arm.ANMULD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "DIVF",
+ argLen: 2,
+ asm: arm.ADIVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "DIVD",
+ argLen: 2,
+ asm: arm.ADIVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MULAF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: arm.AMULAF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MULAD",
+ argLen: 3,
+ resultInArg0: true,
+ asm: arm.AMULAD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MULSF",
+ argLen: 3,
+ resultInArg0: true,
+ asm: arm.AMULSF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MULSD",
+ argLen: 3,
+ resultInArg0: true,
+ asm: arm.AMULSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMULAD",
+ argLen: 3,
+ resultInArg0: true,
+ asm: arm.AFMULAD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "AND",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "OR",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "XOR",
+ argLen: 2,
+ commutative: true,
+ asm: arm.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "BIC",
+ argLen: 2,
+ asm: arm.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "BICconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "BFX",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ABFX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "BFXU",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ABFXU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MVN",
+ argLen: 1,
+ asm: arm.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "NEGF",
+ argLen: 1,
+ asm: arm.ANEGF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "NEGD",
+ argLen: 1,
+ asm: arm.ANEGD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "SQRTD",
+ argLen: 1,
+ asm: arm.ASQRTD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "ABSD",
+ argLen: 1,
+ asm: arm.AABSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CLZ",
+ argLen: 1,
+ asm: arm.ACLZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "REV",
+ argLen: 1,
+ asm: arm.AREV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "REV16",
+ argLen: 1,
+ asm: arm.AREV16,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RBIT",
+ argLen: 1,
+ asm: arm.ARBIT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SLL",
+ argLen: 2,
+ asm: arm.ASLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SLLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ASLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRL",
+ argLen: 2,
+ asm: arm.ASRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ASRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRA",
+ argLen: 2,
+ asm: arm.ASRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRAconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ASRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRR",
+ argLen: 2,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRRconst",
+ auxType: auxInt32,
+ argLen: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORshiftRR",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "BICshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "BICshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "BICshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MVNshiftLL",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MVNshiftRL",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MVNshiftRA",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADCshiftLL",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.AADC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADCshiftRL",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.AADC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADCshiftRA",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.AADC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SBCshiftLL",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.ASBC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SBCshiftRL",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.ASBC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SBCshiftRA",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.ASBC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSCshiftLL",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.ARSC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSCshiftRL",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.ARSC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSCshiftRA",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.ARSC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDSshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDSshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDSshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBSshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBSshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBSshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBSshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBSshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBSshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDshiftLLreg",
+ argLen: 3,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDshiftRLreg",
+ argLen: 3,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDshiftRAreg",
+ argLen: 3,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBshiftLLreg",
+ argLen: 3,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBshiftRLreg",
+ argLen: 3,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBshiftRAreg",
+ argLen: 3,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBshiftLLreg",
+ argLen: 3,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBshiftRLreg",
+ argLen: 3,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBshiftRAreg",
+ argLen: 3,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDshiftLLreg",
+ argLen: 3,
+ asm: arm.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDshiftRLreg",
+ argLen: 3,
+ asm: arm.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDshiftRAreg",
+ argLen: 3,
+ asm: arm.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORshiftLLreg",
+ argLen: 3,
+ asm: arm.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORshiftRLreg",
+ argLen: 3,
+ asm: arm.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORshiftRAreg",
+ argLen: 3,
+ asm: arm.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORshiftLLreg",
+ argLen: 3,
+ asm: arm.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORshiftRLreg",
+ argLen: 3,
+ asm: arm.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORshiftRAreg",
+ argLen: 3,
+ asm: arm.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "BICshiftLLreg",
+ argLen: 3,
+ asm: arm.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "BICshiftRLreg",
+ argLen: 3,
+ asm: arm.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "BICshiftRAreg",
+ argLen: 3,
+ asm: arm.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MVNshiftLLreg",
+ argLen: 2,
+ asm: arm.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MVNshiftRLreg",
+ argLen: 2,
+ asm: arm.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MVNshiftRAreg",
+ argLen: 2,
+ asm: arm.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADCshiftLLreg",
+ argLen: 4,
+ asm: arm.AADC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADCshiftRLreg",
+ argLen: 4,
+ asm: arm.AADC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADCshiftRAreg",
+ argLen: 4,
+ asm: arm.AADC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SBCshiftLLreg",
+ argLen: 4,
+ asm: arm.ASBC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SBCshiftRLreg",
+ argLen: 4,
+ asm: arm.ASBC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SBCshiftRAreg",
+ argLen: 4,
+ asm: arm.ASBC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSCshiftLLreg",
+ argLen: 4,
+ asm: arm.ARSC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSCshiftRLreg",
+ argLen: 4,
+ asm: arm.ARSC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSCshiftRAreg",
+ argLen: 4,
+ asm: arm.ARSC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDSshiftLLreg",
+ argLen: 3,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDSshiftRLreg",
+ argLen: 3,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDSshiftRAreg",
+ argLen: 3,
+ asm: arm.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBSshiftLLreg",
+ argLen: 3,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBSshiftRLreg",
+ argLen: 3,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBSshiftRAreg",
+ argLen: 3,
+ asm: arm.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBSshiftLLreg",
+ argLen: 3,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBSshiftRLreg",
+ argLen: 3,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "RSBSshiftRAreg",
+ argLen: 3,
+ asm: arm.ARSB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "CMP",
+ argLen: 2,
+ asm: arm.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "CMPconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "CMN",
+ argLen: 2,
+ commutative: true,
+ asm: arm.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "CMNconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "TST",
+ argLen: 2,
+ commutative: true,
+ asm: arm.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "TSTconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "TEQ",
+ argLen: 2,
+ commutative: true,
+ asm: arm.ATEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "TEQconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm.ATEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "CMPF",
+ argLen: 2,
+ asm: arm.ACMPF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CMPD",
+ argLen: 2,
+ asm: arm.ACMPD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CMPshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "CMPshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "CMPshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "CMNshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "CMNshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "CMNshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "TSTshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "TSTshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "TSTshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "TEQshiftLL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ATEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "TEQshiftRL",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ATEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "TEQshiftRA",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: arm.ATEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "CMPshiftLLreg",
+ argLen: 3,
+ asm: arm.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "CMPshiftRLreg",
+ argLen: 3,
+ asm: arm.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "CMPshiftRAreg",
+ argLen: 3,
+ asm: arm.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "CMNshiftLLreg",
+ argLen: 3,
+ asm: arm.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "CMNshiftRLreg",
+ argLen: 3,
+ asm: arm.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "CMNshiftRAreg",
+ argLen: 3,
+ asm: arm.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "TSTshiftLLreg",
+ argLen: 3,
+ asm: arm.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "TSTshiftRLreg",
+ argLen: 3,
+ asm: arm.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "TSTshiftRAreg",
+ argLen: 3,
+ asm: arm.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "TEQshiftLLreg",
+ argLen: 3,
+ asm: arm.ATEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "TEQshiftRLreg",
+ argLen: 3,
+ asm: arm.ATEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "TEQshiftRAreg",
+ argLen: 3,
+ asm: arm.ATEQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "CMPF0",
+ argLen: 1,
+ asm: arm.ACMPF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CMPD0",
+ argLen: 1,
+ asm: arm.ACMPD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVWconst",
+ auxType: auxInt32,
+ argLen: 0,
+ rematerializeable: true,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVFconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: arm.AMOVF,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVDconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: arm.AMOVD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVWaddr",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymAddr,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294975488}, // SP SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVFload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm.AMOVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVBstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ },
+ },
+ {
+ name: "MOVHstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ },
+ },
+ {
+ name: "MOVWstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ },
+ },
+ {
+ name: "MOVFstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm.AMOVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVWloadidx",
+ argLen: 3,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWloadshiftLL",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWloadshiftRL",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWloadshiftRA",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBUloadidx",
+ argLen: 3,
+ asm: arm.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBloadidx",
+ argLen: 3,
+ asm: arm.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHUloadidx",
+ argLen: 3,
+ asm: arm.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHloadidx",
+ argLen: 3,
+ asm: arm.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWstoreidx",
+ argLen: 4,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {2, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreshiftLL",
+ auxType: auxInt32,
+ argLen: 4,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {2, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreshiftRL",
+ auxType: auxInt32,
+ argLen: 4,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {2, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreshiftRA",
+ auxType: auxInt32,
+ argLen: 4,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {2, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ },
+ },
+ {
+ name: "MOVBstoreidx",
+ argLen: 4,
+ asm: arm.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {2, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ },
+ },
+ {
+ name: "MOVHstoreidx",
+ argLen: 4,
+ asm: arm.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {2, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ {0, 4294998015}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP R14 SB
+ },
+ },
+ },
+ {
+ name: "MOVBreg",
+ argLen: 1,
+ asm: arm.AMOVBS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBUreg",
+ argLen: 1,
+ asm: arm.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHreg",
+ argLen: 1,
+ asm: arm.AMOVHS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHUreg",
+ argLen: 1,
+ asm: arm.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWreg",
+ argLen: 1,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWnop",
+ argLen: 1,
+ resultInArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWF",
+ argLen: 1,
+ asm: arm.AMOVWF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2147483648, // F15
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVWD",
+ argLen: 1,
+ asm: arm.AMOVWD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2147483648, // F15
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVWUF",
+ argLen: 1,
+ asm: arm.AMOVWF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2147483648, // F15
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVWUD",
+ argLen: 1,
+ asm: arm.AMOVWD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2147483648, // F15
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVFW",
+ argLen: 1,
+ asm: arm.AMOVFW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ clobbers: 2147483648, // F15
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVDW",
+ argLen: 1,
+ asm: arm.AMOVDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ clobbers: 2147483648, // F15
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVFWU",
+ argLen: 1,
+ asm: arm.AMOVFW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ clobbers: 2147483648, // F15
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVDWU",
+ argLen: 1,
+ asm: arm.AMOVDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ clobbers: 2147483648, // F15
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVFD",
+ argLen: 1,
+ asm: arm.AMOVFD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVDF",
+ argLen: 1,
+ asm: arm.AMOVDF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CMOVWHSconst",
+ auxType: auxInt32,
+ argLen: 2,
+ resultInArg0: true,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "CMOVWLSconst",
+ auxType: auxInt32,
+ argLen: 2,
+ resultInArg0: true,
+ asm: arm.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRAcond",
+ argLen: 3,
+ asm: arm.ASRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "CALLstatic",
+ auxType: auxCallOff,
+ argLen: 1,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ clobbers: 4294924287, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ {
+ name: "CALLclosure",
+ auxType: auxCallOff,
+ argLen: 3,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 128}, // R7
+ {0, 29695}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP R14
+ },
+ clobbers: 4294924287, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ {
+ name: "CALLinter",
+ auxType: auxCallOff,
+ argLen: 2,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 4294924287, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ {
+ name: "LoweredNilCheck",
+ argLen: 2,
+ nilCheck: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
+ },
+ },
+ },
+ {
+ name: "Equal",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "NotEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "LessThan",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "LessEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "GreaterThan",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "GreaterEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "LessThanU",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "LessEqualU",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "GreaterThanU",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "GreaterEqualU",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "DUFFZERO",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 1}, // R0
+ },
+ clobbers: 16386, // R1 R14
+ },
+ },
+ {
+ name: "DUFFCOPY",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 2}, // R1
+ },
+ clobbers: 16391, // R0 R1 R2 R14
+ },
+ },
+ {
+ name: "LoweredZero",
+ auxType: auxInt64,
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2, // R1
+ },
+ },
+ {
+ name: "LoweredMove",
+ auxType: auxInt64,
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 2}, // R1
+ {2, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 6, // R1 R2
+ },
+ },
+ {
+ name: "LoweredGetClosurePtr",
+ argLen: 0,
+ zeroWidth: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 128}, // R7
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerSP",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerPC",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsA",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 8}, // R3
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsB",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 4}, // R2
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsC",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // R0
+ {1, 2}, // R1
+ },
+ },
+ },
+ {
+ name: "LoweredPanicExtendA",
+ auxType: auxInt64,
+ argLen: 4,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 16}, // R4
+ {1, 4}, // R2
+ {2, 8}, // R3
+ },
+ },
+ },
+ {
+ name: "LoweredPanicExtendB",
+ auxType: auxInt64,
+ argLen: 4,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 16}, // R4
+ {1, 2}, // R1
+ {2, 4}, // R2
+ },
+ },
+ },
+ {
+ name: "LoweredPanicExtendC",
+ auxType: auxInt64,
+ argLen: 4,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 16}, // R4
+ {1, 1}, // R0
+ {2, 2}, // R1
+ },
+ },
+ },
+ {
+ name: "FlagConstant",
+ auxType: auxFlagConstant,
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "InvertFlags",
+ argLen: 1,
+ reg: regInfo{},
+ },
+ {
+ name: "LoweredWB",
+ auxType: auxSym,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymNone,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 8}, // R3
+ },
+ clobbers: 4294918144, // R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+
+ {
+ name: "ADCSflags",
+ argLen: 3,
+ commutative: true,
+ asm: arm64.AADCS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ADCzerocarry",
+ argLen: 1,
+ asm: arm64.AADC,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ADD",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ADDconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1878786047}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ADDSconstflags",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AADDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ADDSflags",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AADDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SUB",
+ argLen: 2,
+ asm: arm64.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SUBconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SBCSflags",
+ argLen: 3,
+ asm: arm64.ASBCS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SUBSflags",
+ argLen: 2,
+ asm: arm64.ASUBS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MUL",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AMUL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MULW",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AMULW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MNEG",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AMNEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MNEGW",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AMNEGW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MULH",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.ASMULH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "UMULH",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AUMULH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MULL",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.ASMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "UMULL",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AUMULL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "DIV",
+ argLen: 2,
+ asm: arm64.ASDIV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "UDIV",
+ argLen: 2,
+ asm: arm64.AUDIV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "DIVW",
+ argLen: 2,
+ asm: arm64.ASDIVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "UDIVW",
+ argLen: 2,
+ asm: arm64.AUDIVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOD",
+ argLen: 2,
+ asm: arm64.AREM,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "UMOD",
+ argLen: 2,
+ asm: arm64.AUREM,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MODW",
+ argLen: 2,
+ asm: arm64.AREMW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "UMODW",
+ argLen: 2,
+ asm: arm64.AUREMW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FADDS",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AFADDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FADDD",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AFADDD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FSUBS",
+ argLen: 2,
+ asm: arm64.AFSUBS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FSUBD",
+ argLen: 2,
+ asm: arm64.AFSUBD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMULS",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AFMULS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMULD",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AFMULD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FNMULS",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AFNMULS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FNMULD",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AFNMULD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FDIVS",
+ argLen: 2,
+ asm: arm64.AFDIVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FDIVD",
+ argLen: 2,
+ asm: arm64.AFDIVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "AND",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ANDconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "OR",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ORconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "XOR",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "XORconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "BIC",
+ argLen: 2,
+ asm: arm64.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "EON",
+ argLen: 2,
+ asm: arm64.AEON,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ORN",
+ argLen: 2,
+ asm: arm64.AORN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredMuluhilo",
+ argLen: 2,
+ resultNotInArgs: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MVN",
+ argLen: 1,
+ asm: arm64.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NEG",
+ argLen: 1,
+ asm: arm64.ANEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NEGSflags",
+ argLen: 1,
+ asm: arm64.ANEGS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NGCzerocarry",
+ argLen: 1,
+ asm: arm64.ANGC,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FABSD",
+ argLen: 1,
+ asm: arm64.AFABSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FNEGS",
+ argLen: 1,
+ asm: arm64.AFNEGS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FNEGD",
+ argLen: 1,
+ asm: arm64.AFNEGD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FSQRTD",
+ argLen: 1,
+ asm: arm64.AFSQRTD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "REV",
+ argLen: 1,
+ asm: arm64.AREV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "REVW",
+ argLen: 1,
+ asm: arm64.AREVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "REV16W",
+ argLen: 1,
+ asm: arm64.AREV16W,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "RBIT",
+ argLen: 1,
+ asm: arm64.ARBIT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "RBITW",
+ argLen: 1,
+ asm: arm64.ARBITW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "CLZ",
+ argLen: 1,
+ asm: arm64.ACLZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "CLZW",
+ argLen: 1,
+ asm: arm64.ACLZW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "VCNT",
+ argLen: 1,
+ asm: arm64.AVCNT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "VUADDLV",
+ argLen: 1,
+ asm: arm64.AVUADDLV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "LoweredRound32F",
+ argLen: 1,
+ resultInArg0: true,
+ zeroWidth: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "LoweredRound64F",
+ argLen: 1,
+ resultInArg0: true,
+ zeroWidth: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMADDS",
+ argLen: 3,
+ asm: arm64.AFMADDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMADDD",
+ argLen: 3,
+ asm: arm64.AFMADDD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FNMADDS",
+ argLen: 3,
+ asm: arm64.AFNMADDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FNMADDD",
+ argLen: 3,
+ asm: arm64.AFNMADDD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMSUBS",
+ argLen: 3,
+ asm: arm64.AFMSUBS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMSUBD",
+ argLen: 3,
+ asm: arm64.AFMSUBD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FNMSUBS",
+ argLen: 3,
+ asm: arm64.AFNMSUBS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FNMSUBD",
+ argLen: 3,
+ asm: arm64.AFNMSUBD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MADD",
+ argLen: 3,
+ asm: arm64.AMADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MADDW",
+ argLen: 3,
+ asm: arm64.AMADDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MSUB",
+ argLen: 3,
+ asm: arm64.AMSUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MSUBW",
+ argLen: 3,
+ asm: arm64.AMSUBW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SLL",
+ argLen: 2,
+ asm: arm64.ALSL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SLLconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ALSL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SRL",
+ argLen: 2,
+ asm: arm64.ALSR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SRLconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ALSR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SRA",
+ argLen: 2,
+ asm: arm64.AASR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SRAconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AASR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ROR",
+ argLen: 2,
+ asm: arm64.AROR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "RORW",
+ argLen: 2,
+ asm: arm64.ARORW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "RORconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AROR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "RORWconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ARORW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "EXTRconst",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AEXTR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "EXTRWconst",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AEXTRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "CMP",
+ argLen: 2,
+ asm: arm64.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMPconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMPW",
+ argLen: 2,
+ asm: arm64.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMPWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm64.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMN",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMNconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMNW",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.ACMNW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMNWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm64.ACMNW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "TST",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "TSTconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "TSTW",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.ATSTW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "TSTWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: arm64.ATSTW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "FCMPS",
+ argLen: 2,
+ asm: arm64.AFCMPS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCMPD",
+ argLen: 2,
+ asm: arm64.AFCMPD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCMPS0",
+ argLen: 1,
+ asm: arm64.AFCMPS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCMPD0",
+ argLen: 1,
+ asm: arm64.AFCMPD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MVNshiftLL",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MVNshiftRL",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MVNshiftRA",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NEGshiftLL",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ANEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NEGshiftRL",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ANEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NEGshiftRA",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ANEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ADDshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ADDshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ADDshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SUBshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SUBshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SUBshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ANDshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ANDshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ANDshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ORshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ORshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ORshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "XORshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "XORshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "XORshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AEOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "BICshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "BICshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "BICshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ABIC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "EONshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AEON,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "EONshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AEON,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "EONshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AEON,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ORNshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AORN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ORNshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AORN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "ORNshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.AORN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "CMPshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMPshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMPshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMNshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMNshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMNshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "TSTshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "TSTshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "TSTshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "BFI",
+ auxType: auxARM64BitField,
+ argLen: 2,
+ resultInArg0: true,
+ asm: arm64.ABFI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "BFXIL",
+ auxType: auxARM64BitField,
+ argLen: 2,
+ resultInArg0: true,
+ asm: arm64.ABFXIL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SBFIZ",
+ auxType: auxARM64BitField,
+ argLen: 1,
+ asm: arm64.ASBFIZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SBFX",
+ auxType: auxARM64BitField,
+ argLen: 1,
+ asm: arm64.ASBFX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "UBFIZ",
+ auxType: auxARM64BitField,
+ argLen: 1,
+ asm: arm64.AUBFIZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "UBFX",
+ auxType: auxARM64BitField,
+ argLen: 1,
+ asm: arm64.AUBFX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVDconst",
+ auxType: auxInt64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FMOVSconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: arm64.AFMOVS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVDconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: arm64.AFMOVD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVDaddr",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymAddr,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037928517632}, // SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVBload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVBUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm64.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVHload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVHUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm64.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVWload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVWUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm64.AMOVWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FMOVSload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: arm64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVDloadidx",
+ argLen: 3,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVWloadidx",
+ argLen: 3,
+ asm: arm64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVWUloadidx",
+ argLen: 3,
+ asm: arm64.AMOVWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVHloadidx",
+ argLen: 3,
+ asm: arm64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVHUloadidx",
+ argLen: 3,
+ asm: arm64.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVBloadidx",
+ argLen: 3,
+ asm: arm64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVBUloadidx",
+ argLen: 3,
+ asm: arm64.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FMOVSloadidx",
+ argLen: 3,
+ asm: arm64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVDloadidx",
+ argLen: 3,
+ asm: arm64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVHloadidx2",
+ argLen: 3,
+ asm: arm64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVHUloadidx2",
+ argLen: 3,
+ asm: arm64.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVWloadidx4",
+ argLen: 3,
+ asm: arm64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVWUloadidx4",
+ argLen: 3,
+ asm: arm64.AMOVWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVDloadidx8",
+ argLen: 3,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVBstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVHstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVWstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "STP",
+ auxType: auxSymOff,
+ argLen: 4,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.ASTP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "FMOVSstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVBstoreidx",
+ argLen: 4,
+ asm: arm64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVHstoreidx",
+ argLen: 4,
+ asm: arm64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreidx",
+ argLen: 4,
+ asm: arm64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVDstoreidx",
+ argLen: 4,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "FMOVSstoreidx",
+ argLen: 4,
+ asm: arm64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVDstoreidx",
+ argLen: 4,
+ asm: arm64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVHstoreidx2",
+ argLen: 4,
+ asm: arm64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreidx4",
+ argLen: 4,
+ asm: arm64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVDstoreidx8",
+ argLen: 4,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVBstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVHstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVWstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVDstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVQstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: arm64.ASTP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVBstorezeroidx",
+ argLen: 3,
+ asm: arm64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVHstorezeroidx",
+ argLen: 3,
+ asm: arm64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVWstorezeroidx",
+ argLen: 3,
+ asm: arm64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVDstorezeroidx",
+ argLen: 3,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVHstorezeroidx2",
+ argLen: 3,
+ asm: arm64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVWstorezeroidx4",
+ argLen: 3,
+ asm: arm64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVDstorezeroidx8",
+ argLen: 3,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "FMOVDgpfp",
+ argLen: 1,
+ asm: arm64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVDfpgp",
+ argLen: 1,
+ asm: arm64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FMOVSgpfp",
+ argLen: 1,
+ asm: arm64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVSfpgp",
+ argLen: 1,
+ asm: arm64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVBreg",
+ argLen: 1,
+ asm: arm64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVBUreg",
+ argLen: 1,
+ asm: arm64.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVHreg",
+ argLen: 1,
+ asm: arm64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVHUreg",
+ argLen: 1,
+ asm: arm64.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVWreg",
+ argLen: 1,
+ asm: arm64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVWUreg",
+ argLen: 1,
+ asm: arm64.AMOVWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVDreg",
+ argLen: 1,
+ asm: arm64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MOVDnop",
+ argLen: 1,
+ resultInArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "SCVTFWS",
+ argLen: 1,
+ asm: arm64.ASCVTFWS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "SCVTFWD",
+ argLen: 1,
+ asm: arm64.ASCVTFWD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "UCVTFWS",
+ argLen: 1,
+ asm: arm64.AUCVTFWS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "UCVTFWD",
+ argLen: 1,
+ asm: arm64.AUCVTFWD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "SCVTFS",
+ argLen: 1,
+ asm: arm64.ASCVTFS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "SCVTFD",
+ argLen: 1,
+ asm: arm64.ASCVTFD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "UCVTFS",
+ argLen: 1,
+ asm: arm64.AUCVTFS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "UCVTFD",
+ argLen: 1,
+ asm: arm64.AUCVTFD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCVTZSSW",
+ argLen: 1,
+ asm: arm64.AFCVTZSSW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FCVTZSDW",
+ argLen: 1,
+ asm: arm64.AFCVTZSDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FCVTZUSW",
+ argLen: 1,
+ asm: arm64.AFCVTZUSW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FCVTZUDW",
+ argLen: 1,
+ asm: arm64.AFCVTZUDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FCVTZSS",
+ argLen: 1,
+ asm: arm64.AFCVTZSS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FCVTZSD",
+ argLen: 1,
+ asm: arm64.AFCVTZSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FCVTZUS",
+ argLen: 1,
+ asm: arm64.AFCVTZUS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FCVTZUD",
+ argLen: 1,
+ asm: arm64.AFCVTZUD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FCVTSD",
+ argLen: 1,
+ asm: arm64.AFCVTSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCVTDS",
+ argLen: 1,
+ asm: arm64.AFCVTDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FRINTAD",
+ argLen: 1,
+ asm: arm64.AFRINTAD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FRINTMD",
+ argLen: 1,
+ asm: arm64.AFRINTMD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FRINTND",
+ argLen: 1,
+ asm: arm64.AFRINTND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FRINTPD",
+ argLen: 1,
+ asm: arm64.AFRINTPD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FRINTZD",
+ argLen: 1,
+ asm: arm64.AFRINTZD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "CSEL",
+ auxType: auxCCop,
+ argLen: 3,
+ asm: arm64.ACSEL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "CSEL0",
+ auxType: auxCCop,
+ argLen: 2,
+ asm: arm64.ACSEL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "CALLstatic",
+ auxType: auxCallOff,
+ argLen: 1,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ clobbers: 9223372035512336383, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ {
+ name: "CALLclosure",
+ auxType: auxCallOff,
+ argLen: 3,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 67108864}, // R26
+ {0, 1744568319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 SP
+ },
+ clobbers: 9223372035512336383, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ {
+ name: "CALLinter",
+ auxType: auxCallOff,
+ argLen: 2,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ clobbers: 9223372035512336383, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ {
+ name: "LoweredNilCheck",
+ argLen: 2,
+ nilCheck: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "Equal",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NotEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LessThan",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LessEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "GreaterThan",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "GreaterEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LessThanU",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LessEqualU",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "GreaterThanU",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "GreaterEqualU",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LessThanF",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LessEqualF",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "GreaterThanF",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "GreaterEqualF",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NotLessThanF",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NotLessEqualF",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NotGreaterThanF",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NotGreaterEqualF",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "DUFFZERO",
+ auxType: auxInt64,
+ argLen: 2,
+ faultOnNilArg0: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1048576}, // R20
+ },
+ clobbers: 538116096, // R16 R17 R20 R30
+ },
+ },
+ {
+ name: "LoweredZero",
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65536}, // R16
+ {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ clobbers: 65536, // R16
+ },
+ },
+ {
+ name: "DUFFCOPY",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2097152}, // R21
+ {1, 1048576}, // R20
+ },
+ clobbers: 607322112, // R16 R17 R20 R21 R26 R30
+ },
+ },
+ {
+ name: "LoweredMove",
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 131072}, // R17
+ {1, 65536}, // R16
+ {2, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ clobbers: 196608, // R16 R17
+ },
+ },
+ {
+ name: "LoweredGetClosurePtr",
+ argLen: 0,
+ zeroWidth: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 67108864}, // R26
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerSP",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerPC",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "FlagConstant",
+ auxType: auxFlagConstant,
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "InvertFlags",
+ argLen: 1,
+ reg: regInfo{},
+ },
+ {
+ name: "LDAR",
+ argLen: 2,
+ faultOnNilArg0: true,
+ asm: arm64.ALDAR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LDARB",
+ argLen: 2,
+ faultOnNilArg0: true,
+ asm: arm64.ALDARB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LDARW",
+ argLen: 2,
+ faultOnNilArg0: true,
+ asm: arm64.ALDARW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "STLRB",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ asm: arm64.ASTLRB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "STLR",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ asm: arm64.ASTLR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "STLRW",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ asm: arm64.ASTLRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange64",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange32",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange64Variant",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange32Variant",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd64",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd32",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd64Variant",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd32Variant",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas64",
+ argLen: 4,
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas32",
+ argLen: 4,
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas64Variant",
+ argLen: 4,
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas32Variant",
+ argLen: 4,
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAnd8",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ asm: arm64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAnd32",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ asm: arm64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicOr8",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ asm: arm64.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicOr32",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ asm: arm64.AORR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAnd8Variant",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAnd32Variant",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicOr8Variant",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicOr32Variant",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "LoweredWB",
+ auxType: auxSym,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymNone,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 8}, // R3
+ },
+ clobbers: 9223372035244359680, // R16 R17 R30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ {
+ name: "LoweredPanicBoundsA",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 8}, // R3
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsB",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 4}, // R2
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsC",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // R0
+ {1, 2}, // R1
+ },
+ },
+ },
+
+ {
+ name: "ADD",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AADDU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "ADDconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.AADDU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 536870910}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SUB",
+ argLen: 2,
+ asm: mips.ASUBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SUBconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.ASUBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MUL",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AMUL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ clobbers: 105553116266496, // HI LO
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MULT",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AMUL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 35184372088832}, // HI
+ {1, 70368744177664}, // LO
+ },
+ },
+ },
+ {
+ name: "MULTU",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AMULU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 35184372088832}, // HI
+ {1, 70368744177664}, // LO
+ },
+ },
+ },
+ {
+ name: "DIV",
+ argLen: 2,
+ asm: mips.ADIV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 35184372088832}, // HI
+ {1, 70368744177664}, // LO
+ },
+ },
+ },
+ {
+ name: "DIVU",
+ argLen: 2,
+ asm: mips.ADIVU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 35184372088832}, // HI
+ {1, 70368744177664}, // LO
+ },
+ },
+ },
+ {
+ name: "ADDF",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AADDF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "ADDD",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AADDD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "SUBF",
+ argLen: 2,
+ asm: mips.ASUBF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "SUBD",
+ argLen: 2,
+ asm: mips.ASUBD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "MULF",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AMULF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "MULD",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AMULD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "DIVF",
+ argLen: 2,
+ asm: mips.ADIVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "DIVD",
+ argLen: 2,
+ asm: mips.ADIVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "AND",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "ANDconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "OR",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "ORconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "XOR",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "XORconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.AXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "NOR",
+ argLen: 2,
+ commutative: true,
+ asm: mips.ANOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "NORconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.ANOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "NEG",
+ argLen: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "NEGF",
+ argLen: 1,
+ asm: mips.ANEGF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "NEGD",
+ argLen: 1,
+ asm: mips.ANEGD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "SQRTD",
+ argLen: 1,
+ asm: mips.ASQRTD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "SLL",
+ argLen: 2,
+ asm: mips.ASLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SLLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.ASLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SRL",
+ argLen: 2,
+ asm: mips.ASRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SRLconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.ASRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SRA",
+ argLen: 2,
+ asm: mips.ASRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SRAconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.ASRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "CLZ",
+ argLen: 1,
+ asm: mips.ACLZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SGT",
+ argLen: 2,
+ asm: mips.ASGT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SGTconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.ASGT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SGTzero",
+ argLen: 1,
+ asm: mips.ASGT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SGTU",
+ argLen: 2,
+ asm: mips.ASGTU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SGTUconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: mips.ASGTU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "SGTUzero",
+ argLen: 1,
+ asm: mips.ASGTU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "CMPEQF",
+ argLen: 2,
+ asm: mips.ACMPEQF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "CMPEQD",
+ argLen: 2,
+ asm: mips.ACMPEQD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "CMPGEF",
+ argLen: 2,
+ asm: mips.ACMPGEF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "CMPGED",
+ argLen: 2,
+ asm: mips.ACMPGED,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "CMPGTF",
+ argLen: 2,
+ asm: mips.ACMPGTF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "CMPGTD",
+ argLen: 2,
+ asm: mips.ACMPGTD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "MOVWconst",
+ auxType: auxInt32,
+ argLen: 0,
+ rematerializeable: true,
+ asm: mips.AMOVW,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVFconst",
+ auxType: auxFloat32,
+ argLen: 0,
+ rematerializeable: true,
+ asm: mips.AMOVF,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "MOVDconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: mips.AMOVD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "MOVWaddr",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymAddr,
+ asm: mips.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140737555464192}, // SP SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVBload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVBUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVHload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVHUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVWload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVFload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "MOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "MOVBstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVHstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVWstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVFstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVBstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVHstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVWstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVBreg",
+ argLen: 1,
+ asm: mips.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVBUreg",
+ argLen: 1,
+ asm: mips.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVHreg",
+ argLen: 1,
+ asm: mips.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVHUreg",
+ argLen: 1,
+ asm: mips.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVWreg",
+ argLen: 1,
+ asm: mips.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVWnop",
+ argLen: 1,
+ resultInArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "CMOVZ",
+ argLen: 3,
+ resultInArg0: true,
+ asm: mips.ACMOVZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ {1, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ {2, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "CMOVZzero",
+ argLen: 2,
+ resultInArg0: true,
+ asm: mips.ACMOVZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "MOVWF",
+ argLen: 1,
+ asm: mips.AMOVWF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "MOVWD",
+ argLen: 1,
+ asm: mips.AMOVWD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "TRUNCFW",
+ argLen: 1,
+ asm: mips.ATRUNCFW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "TRUNCDW",
+ argLen: 1,
+ asm: mips.ATRUNCDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "MOVFD",
+ argLen: 1,
+ asm: mips.AMOVFD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "MOVDF",
+ argLen: 1,
+ asm: mips.AMOVDF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ outputs: []outputInfo{
+ {0, 35183835217920}, // F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30
+ },
+ },
+ },
+ {
+ name: "CALLstatic",
+ auxType: auxCallOff,
+ argLen: 1,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ clobbers: 140737421246462, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31 F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30 HI LO
+ },
+ },
+ {
+ name: "CALLclosure",
+ auxType: auxCallOff,
+ argLen: 3,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 4194304}, // R22
+ {0, 402653182}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP R31
+ },
+ clobbers: 140737421246462, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31 F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30 HI LO
+ },
+ },
+ {
+ name: "CALLinter",
+ auxType: auxCallOff,
+ argLen: 2,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ clobbers: 140737421246462, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31 F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30 HI LO
+ },
+ },
+ {
+ name: "LoweredAtomicLoad8",
+ argLen: 2,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicLoad32",
+ argLen: 2,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore8",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore32",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStorezero",
+ argLen: 2,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAddconst",
+ auxType: auxInt32,
+ argLen: 2,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas",
+ argLen: 4,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {2, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAnd",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ asm: mips.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicOr",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ asm: mips.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ {0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "LoweredZero",
+ auxType: auxInt32,
+ argLen: 3,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ clobbers: 2, // R1
+ },
+ },
+ {
+ name: "LoweredMove",
+ auxType: auxInt32,
+ argLen: 4,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 2}, // R1
+ {2, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ clobbers: 6, // R1 R2
+ },
+ },
+ {
+ name: "LoweredNilCheck",
+ argLen: 2,
+ nilCheck: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
+ },
+ },
+ },
+ {
+ name: "FPFlagTrue",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "FPFlagFalse",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "LoweredGetClosurePtr",
+ argLen: 0,
+ zeroWidth: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4194304}, // R22
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerSP",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerPC",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
+ },
+ },
+ },
+ {
+ name: "LoweredWB",
+ auxType: auxSym,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymNone,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1048576}, // R20
+ {1, 2097152}, // R21
+ },
+ clobbers: 140737219919872, // R31 F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30 HI LO
+ },
+ },
+ {
+ name: "LoweredPanicBoundsA",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 8}, // R3
+ {1, 16}, // R4
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsB",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 8}, // R3
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsC",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 4}, // R2
+ },
+ },
+ },
+ {
+ name: "LoweredPanicExtendA",
+ auxType: auxInt64,
+ argLen: 4,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 32}, // R5
+ {1, 8}, // R3
+ {2, 16}, // R4
+ },
+ },
+ },
+ {
+ name: "LoweredPanicExtendB",
+ auxType: auxInt64,
+ argLen: 4,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 32}, // R5
+ {1, 4}, // R2
+ {2, 8}, // R3
+ },
+ },
+ },
+ {
+ name: "LoweredPanicExtendC",
+ auxType: auxInt64,
+ argLen: 4,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 32}, // R5
+ {1, 2}, // R1
+ {2, 4}, // R2
+ },
+ },
+ },
+
+ {
+ name: "ADDV",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AADDVU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "ADDVconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.AADDVU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 268435454}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SUBV",
+ argLen: 2,
+ asm: mips.ASUBVU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SUBVconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.ASUBVU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MULV",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AMULV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504606846976}, // HI
+ {1, 2305843009213693952}, // LO
+ },
+ },
+ },
+ {
+ name: "MULVU",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AMULVU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504606846976}, // HI
+ {1, 2305843009213693952}, // LO
+ },
+ },
+ },
+ {
+ name: "DIVV",
+ argLen: 2,
+ asm: mips.ADIVV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504606846976}, // HI
+ {1, 2305843009213693952}, // LO
+ },
+ },
+ },
+ {
+ name: "DIVVU",
+ argLen: 2,
+ asm: mips.ADIVVU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504606846976}, // HI
+ {1, 2305843009213693952}, // LO
+ },
+ },
+ },
+ {
+ name: "ADDF",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AADDF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "ADDD",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AADDD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "SUBF",
+ argLen: 2,
+ asm: mips.ASUBF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "SUBD",
+ argLen: 2,
+ asm: mips.ASUBD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MULF",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AMULF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MULD",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AMULD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "DIVF",
+ argLen: 2,
+ asm: mips.ADIVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "DIVD",
+ argLen: 2,
+ asm: mips.ADIVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "AND",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "ANDconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "OR",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "ORconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "XOR",
+ argLen: 2,
+ commutative: true,
+ asm: mips.AXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "XORconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.AXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "NOR",
+ argLen: 2,
+ commutative: true,
+ asm: mips.ANOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "NORconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.ANOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "NEGV",
+ argLen: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "NEGF",
+ argLen: 1,
+ asm: mips.ANEGF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "NEGD",
+ argLen: 1,
+ asm: mips.ANEGD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "SQRTD",
+ argLen: 1,
+ asm: mips.ASQRTD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "SLLV",
+ argLen: 2,
+ asm: mips.ASLLV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SLLVconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.ASLLV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SRLV",
+ argLen: 2,
+ asm: mips.ASRLV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SRLVconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.ASRLV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SRAV",
+ argLen: 2,
+ asm: mips.ASRAV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SRAVconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.ASRAV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SGT",
+ argLen: 2,
+ asm: mips.ASGT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SGTconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.ASGT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SGTU",
+ argLen: 2,
+ asm: mips.ASGTU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "SGTUconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: mips.ASGTU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "CMPEQF",
+ argLen: 2,
+ asm: mips.ACMPEQF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "CMPEQD",
+ argLen: 2,
+ asm: mips.ACMPEQD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "CMPGEF",
+ argLen: 2,
+ asm: mips.ACMPGEF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "CMPGED",
+ argLen: 2,
+ asm: mips.ACMPGED,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "CMPGTF",
+ argLen: 2,
+ asm: mips.ACMPGTF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "CMPGTD",
+ argLen: 2,
+ asm: mips.ACMPGTD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVVconst",
+ auxType: auxInt64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: mips.AMOVV,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVFconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: mips.AMOVF,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVDconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: mips.AMOVD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVVaddr",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymAddr,
+ asm: mips.AMOVV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018460942336}, // SP SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVBload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVBUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVHload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVHUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVWload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVWUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVVload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVFload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: mips.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVBstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVHstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVWstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVVstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVFstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ {1, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVBstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVHstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVWstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVVstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: mips.AMOVV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "MOVBreg",
+ argLen: 1,
+ asm: mips.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVBUreg",
+ argLen: 1,
+ asm: mips.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVHreg",
+ argLen: 1,
+ asm: mips.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVHUreg",
+ argLen: 1,
+ asm: mips.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVWreg",
+ argLen: 1,
+ asm: mips.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVWUreg",
+ argLen: 1,
+ asm: mips.AMOVWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVVreg",
+ argLen: 1,
+ asm: mips.AMOVV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVVnop",
+ argLen: 1,
+ resultInArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "MOVWF",
+ argLen: 1,
+ asm: mips.AMOVWF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVWD",
+ argLen: 1,
+ asm: mips.AMOVWD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVVF",
+ argLen: 1,
+ asm: mips.AMOVVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVVD",
+ argLen: 1,
+ asm: mips.AMOVVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "TRUNCFW",
+ argLen: 1,
+ asm: mips.ATRUNCFW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "TRUNCDW",
+ argLen: 1,
+ asm: mips.ATRUNCDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "TRUNCFV",
+ argLen: 1,
+ asm: mips.ATRUNCFV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "TRUNCDV",
+ argLen: 1,
+ asm: mips.ATRUNCDV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVFD",
+ argLen: 1,
+ asm: mips.AMOVFD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "MOVDF",
+ argLen: 1,
+ asm: mips.AMOVDF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1152921504338411520}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "CALLstatic",
+ auxType: auxCallOff,
+ argLen: 1,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ clobbers: 4611686018393833470, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO
+ },
+ },
+ {
+ name: "CALLclosure",
+ auxType: auxCallOff,
+ argLen: 3,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 4194304}, // R22
+ {0, 201326590}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP R31
+ },
+ clobbers: 4611686018393833470, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO
+ },
+ },
+ {
+ name: "CALLinter",
+ auxType: auxCallOff,
+ argLen: 2,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ clobbers: 4611686018393833470, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO
+ },
+ },
+ {
+ name: "DUFFZERO",
+ auxType: auxInt64,
+ argLen: 2,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ clobbers: 134217730, // R1 R31
+ },
+ },
+ {
+ name: "DUFFCOPY",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 2}, // R1
+ },
+ clobbers: 134217734, // R1 R2 R31
+ },
+ },
+ {
+ name: "LoweredZero",
+ auxType: auxInt64,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ clobbers: 2, // R1
+ },
+ },
+ {
+ name: "LoweredMove",
+ auxType: auxInt64,
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 2}, // R1
+ {2, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ clobbers: 6, // R1 R2
+ },
+ },
+ {
+ name: "LoweredAtomicLoad8",
+ argLen: 2,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicLoad32",
+ argLen: 2,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicLoad64",
+ argLen: 2,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore8",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore32",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore64",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStorezero32",
+ argLen: 2,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStorezero64",
+ argLen: 2,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange32",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange64",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd32",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd64",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAddconst32",
+ auxType: auxInt32,
+ argLen: 2,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAddconst64",
+ auxType: auxInt64,
+ argLen: 2,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas32",
+ argLen: 4,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {2, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas64",
+ argLen: 4,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {2, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ {0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
+ },
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredNilCheck",
+ argLen: 2,
+ nilCheck: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
+ },
+ },
+ },
+ {
+ name: "FPFlagTrue",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "FPFlagFalse",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredGetClosurePtr",
+ argLen: 0,
+ zeroWidth: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4194304}, // R22
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerSP",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerPC",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
+ },
+ },
+ },
+ {
+ name: "LoweredWB",
+ auxType: auxSym,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymNone,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1048576}, // R20
+ {1, 2097152}, // R21
+ },
+ clobbers: 4611686018293170176, // R31 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO
+ },
+ },
+ {
+ name: "LoweredPanicBoundsA",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 8}, // R3
+ {1, 16}, // R4
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsB",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 8}, // R3
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsC",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 4}, // R2
+ },
+ },
+ },
+
+ {
+ name: "ADD",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ADDconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FADD",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AFADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FADDS",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AFADDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "SUB",
+ argLen: 2,
+ asm: ppc64.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SUBFCconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.ASUBC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FSUB",
+ argLen: 2,
+ asm: ppc64.AFSUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FSUBS",
+ argLen: 2,
+ asm: ppc64.AFSUBS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "MULLD",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AMULLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MULLW",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AMULLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MULLDconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: ppc64.AMULLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MULLWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: ppc64.AMULLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MADDLD",
+ argLen: 3,
+ asm: ppc64.AMADDLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MULHD",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AMULHD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MULHW",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AMULHW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MULHDU",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AMULHDU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MULHWU",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AMULHWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredMuluhilo",
+ argLen: 2,
+ resultNotInArgs: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMUL",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AFMUL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FMULS",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AFMULS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FMADD",
+ argLen: 3,
+ asm: ppc64.AFMADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FMADDS",
+ argLen: 3,
+ asm: ppc64.AFMADDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FMSUB",
+ argLen: 3,
+ asm: ppc64.AFMSUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FMSUBS",
+ argLen: 3,
+ asm: ppc64.AFMSUBS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "SRAD",
+ argLen: 2,
+ asm: ppc64.ASRAD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SRAW",
+ argLen: 2,
+ asm: ppc64.ASRAW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SRD",
+ argLen: 2,
+ asm: ppc64.ASRD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SRW",
+ argLen: 2,
+ asm: ppc64.ASRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SLD",
+ argLen: 2,
+ asm: ppc64.ASLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SLW",
+ argLen: 2,
+ asm: ppc64.ASLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ROTL",
+ argLen: 2,
+ asm: ppc64.AROTL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ROTLW",
+ argLen: 2,
+ asm: ppc64.AROTLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "RLDICL",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: ppc64.ARLDICL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CLRLSLWI",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: ppc64.ACLRLSLWI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CLRLSLDI",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: ppc64.ACLRLSLDI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAdd64Carry",
+ argLen: 3,
+ resultNotInArgs: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SRADconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.ASRAD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SRAWconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.ASRAW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SRDconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.ASRD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SRWconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.ASRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SLDconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.ASLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "SLWconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.ASLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ROTLconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.AROTL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ROTLWconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.AROTLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "EXTSWSLconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.AEXTSWSLI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "RLWINM",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.ARLWNM,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "RLWNM",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: ppc64.ARLWNM,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "RLWMI",
+ auxType: auxInt64,
+ argLen: 2,
+ resultInArg0: true,
+ asm: ppc64.ARLWMI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CNTLZD",
+ argLen: 1,
+ clobberFlags: true,
+ asm: ppc64.ACNTLZD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CNTLZW",
+ argLen: 1,
+ clobberFlags: true,
+ asm: ppc64.ACNTLZW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CNTTZD",
+ argLen: 1,
+ asm: ppc64.ACNTTZD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CNTTZW",
+ argLen: 1,
+ asm: ppc64.ACNTTZW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "POPCNTD",
+ argLen: 1,
+ asm: ppc64.APOPCNTD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "POPCNTW",
+ argLen: 1,
+ asm: ppc64.APOPCNTW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "POPCNTB",
+ argLen: 1,
+ asm: ppc64.APOPCNTB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FDIV",
+ argLen: 2,
+ asm: ppc64.AFDIV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FDIVS",
+ argLen: 2,
+ asm: ppc64.AFDIVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "DIVD",
+ argLen: 2,
+ asm: ppc64.ADIVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "DIVW",
+ argLen: 2,
+ asm: ppc64.ADIVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "DIVDU",
+ argLen: 2,
+ asm: ppc64.ADIVDU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "DIVWU",
+ argLen: 2,
+ asm: ppc64.ADIVWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MODUD",
+ argLen: 2,
+ asm: ppc64.AMODUD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MODSD",
+ argLen: 2,
+ asm: ppc64.AMODSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MODUW",
+ argLen: 2,
+ asm: ppc64.AMODUW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MODSW",
+ argLen: 2,
+ asm: ppc64.AMODSW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FCTIDZ",
+ argLen: 1,
+ asm: ppc64.AFCTIDZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FCTIWZ",
+ argLen: 1,
+ asm: ppc64.AFCTIWZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FCFID",
+ argLen: 1,
+ asm: ppc64.AFCFID,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FCFIDS",
+ argLen: 1,
+ asm: ppc64.AFCFIDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FRSP",
+ argLen: 1,
+ asm: ppc64.AFRSP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "MFVSRD",
+ argLen: 1,
+ asm: ppc64.AMFVSRD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MTVSRD",
+ argLen: 1,
+ asm: ppc64.AMTVSRD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "AND",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ANDN",
+ argLen: 2,
+ asm: ppc64.AANDN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ANDCC",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AANDCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "OR",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ORN",
+ argLen: 2,
+ asm: ppc64.AORN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ORCC",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AORCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "NOR",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.ANOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "XOR",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "XORCC",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AXORCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "EQV",
+ argLen: 2,
+ commutative: true,
+ asm: ppc64.AEQV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "NEG",
+ argLen: 1,
+ asm: ppc64.ANEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FNEG",
+ argLen: 1,
+ asm: ppc64.AFNEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FSQRT",
+ argLen: 1,
+ asm: ppc64.AFSQRT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FSQRTS",
+ argLen: 1,
+ asm: ppc64.AFSQRTS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FFLOOR",
+ argLen: 1,
+ asm: ppc64.AFRIM,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FCEIL",
+ argLen: 1,
+ asm: ppc64.AFRIP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FTRUNC",
+ argLen: 1,
+ asm: ppc64.AFRIZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FROUND",
+ argLen: 1,
+ asm: ppc64.AFRIN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FABS",
+ argLen: 1,
+ asm: ppc64.AFABS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FNABS",
+ argLen: 1,
+ asm: ppc64.AFNABS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FCPSGN",
+ argLen: 2,
+ asm: ppc64.AFCPSGN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "ORconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "XORconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.AXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ANDconst",
+ auxType: auxInt64,
+ argLen: 1,
+ clobberFlags: true,
+ asm: ppc64.AANDCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ANDCCconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.AANDCC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVBreg",
+ argLen: 1,
+ asm: ppc64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVBZreg",
+ argLen: 1,
+ asm: ppc64.AMOVBZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHreg",
+ argLen: 1,
+ asm: ppc64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHZreg",
+ argLen: 1,
+ asm: ppc64.AMOVHZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWreg",
+ argLen: 1,
+ asm: ppc64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWZreg",
+ argLen: 1,
+ asm: ppc64.AMOVWZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVBZload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVBZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHZload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVHZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWZload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVWZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDBRload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWBRload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHBRload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVHBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVBZloadidx",
+ argLen: 3,
+ asm: ppc64.AMOVBZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHloadidx",
+ argLen: 3,
+ asm: ppc64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHZloadidx",
+ argLen: 3,
+ asm: ppc64.AMOVHZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWloadidx",
+ argLen: 3,
+ asm: ppc64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWZloadidx",
+ argLen: 3,
+ asm: ppc64.AMOVWZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDloadidx",
+ argLen: 3,
+ asm: ppc64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHBRloadidx",
+ argLen: 3,
+ asm: ppc64.AMOVHBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWBRloadidx",
+ argLen: 3,
+ asm: ppc64.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDBRloadidx",
+ argLen: 3,
+ asm: ppc64.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMOVDloadidx",
+ argLen: 3,
+ asm: ppc64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FMOVSloadidx",
+ argLen: 3,
+ asm: ppc64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "MOVDBRstore",
+ auxType: auxSym,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWBRstore",
+ auxType: auxSym,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHBRstore",
+ auxType: auxSym,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVHBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FMOVSload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "MOVBstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMOVSstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVBstoreidx",
+ argLen: 4,
+ asm: ppc64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHstoreidx",
+ argLen: 4,
+ asm: ppc64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWstoreidx",
+ argLen: 4,
+ asm: ppc64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDstoreidx",
+ argLen: 4,
+ asm: ppc64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMOVDstoreidx",
+ argLen: 4,
+ asm: ppc64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMOVSstoreidx",
+ argLen: 4,
+ asm: ppc64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHBRstoreidx",
+ argLen: 4,
+ asm: ppc64.AMOVHBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWBRstoreidx",
+ argLen: 4,
+ asm: ppc64.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDBRstoreidx",
+ argLen: 4,
+ asm: ppc64.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVBstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDaddr",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymAddr,
+ asm: ppc64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDconst",
+ auxType: auxInt64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: ppc64.AMOVD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMOVDconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: ppc64.AFMOVD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FMOVSconst",
+ auxType: auxFloat32,
+ argLen: 0,
+ rematerializeable: true,
+ asm: ppc64.AFMOVS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FCMPU",
+ argLen: 2,
+ asm: ppc64.AFCMPU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "CMP",
+ argLen: 2,
+ asm: ppc64.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CMPU",
+ argLen: 2,
+ asm: ppc64.ACMPU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CMPW",
+ argLen: 2,
+ asm: ppc64.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CMPWU",
+ argLen: 2,
+ asm: ppc64.ACMPWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CMPconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CMPUconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: ppc64.ACMPU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CMPWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: ppc64.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "CMPWUconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: ppc64.ACMPWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ISEL",
+ auxType: auxInt32,
+ argLen: 3,
+ asm: ppc64.AISEL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "ISELB",
+ auxType: auxInt32,
+ argLen: 2,
+ asm: ppc64.AISEL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "Equal",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "NotEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LessThan",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FLessThan",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LessEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FLessEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "GreaterThan",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FGreaterThan",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "GreaterEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FGreaterEqual",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredGetClosurePtr",
+ argLen: 0,
+ zeroWidth: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 2048}, // R11
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerSP",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerPC",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredNilCheck",
+ argLen: 2,
+ clobberFlags: true,
+ nilCheck: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ clobbers: 2147483648, // R31
+ },
+ },
+ {
+ name: "LoweredRound32F",
+ argLen: 1,
+ resultInArg0: true,
+ zeroWidth: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "LoweredRound64F",
+ argLen: 1,
+ resultInArg0: true,
+ zeroWidth: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "CALLstatic",
+ auxType: auxCallOff,
+ argLen: 1,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ {
+ name: "CALLclosure",
+ auxType: auxCallOff,
+ argLen: 3,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4096}, // R12
+ {1, 2048}, // R11
+ },
+ clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ {
+ name: "CALLinter",
+ auxType: auxCallOff,
+ argLen: 2,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4096}, // R12
+ },
+ clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ {
+ name: "LoweredZero",
+ auxType: auxInt64,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1048576}, // R20
+ },
+ clobbers: 1048576, // R20
+ },
+ },
+ {
+ name: "LoweredZeroShort",
+ auxType: auxInt64,
+ argLen: 2,
+ faultOnNilArg0: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredQuadZeroShort",
+ auxType: auxInt64,
+ argLen: 2,
+ faultOnNilArg0: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredQuadZero",
+ auxType: auxInt64,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1048576}, // R20
+ },
+ clobbers: 1048576, // R20
+ },
+ },
+ {
+ name: "LoweredMove",
+ auxType: auxInt64,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1048576}, // R20
+ {1, 2097152}, // R21
+ },
+ clobbers: 3145728, // R20 R21
+ },
+ },
+ {
+ name: "LoweredMoveShort",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredQuadMove",
+ auxType: auxInt64,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1048576}, // R20
+ {1, 2097152}, // R21
+ },
+ clobbers: 3145728, // R20 R21
+ },
+ },
+ {
+ name: "LoweredQuadMoveShort",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore8",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore32",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore64",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicLoad8",
+ auxType: auxInt64,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicLoad32",
+ auxType: auxInt64,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicLoad64",
+ auxType: auxInt64,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicLoadPtr",
+ auxType: auxInt64,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd32",
+ argLen: 3,
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd64",
+ argLen: 3,
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange32",
+ argLen: 3,
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange64",
+ argLen: 3,
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas64",
+ auxType: auxInt64,
+ argLen: 4,
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas32",
+ auxType: auxInt64,
+ argLen: 4,
+ resultNotInArgs: true,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAnd8",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ asm: ppc64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAnd32",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ asm: ppc64.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicOr8",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ asm: ppc64.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicOr32",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ asm: ppc64.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "LoweredWB",
+ auxType: auxSym,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymNone,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1048576}, // R20
+ {1, 2097152}, // R21
+ },
+ clobbers: 576460746931312640, // R11 R12 R18 R19 R22 R23 R24 R25 R26 R27 R28 R29 R31 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ {
+ name: "LoweredPanicBoundsA",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 32}, // R5
+ {1, 64}, // R6
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsB",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 16}, // R4
+ {1, 32}, // R5
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsC",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 8}, // R3
+ {1, 16}, // R4
+ },
+ },
+ },
+ {
+ name: "InvertFlags",
+ argLen: 1,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagEQ",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagLT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagGT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+
+ {
+ name: "ADD",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "ADDI",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: riscv.AADDI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "ADDIW",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: riscv.AADDIW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "NEG",
+ argLen: 1,
+ asm: riscv.ANEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "NEGW",
+ argLen: 1,
+ asm: riscv.ANEGW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SUB",
+ argLen: 2,
+ asm: riscv.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SUBW",
+ argLen: 2,
+ asm: riscv.ASUBW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MUL",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AMUL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MULW",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AMULW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MULH",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AMULH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MULHU",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AMULHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "DIV",
+ argLen: 2,
+ asm: riscv.ADIV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "DIVU",
+ argLen: 2,
+ asm: riscv.ADIVU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "DIVW",
+ argLen: 2,
+ asm: riscv.ADIVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "DIVUW",
+ argLen: 2,
+ asm: riscv.ADIVUW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "REM",
+ argLen: 2,
+ asm: riscv.AREM,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "REMU",
+ argLen: 2,
+ asm: riscv.AREMU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "REMW",
+ argLen: 2,
+ asm: riscv.AREMW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "REMUW",
+ argLen: 2,
+ asm: riscv.AREMUW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVaddr",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymRdWr,
+ asm: riscv.AMOV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVBconst",
+ auxType: auxInt8,
+ argLen: 0,
+ rematerializeable: true,
+ asm: riscv.AMOV,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVHconst",
+ auxType: auxInt16,
+ argLen: 0,
+ rematerializeable: true,
+ asm: riscv.AMOV,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVWconst",
+ auxType: auxInt32,
+ argLen: 0,
+ rematerializeable: true,
+ asm: riscv.AMOV,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVDconst",
+ auxType: auxInt64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: riscv.AMOV,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVBload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: riscv.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVHload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: riscv.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVWload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: riscv.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: riscv.AMOV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVBUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: riscv.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVHUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: riscv.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVWUload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: riscv.AMOVWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVBstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: riscv.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "MOVHstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: riscv.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "MOVWstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: riscv.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "MOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: riscv.AMOV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "MOVBstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: riscv.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "MOVHstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: riscv.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "MOVWstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: riscv.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "MOVDstorezero",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: riscv.AMOV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "MOVBreg",
+ argLen: 1,
+ asm: riscv.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVHreg",
+ argLen: 1,
+ asm: riscv.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVWreg",
+ argLen: 1,
+ asm: riscv.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVDreg",
+ argLen: 1,
+ asm: riscv.AMOV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVBUreg",
+ argLen: 1,
+ asm: riscv.AMOVBU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVHUreg",
+ argLen: 1,
+ asm: riscv.AMOVHU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVWUreg",
+ argLen: 1,
+ asm: riscv.AMOVWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVDnop",
+ argLen: 1,
+ resultInArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SLL",
+ argLen: 2,
+ asm: riscv.ASLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SRA",
+ argLen: 2,
+ asm: riscv.ASRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SRL",
+ argLen: 2,
+ asm: riscv.ASRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SLLI",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: riscv.ASLLI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SRAI",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: riscv.ASRAI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SRLI",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: riscv.ASRLI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "XOR",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "XORI",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: riscv.AXORI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "OR",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "ORI",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: riscv.AORI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "AND",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "ANDI",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: riscv.AANDI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "NOT",
+ argLen: 1,
+ asm: riscv.ANOT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SEQZ",
+ argLen: 1,
+ asm: riscv.ASEQZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SNEZ",
+ argLen: 1,
+ asm: riscv.ASNEZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SLT",
+ argLen: 2,
+ asm: riscv.ASLT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SLTI",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: riscv.ASLTI,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SLTU",
+ argLen: 2,
+ asm: riscv.ASLTU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "SLTIU",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: riscv.ASLTIU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "MOVconvert",
+ argLen: 2,
+ asm: riscv.AMOV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "CALLstatic",
+ auxType: auxCallOff,
+ argLen: 1,
+ call: true,
+ reg: regInfo{
+ clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ {
+ name: "CALLclosure",
+ auxType: auxCallOff,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 524288}, // X20
+ {0, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ {
+ name: "CALLinter",
+ auxType: auxCallOff,
+ argLen: 2,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ {
+ name: "DUFFZERO",
+ auxType: auxInt64,
+ argLen: 2,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 512}, // X10
+ },
+ clobbers: 512, // X10
+ },
+ },
+ {
+ name: "DUFFCOPY",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1024}, // X11
+ {1, 512}, // X10
+ },
+ clobbers: 1536, // X10 X11
+ },
+ },
+ {
+ name: "LoweredZero",
+ auxType: auxInt64,
+ argLen: 3,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 16}, // X5
+ {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ clobbers: 16, // X5
+ },
+ },
+ {
+ name: "LoweredMove",
+ auxType: auxInt64,
+ argLen: 4,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 16}, // X5
+ {1, 32}, // X6
+ {2, 1006632884}, // X3 X5 X6 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ clobbers: 112, // X5 X6 X7
+ },
+ },
+ {
+ name: "LoweredAtomicLoad8",
+ argLen: 2,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicLoad32",
+ argLen: 2,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicLoad64",
+ argLen: 2,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore8",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore32",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicStore64",
+ argLen: 3,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange32",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30
+ {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange64",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30
+ {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd32",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30
+ {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicAdd64",
+ argLen: 3,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30
+ {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas32",
+ argLen: 4,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30
+ {2, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30
+ {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas64",
+ argLen: 4,
+ resultNotInArgs: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ unsafePoint: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30
+ {2, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30
+ {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredNilCheck",
+ argLen: 2,
+ nilCheck: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredGetClosurePtr",
+ argLen: 0,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 524288}, // X20
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerSP",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerPC",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "LoweredWB",
+ auxType: auxSym,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymNone,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 16}, // X5
+ {1, 32}, // X6
+ },
+ clobbers: 9223372034707292160, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ {
+ name: "LoweredPanicBoundsA",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 64}, // X7
+ {1, 134217728}, // X28
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsB",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 32}, // X6
+ {1, 64}, // X7
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsC",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 16}, // X5
+ {1, 32}, // X6
+ },
+ },
+ },
+ {
+ name: "FADDS",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AFADDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FSUBS",
+ argLen: 2,
+ asm: riscv.AFSUBS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMULS",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AFMULS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FDIVS",
+ argLen: 2,
+ asm: riscv.AFDIVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FSQRTS",
+ argLen: 1,
+ asm: riscv.AFSQRTS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FNEGS",
+ argLen: 1,
+ asm: riscv.AFNEGS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMVSX",
+ argLen: 1,
+ asm: riscv.AFMVSX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCVTSW",
+ argLen: 1,
+ asm: riscv.AFCVTSW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCVTSL",
+ argLen: 1,
+ asm: riscv.AFCVTSL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCVTWS",
+ argLen: 1,
+ asm: riscv.AFCVTWS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FCVTLS",
+ argLen: 1,
+ asm: riscv.AFCVTLS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FMOVWload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: riscv.AMOVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVWstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: riscv.AMOVF,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FEQS",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AFEQS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FNES",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AFNES,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FLTS",
+ argLen: 2,
+ asm: riscv.AFLTS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FLES",
+ argLen: 2,
+ asm: riscv.AFLES,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FADDD",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AFADDD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FSUBD",
+ argLen: 2,
+ asm: riscv.AFSUBD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMULD",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AFMULD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FDIVD",
+ argLen: 2,
+ asm: riscv.AFDIVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FSQRTD",
+ argLen: 1,
+ asm: riscv.AFSQRTD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FNEGD",
+ argLen: 1,
+ asm: riscv.AFNEGD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMVDX",
+ argLen: 1,
+ asm: riscv.AFMVDX,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCVTDW",
+ argLen: 1,
+ asm: riscv.AFCVTDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCVTDL",
+ argLen: 1,
+ asm: riscv.AFCVTDL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCVTWD",
+ argLen: 1,
+ asm: riscv.AFCVTWD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FCVTLD",
+ argLen: 1,
+ asm: riscv.AFCVTLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FCVTDS",
+ argLen: 1,
+ asm: riscv.AFCVTDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FCVTSD",
+ argLen: 1,
+ asm: riscv.AFCVTSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: riscv.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: riscv.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FEQD",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AFEQD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FNED",
+ argLen: 2,
+ commutative: true,
+ asm: riscv.AFNED,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FLTD",
+ argLen: 2,
+ asm: riscv.AFLTD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+ {
+ name: "FLED",
+ argLen: 2,
+ asm: riscv.AFLED,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+ },
+ },
+ },
+
+ {
+ name: "FADDS",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ asm: s390x.AFADDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FADD",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ asm: s390x.AFADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FSUBS",
+ argLen: 2,
+ resultInArg0: true,
+ asm: s390x.AFSUBS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FSUB",
+ argLen: 2,
+ resultInArg0: true,
+ asm: s390x.AFSUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMULS",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ asm: s390x.AFMULS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMUL",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ asm: s390x.AFMUL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FDIVS",
+ argLen: 2,
+ resultInArg0: true,
+ asm: s390x.AFDIVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FDIV",
+ argLen: 2,
+ resultInArg0: true,
+ asm: s390x.AFDIV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FNEGS",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.AFNEGS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FNEG",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.AFNEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMADDS",
+ argLen: 3,
+ resultInArg0: true,
+ asm: s390x.AFMADDS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMADD",
+ argLen: 3,
+ resultInArg0: true,
+ asm: s390x.AFMADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMSUBS",
+ argLen: 3,
+ resultInArg0: true,
+ asm: s390x.AFMSUBS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMSUB",
+ argLen: 3,
+ resultInArg0: true,
+ asm: s390x.AFMSUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "LPDFR",
+ argLen: 1,
+ asm: s390x.ALPDFR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "LNDFR",
+ argLen: 1,
+ asm: s390x.ALNDFR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CPSDR",
+ argLen: 2,
+ asm: s390x.ACPSDR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FIDBR",
+ auxType: auxInt8,
+ argLen: 1,
+ asm: s390x.AFIDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMOVSload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMOVSconst",
+ auxType: auxFloat32,
+ argLen: 0,
+ rematerializeable: true,
+ asm: s390x.AFMOVS,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMOVDconst",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: s390x.AFMOVD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMOVSloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: s390x.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMOVDloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymRead,
+ asm: s390x.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMOVSstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMOVSstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: s390x.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FMOVDstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ symEffect: SymWrite,
+ asm: s390x.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "ADD",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: s390x.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDW",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: s390x.AADDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDconst",
+ auxType: auxInt32,
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.AADDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.AADD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDWload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.AADDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUB",
+ argLen: 2,
+ clobberFlags: true,
+ asm: s390x.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBW",
+ argLen: 2,
+ clobberFlags: true,
+ asm: s390x.ASUBW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.ASUBW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.ASUB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBWload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.ASUBW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULLD",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AMULLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULLW",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AMULLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULLDconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AMULLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULLWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AMULLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULLDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.AMULLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULLWload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.AMULLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULHD",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AMULHD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2048, // R11
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MULHDU",
+ argLen: 2,
+ commutative: true,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AMULHDU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2048, // R11
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "DIVD",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.ADIVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2048, // R11
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "DIVW",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.ADIVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2048, // R11
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "DIVDU",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.ADIVDU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2048, // R11
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "DIVWU",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.ADIVWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2048, // R11
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MODD",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AMODD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2048, // R11
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MODW",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AMODW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2048, // R11
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MODDU",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AMODDU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2048, // R11
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "MODWU",
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AMODWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ {1, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ clobbers: 2048, // R11
+ outputs: []outputInfo{
+ {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+ },
+ },
+ },
+ {
+ name: "AND",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: s390x.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDW",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: s390x.AANDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDconst",
+ auxType: auxInt64,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AANDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.AAND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ANDWload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.AANDW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "OR",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: s390x.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORW",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: s390x.AORW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORconst",
+ auxType: auxInt64,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AORW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.AOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ORWload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.AORW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "XOR",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: s390x.AXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORW",
+ argLen: 2,
+ commutative: true,
+ clobberFlags: true,
+ asm: s390x.AXORW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORconst",
+ auxType: auxInt64,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.AXORW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.AXOR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "XORWload",
+ auxType: auxSymOff,
+ argLen: 3,
+ resultInArg0: true,
+ clobberFlags: true,
+ faultOnNilArg1: true,
+ symEffect: SymRead,
+ asm: s390x.AXORW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDC",
+ argLen: 2,
+ commutative: true,
+ asm: s390x.AADDC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDCconst",
+ auxType: auxInt16,
+ argLen: 1,
+ asm: s390x.AADDC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "ADDE",
+ argLen: 3,
+ commutative: true,
+ resultInArg0: true,
+ asm: s390x.AADDE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBC",
+ argLen: 2,
+ asm: s390x.ASUBC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SUBE",
+ argLen: 3,
+ resultInArg0: true,
+ asm: s390x.ASUBE,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CMP",
+ argLen: 2,
+ asm: s390x.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "CMPW",
+ argLen: 2,
+ asm: s390x.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "CMPU",
+ argLen: 2,
+ asm: s390x.ACMPU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "CMPWU",
+ argLen: 2,
+ asm: s390x.ACMPWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "CMPconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: s390x.ACMP,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "CMPWconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: s390x.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "CMPUconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: s390x.ACMPU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "CMPWUconst",
+ auxType: auxInt32,
+ argLen: 1,
+ asm: s390x.ACMPWU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "FCMPS",
+ argLen: 2,
+ asm: s390x.ACEBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "FCMP",
+ argLen: 2,
+ asm: s390x.AFCMPU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "LTDBR",
+ argLen: 1,
+ asm: s390x.ALTDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "LTEBR",
+ argLen: 1,
+ asm: s390x.ALTEBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "SLD",
+ argLen: 2,
+ asm: s390x.ASLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 23550}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SLW",
+ argLen: 2,
+ asm: s390x.ASLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 23550}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SLDconst",
+ auxType: auxUInt8,
+ argLen: 1,
+ asm: s390x.ASLD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SLWconst",
+ auxType: auxUInt8,
+ argLen: 1,
+ asm: s390x.ASLW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRD",
+ argLen: 2,
+ asm: s390x.ASRD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 23550}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRW",
+ argLen: 2,
+ asm: s390x.ASRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 23550}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRDconst",
+ auxType: auxUInt8,
+ argLen: 1,
+ asm: s390x.ASRD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRWconst",
+ auxType: auxUInt8,
+ argLen: 1,
+ asm: s390x.ASRW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRAD",
+ argLen: 2,
+ clobberFlags: true,
+ asm: s390x.ASRAD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 23550}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRAW",
+ argLen: 2,
+ clobberFlags: true,
+ asm: s390x.ASRAW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 23550}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRADconst",
+ auxType: auxUInt8,
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ASRAD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "SRAWconst",
+ auxType: auxUInt8,
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ASRAW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "RLLG",
+ argLen: 2,
+ asm: s390x.ARLLG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 23550}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "RLL",
+ argLen: 2,
+ asm: s390x.ARLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 23550}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "RLLconst",
+ auxType: auxUInt8,
+ argLen: 1,
+ asm: s390x.ARLL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "RXSBG",
+ auxType: auxS390XRotateParams,
+ argLen: 2,
+ resultInArg0: true,
+ clobberFlags: true,
+ asm: s390x.ARXSBG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "RISBGZ",
+ auxType: auxS390XRotateParams,
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ARISBGZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "NEG",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ANEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "NEGW",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ANEGW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "NOT",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "NOTW",
+ argLen: 1,
+ resultInArg0: true,
+ clobberFlags: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "FSQRT",
+ argLen: 1,
+ asm: s390x.AFSQRT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "LOCGR",
+ auxType: auxS390XCCMask,
+ argLen: 3,
+ resultInArg0: true,
+ asm: s390x.ALOCGR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ {1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBreg",
+ argLen: 1,
+ asm: s390x.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBZreg",
+ argLen: 1,
+ asm: s390x.AMOVBZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHreg",
+ argLen: 1,
+ asm: s390x.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHZreg",
+ argLen: 1,
+ asm: s390x.AMOVHZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWreg",
+ argLen: 1,
+ asm: s390x.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWZreg",
+ argLen: 1,
+ asm: s390x.AMOVWZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVDconst",
+ auxType: auxInt64,
+ argLen: 0,
+ rematerializeable: true,
+ asm: s390x.AMOVD,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "LDGR",
+ argLen: 1,
+ asm: s390x.ALDGR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "LGDR",
+ argLen: 1,
+ asm: s390x.ALGDR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CFDBRA",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACFDBRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CGDBRA",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACGDBRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CFEBRA",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACFEBRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CGEBRA",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACGEBRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CEFBRA",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACEFBRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CDFBRA",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACDFBRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CEGBRA",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACEGBRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CDGBRA",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACDGBRA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CLFEBR",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACLFEBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CLFDBR",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACLFDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CLGEBR",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACLGEBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CLGDBR",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACLGDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CELFBR",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACELFBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CDLFBR",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACDLFBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CELGBR",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACELGBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "CDLGBR",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.ACDLGBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "LEDBR",
+ argLen: 1,
+ asm: s390x.ALEDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "LDEBR",
+ argLen: 1,
+ asm: s390x.ALDEBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "MOVDaddr",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymRead,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295000064}, // SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVDaddridx",
+ auxType: auxSymOff,
+ argLen: 2,
+ symEffect: SymRead,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295000064}, // SP SB
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBZload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVBZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHZload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVHZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWZload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVWZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVDload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWBR",
+ argLen: 1,
+ asm: s390x.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVDBR",
+ argLen: 1,
+ asm: s390x.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHBRload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVHBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWBRload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVDBRload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVHstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVWstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVDstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVHBRstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVHBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVWBRstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVDBRstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MVC",
+ auxType: auxSymValAndOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ symEffect: SymNone,
+ asm: s390x.AMVC,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVBZloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVBZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHZloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVHZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWZloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVWZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVDloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVHBRloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVHBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWBRloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVDBRloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ commutative: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVHstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVWstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVDstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVHBRstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVHBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVWBRstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVDBRstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ commutative: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVBstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVHstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVWstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ },
+ },
+ {
+ name: "MOVDstoreconst",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ },
+ },
+ {
+ name: "CLEAR",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.ACLEAR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23550}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "CALLstatic",
+ auxType: auxCallOff,
+ argLen: 1,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ clobbers: 4294933503, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 g R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ {
+ name: "CALLclosure",
+ auxType: auxCallOff,
+ argLen: 3,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 4096}, // R12
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ clobbers: 4294933503, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 g R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ {
+ name: "CALLinter",
+ auxType: auxCallOff,
+ argLen: 2,
+ clobberFlags: true,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23550}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ clobbers: 4294933503, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 g R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ {
+ name: "InvertFlags",
+ argLen: 1,
+ reg: regInfo{},
+ },
+ {
+ name: "LoweredGetG",
+ argLen: 1,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "LoweredGetClosurePtr",
+ argLen: 0,
+ zeroWidth: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4096}, // R12
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerSP",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerPC",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "LoweredNilCheck",
+ argLen: 2,
+ clobberFlags: true,
+ nilCheck: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "LoweredRound32F",
+ argLen: 1,
+ resultInArg0: true,
+ zeroWidth: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "LoweredRound64F",
+ argLen: 1,
+ resultInArg0: true,
+ zeroWidth: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "LoweredWB",
+ auxType: auxSym,
+ argLen: 3,
+ clobberFlags: true,
+ symEffect: SymNone,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 8}, // R3
+ },
+ clobbers: 4294918144, // R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ {
+ name: "LoweredPanicBoundsA",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4}, // R2
+ {1, 8}, // R3
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsB",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 4}, // R2
+ },
+ },
+ },
+ {
+ name: "LoweredPanicBoundsC",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1}, // R0
+ {1, 2}, // R1
+ },
+ },
+ },
+ {
+ name: "FlagEQ",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagLT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagGT",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "FlagOV",
+ argLen: 0,
+ reg: regInfo{},
+ },
+ {
+ name: "SYNC",
+ argLen: 1,
+ asm: s390x.ASYNC,
+ reg: regInfo{},
+ },
+ {
+ name: "MOVBZatomicload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVBZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVWZatomicload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVWZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVDatomicload",
+ auxType: auxSymOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: s390x.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MOVBatomicstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVWatomicstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "MOVDatomicstore",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymWrite,
+ asm: s390x.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "LAA",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: s390x.ALAA,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "LAAG",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: s390x.ALAAG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "AddTupleFirst32",
+ argLen: 2,
+ reg: regInfo{},
+ },
+ {
+ name: "AddTupleFirst64",
+ argLen: 2,
+ reg: regInfo{},
+ },
+ {
+ name: "LAN",
+ argLen: 3,
+ clobberFlags: true,
+ hasSideEffects: true,
+ asm: s390x.ALAN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "LANfloor",
+ argLen: 3,
+ clobberFlags: true,
+ hasSideEffects: true,
+ asm: s390x.ALAN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ clobbers: 2, // R1
+ },
+ },
+ {
+ name: "LAO",
+ argLen: 3,
+ clobberFlags: true,
+ hasSideEffects: true,
+ asm: s390x.ALAO,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "LAOfloor",
+ argLen: 3,
+ clobberFlags: true,
+ hasSideEffects: true,
+ asm: s390x.ALAO,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ clobbers: 2, // R1
+ },
+ },
+ {
+ name: "LoweredAtomicCas32",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: s390x.ACS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1}, // R0
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ clobbers: 1, // R0
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicCas64",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: s390x.ACSG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1}, // R0
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {2, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ clobbers: 1, // R0
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange32",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: s390x.ACS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 1}, // R0
+ },
+ },
+ },
+ {
+ name: "LoweredAtomicExchange64",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ hasSideEffects: true,
+ symEffect: SymRdWr,
+ asm: s390x.ACSG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ {1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ outputs: []outputInfo{
+ {1, 0},
+ {0, 1}, // R0
+ },
+ },
+ },
+ {
+ name: "FLOGR",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.AFLOGR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ clobbers: 2, // R1
+ outputs: []outputInfo{
+ {0, 1}, // R0
+ },
+ },
+ },
+ {
+ name: "POPCNT",
+ argLen: 1,
+ clobberFlags: true,
+ asm: s390x.APOPCNT,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ },
+ },
+ {
+ name: "MLGR",
+ argLen: 2,
+ asm: s390x.AMLGR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 8}, // R3
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4}, // R2
+ {1, 8}, // R3
+ },
+ },
+ },
+ {
+ name: "SumBytes2",
+ argLen: 1,
+ reg: regInfo{},
+ },
+ {
+ name: "SumBytes4",
+ argLen: 1,
+ reg: regInfo{},
+ },
+ {
+ name: "SumBytes8",
+ argLen: 1,
+ reg: regInfo{},
+ },
+ {
+ name: "STMG2",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.ASTMG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // R1
+ {2, 4}, // R2
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "STMG3",
+ auxType: auxSymOff,
+ argLen: 5,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.ASTMG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // R1
+ {2, 4}, // R2
+ {3, 8}, // R3
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "STMG4",
+ auxType: auxSymOff,
+ argLen: 6,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.ASTMG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // R1
+ {2, 4}, // R2
+ {3, 8}, // R3
+ {4, 16}, // R4
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "STM2",
+ auxType: auxSymOff,
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.ASTMY,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // R1
+ {2, 4}, // R2
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "STM3",
+ auxType: auxSymOff,
+ argLen: 5,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.ASTMY,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // R1
+ {2, 4}, // R2
+ {3, 8}, // R3
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "STM4",
+ auxType: auxSymOff,
+ argLen: 6,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: s390x.ASTMY,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 2}, // R1
+ {2, 4}, // R2
+ {3, 8}, // R3
+ {4, 16}, // R4
+ {0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ },
+ },
+ {
+ name: "LoweredMove",
+ auxType: auxInt64,
+ argLen: 4,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ faultOnNilArg1: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 4}, // R2
+ {2, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ clobbers: 6, // R1 R2
+ },
+ },
+ {
+ name: "LoweredZero",
+ auxType: auxInt64,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 2}, // R1
+ {1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
+ },
+ clobbers: 2, // R1
+ },
+ },
+
+ {
+ name: "LoweredStaticCall",
+ auxType: auxCallOff,
+ argLen: 1,
+ call: true,
+ reg: regInfo{
+ clobbers: 844424930131967, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 g
+ },
+ },
+ {
+ name: "LoweredClosureCall",
+ auxType: auxCallOff,
+ argLen: 3,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ clobbers: 844424930131967, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 g
+ },
+ },
+ {
+ name: "LoweredInterCall",
+ auxType: auxCallOff,
+ argLen: 2,
+ call: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ clobbers: 844424930131967, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 g
+ },
+ },
+ {
+ name: "LoweredAddr",
+ auxType: auxSymOff,
+ argLen: 1,
+ rematerializeable: true,
+ symEffect: SymAddr,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredMove",
+ auxType: auxInt64,
+ argLen: 3,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredZero",
+ auxType: auxInt64,
+ argLen: 2,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredGetClosurePtr",
+ argLen: 0,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerPC",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredGetCallerSP",
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredNilCheck",
+ argLen: 2,
+ nilCheck: true,
+ faultOnNilArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredWB",
+ auxType: auxSym,
+ argLen: 3,
+ symEffect: SymNone,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ {1, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "LoweredConvert",
+ argLen: 2,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "Select",
+ argLen: 3,
+ asm: wasm.ASelect,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {2, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Load8U",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: wasm.AI64Load8U,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Load8S",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: wasm.AI64Load8S,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Load16U",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: wasm.AI64Load16U,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Load16S",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: wasm.AI64Load16S,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Load32U",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: wasm.AI64Load32U,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Load32S",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: wasm.AI64Load32S,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Load",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: wasm.AI64Load,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Store8",
+ auxType: auxInt64,
+ argLen: 3,
+ asm: wasm.AI64Store8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ },
+ },
+ {
+ name: "I64Store16",
+ auxType: auxInt64,
+ argLen: 3,
+ asm: wasm.AI64Store16,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ },
+ },
+ {
+ name: "I64Store32",
+ auxType: auxInt64,
+ argLen: 3,
+ asm: wasm.AI64Store32,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ },
+ },
+ {
+ name: "I64Store",
+ auxType: auxInt64,
+ argLen: 3,
+ asm: wasm.AI64Store,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ },
+ },
+ {
+ name: "F32Load",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: wasm.AF32Load,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "F64Load",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: wasm.AF64Load,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F32Store",
+ auxType: auxInt64,
+ argLen: 3,
+ asm: wasm.AF32Store,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ },
+ },
+ {
+ name: "F64Store",
+ auxType: auxInt64,
+ argLen: 3,
+ asm: wasm.AF64Store,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {0, 1407374883618815}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP SB
+ },
+ },
+ },
+ {
+ name: "I64Const",
+ auxType: auxInt64,
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F32Const",
+ auxType: auxFloat32,
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "F64Const",
+ auxType: auxFloat64,
+ argLen: 0,
+ rematerializeable: true,
+ reg: regInfo{
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "I64Eqz",
+ argLen: 1,
+ asm: wasm.AI64Eqz,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Eq",
+ argLen: 2,
+ asm: wasm.AI64Eq,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Ne",
+ argLen: 2,
+ asm: wasm.AI64Ne,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64LtS",
+ argLen: 2,
+ asm: wasm.AI64LtS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64LtU",
+ argLen: 2,
+ asm: wasm.AI64LtU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64GtS",
+ argLen: 2,
+ asm: wasm.AI64GtS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64GtU",
+ argLen: 2,
+ asm: wasm.AI64GtU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64LeS",
+ argLen: 2,
+ asm: wasm.AI64LeS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64LeU",
+ argLen: 2,
+ asm: wasm.AI64LeU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64GeS",
+ argLen: 2,
+ asm: wasm.AI64GeS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64GeU",
+ argLen: 2,
+ asm: wasm.AI64GeU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F32Eq",
+ argLen: 2,
+ asm: wasm.AF32Eq,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F32Ne",
+ argLen: 2,
+ asm: wasm.AF32Ne,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F32Lt",
+ argLen: 2,
+ asm: wasm.AF32Lt,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F32Gt",
+ argLen: 2,
+ asm: wasm.AF32Gt,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F32Le",
+ argLen: 2,
+ asm: wasm.AF32Le,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F32Ge",
+ argLen: 2,
+ asm: wasm.AF32Ge,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F64Eq",
+ argLen: 2,
+ asm: wasm.AF64Eq,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F64Ne",
+ argLen: 2,
+ asm: wasm.AF64Ne,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F64Lt",
+ argLen: 2,
+ asm: wasm.AF64Lt,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F64Gt",
+ argLen: 2,
+ asm: wasm.AF64Gt,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F64Le",
+ argLen: 2,
+ asm: wasm.AF64Le,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F64Ge",
+ argLen: 2,
+ asm: wasm.AF64Ge,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Add",
+ argLen: 2,
+ asm: wasm.AI64Add,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64AddConst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: wasm.AI64Add,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Sub",
+ argLen: 2,
+ asm: wasm.AI64Sub,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Mul",
+ argLen: 2,
+ asm: wasm.AI64Mul,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64DivS",
+ argLen: 2,
+ asm: wasm.AI64DivS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64DivU",
+ argLen: 2,
+ asm: wasm.AI64DivU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64RemS",
+ argLen: 2,
+ asm: wasm.AI64RemS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64RemU",
+ argLen: 2,
+ asm: wasm.AI64RemU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64And",
+ argLen: 2,
+ asm: wasm.AI64And,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Or",
+ argLen: 2,
+ asm: wasm.AI64Or,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Xor",
+ argLen: 2,
+ asm: wasm.AI64Xor,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Shl",
+ argLen: 2,
+ asm: wasm.AI64Shl,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64ShrS",
+ argLen: 2,
+ asm: wasm.AI64ShrS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64ShrU",
+ argLen: 2,
+ asm: wasm.AI64ShrU,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F32Neg",
+ argLen: 1,
+ asm: wasm.AF32Neg,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "F32Add",
+ argLen: 2,
+ asm: wasm.AF32Add,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "F32Sub",
+ argLen: 2,
+ asm: wasm.AF32Sub,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "F32Mul",
+ argLen: 2,
+ asm: wasm.AF32Mul,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "F32Div",
+ argLen: 2,
+ asm: wasm.AF32Div,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ {1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "F64Neg",
+ argLen: 1,
+ asm: wasm.AF64Neg,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Add",
+ argLen: 2,
+ asm: wasm.AF64Add,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Sub",
+ argLen: 2,
+ asm: wasm.AF64Sub,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Mul",
+ argLen: 2,
+ asm: wasm.AF64Mul,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Div",
+ argLen: 2,
+ asm: wasm.AF64Div,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "I64TruncSatF64S",
+ argLen: 1,
+ asm: wasm.AI64TruncSatF64S,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64TruncSatF64U",
+ argLen: 1,
+ asm: wasm.AI64TruncSatF64U,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64TruncSatF32S",
+ argLen: 1,
+ asm: wasm.AI64TruncSatF32S,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64TruncSatF32U",
+ argLen: 1,
+ asm: wasm.AI64TruncSatF32U,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F32ConvertI64S",
+ argLen: 1,
+ asm: wasm.AF32ConvertI64S,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "F32ConvertI64U",
+ argLen: 1,
+ asm: wasm.AF32ConvertI64U,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "F64ConvertI64S",
+ argLen: 1,
+ asm: wasm.AF64ConvertI64S,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64ConvertI64U",
+ argLen: 1,
+ asm: wasm.AF64ConvertI64U,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F32DemoteF64",
+ argLen: 1,
+ asm: wasm.AF32DemoteF64,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ },
+ },
+ {
+ name: "F64PromoteF32",
+ argLen: 1,
+ asm: wasm.AF64PromoteF32,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "I64Extend8S",
+ argLen: 1,
+ asm: wasm.AI64Extend8S,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Extend16S",
+ argLen: 1,
+ asm: wasm.AI64Extend16S,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Extend32S",
+ argLen: 1,
+ asm: wasm.AI64Extend32S,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "F32Sqrt",
+ argLen: 1,
+ asm: wasm.AF32Sqrt,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F32Trunc",
+ argLen: 1,
+ asm: wasm.AF32Trunc,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F32Ceil",
+ argLen: 1,
+ asm: wasm.AF32Ceil,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F32Floor",
+ argLen: 1,
+ asm: wasm.AF32Floor,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F32Nearest",
+ argLen: 1,
+ asm: wasm.AF32Nearest,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F32Abs",
+ argLen: 1,
+ asm: wasm.AF32Abs,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F32Copysign",
+ argLen: 2,
+ asm: wasm.AF32Copysign,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Sqrt",
+ argLen: 1,
+ asm: wasm.AF64Sqrt,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Trunc",
+ argLen: 1,
+ asm: wasm.AF64Trunc,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Ceil",
+ argLen: 1,
+ asm: wasm.AF64Ceil,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Floor",
+ argLen: 1,
+ asm: wasm.AF64Floor,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Nearest",
+ argLen: 1,
+ asm: wasm.AF64Nearest,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Abs",
+ argLen: 1,
+ asm: wasm.AF64Abs,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "F64Copysign",
+ argLen: 2,
+ asm: wasm.AF64Copysign,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ {1, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "I64Ctz",
+ argLen: 1,
+ asm: wasm.AI64Ctz,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Clz",
+ argLen: 1,
+ asm: wasm.AI64Clz,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I32Rotl",
+ argLen: 2,
+ asm: wasm.AI32Rotl,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Rotl",
+ argLen: 2,
+ asm: wasm.AI64Rotl,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ {1, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+ {
+ name: "I64Popcnt",
+ argLen: 1,
+ asm: wasm.AI64Popcnt,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 281474976776191}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+ },
+ outputs: []outputInfo{
+ {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+ },
+ },
+ },
+
+ {
+ name: "Add8",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Add16",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Add32",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Add64",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "AddPtr",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Add32F",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Add64F",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Sub8",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Sub16",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Sub32",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Sub64",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "SubPtr",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Sub32F",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Sub64F",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Mul8",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Mul16",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Mul32",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Mul64",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Mul32F",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Mul64F",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Div32F",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Div64F",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Hmul32",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Hmul32u",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Hmul64",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Hmul64u",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Mul32uhilo",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Mul64uhilo",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Mul32uover",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Mul64uover",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Avg32u",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Avg64u",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Div8",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Div8u",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Div16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Div16u",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Div32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Div32u",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Div64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Div64u",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Div128u",
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "Mod8",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Mod8u",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Mod16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Mod16u",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Mod32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Mod32u",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Mod64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Mod64u",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "And8",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "And16",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "And32",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "And64",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Or8",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Or16",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Or32",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Or64",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Xor8",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Xor16",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Xor32",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Xor64",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Lsh8x8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh8x16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh8x32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh8x64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh16x8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh16x16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh16x32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh16x64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh32x8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh32x16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh32x32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh32x64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh64x8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh64x16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh64x32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Lsh64x64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh8x8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh8x16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh8x32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh8x64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh16x8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh16x16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh16x32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh16x64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh32x8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh32x16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh32x32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh32x64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh64x8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh64x16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh64x32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh64x64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh8Ux8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh8Ux16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh8Ux32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh8Ux64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh16Ux8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh16Ux16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh16Ux32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh16Ux64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh32Ux8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh32Ux16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh32Ux32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh32Ux64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh64Ux8",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh64Ux16",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh64Ux32",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Rsh64Ux64",
+ auxType: auxBool,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Eq8",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Eq16",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Eq32",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Eq64",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "EqPtr",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "EqInter",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "EqSlice",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Eq32F",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Eq64F",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Neq8",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Neq16",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Neq32",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Neq64",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "NeqPtr",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "NeqInter",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "NeqSlice",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Neq32F",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Neq64F",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Less8",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Less8U",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Less16",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Less16U",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Less32",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Less32U",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Less64",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Less64U",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Less32F",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Less64F",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Leq8",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Leq8U",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Leq16",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Leq16U",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Leq32",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Leq32U",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Leq64",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Leq64U",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Leq32F",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Leq64F",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "CondSelect",
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "AndB",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "OrB",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "EqB",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "NeqB",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Not",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Neg8",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Neg16",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Neg32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Neg64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Neg32F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Neg64F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Com8",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Com16",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Com32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Com64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Ctz8",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Ctz16",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Ctz32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Ctz64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Ctz8NonZero",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Ctz16NonZero",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Ctz32NonZero",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Ctz64NonZero",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "BitLen8",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "BitLen16",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "BitLen32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "BitLen64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Bswap32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Bswap64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "BitRev8",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "BitRev16",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "BitRev32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "BitRev64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "PopCount8",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "PopCount16",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "PopCount32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "PopCount64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "RotateLeft8",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "RotateLeft16",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "RotateLeft32",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "RotateLeft64",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Sqrt",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Floor",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Ceil",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Trunc",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Round",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "RoundToEven",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Abs",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Copysign",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "FMA",
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "Phi",
+ argLen: -1,
+ zeroWidth: true,
+ generic: true,
+ },
+ {
+ name: "Copy",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Convert",
+ argLen: 2,
+ resultInArg0: true,
+ zeroWidth: true,
+ generic: true,
+ },
+ {
+ name: "ConstBool",
+ auxType: auxBool,
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "ConstString",
+ auxType: auxString,
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "ConstNil",
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "Const8",
+ auxType: auxInt8,
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "Const16",
+ auxType: auxInt16,
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "Const32",
+ auxType: auxInt32,
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "Const64",
+ auxType: auxInt64,
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "Const32F",
+ auxType: auxFloat32,
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "Const64F",
+ auxType: auxFloat64,
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "ConstInterface",
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "ConstSlice",
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "InitMem",
+ argLen: 0,
+ zeroWidth: true,
+ generic: true,
+ },
+ {
+ name: "Arg",
+ auxType: auxSymOff,
+ argLen: 0,
+ zeroWidth: true,
+ symEffect: SymRead,
+ generic: true,
+ },
+ {
+ name: "Addr",
+ auxType: auxSym,
+ argLen: 1,
+ symEffect: SymAddr,
+ generic: true,
+ },
+ {
+ name: "LocalAddr",
+ auxType: auxSym,
+ argLen: 2,
+ symEffect: SymAddr,
+ generic: true,
+ },
+ {
+ name: "SP",
+ argLen: 0,
+ zeroWidth: true,
+ generic: true,
+ },
+ {
+ name: "SB",
+ argLen: 0,
+ zeroWidth: true,
+ generic: true,
+ },
+ {
+ name: "Load",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Dereference",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Store",
+ auxType: auxTyp,
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "Move",
+ auxType: auxTypSize,
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "Zero",
+ auxType: auxTypSize,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "StoreWB",
+ auxType: auxTyp,
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "MoveWB",
+ auxType: auxTypSize,
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "ZeroWB",
+ auxType: auxTypSize,
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "WB",
+ auxType: auxSym,
+ argLen: 3,
+ symEffect: SymNone,
+ generic: true,
+ },
+ {
+ name: "HasCPUFeature",
+ auxType: auxSym,
+ argLen: 0,
+ symEffect: SymNone,
+ generic: true,
+ },
+ {
+ name: "PanicBounds",
+ auxType: auxInt64,
+ argLen: 3,
+ call: true,
+ generic: true,
+ },
+ {
+ name: "PanicExtend",
+ auxType: auxInt64,
+ argLen: 4,
+ call: true,
+ generic: true,
+ },
+ {
+ name: "ClosureCall",
+ auxType: auxCallOff,
+ argLen: 3,
+ call: true,
+ generic: true,
+ },
+ {
+ name: "StaticCall",
+ auxType: auxCallOff,
+ argLen: 1,
+ call: true,
+ generic: true,
+ },
+ {
+ name: "InterCall",
+ auxType: auxCallOff,
+ argLen: 2,
+ call: true,
+ generic: true,
+ },
+ {
+ name: "ClosureLECall",
+ auxType: auxCallOff,
+ argLen: -1,
+ call: true,
+ generic: true,
+ },
+ {
+ name: "StaticLECall",
+ auxType: auxCallOff,
+ argLen: -1,
+ call: true,
+ generic: true,
+ },
+ {
+ name: "InterLECall",
+ auxType: auxCallOff,
+ argLen: -1,
+ call: true,
+ generic: true,
+ },
+ {
+ name: "SignExt8to16",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "SignExt8to32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "SignExt8to64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "SignExt16to32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "SignExt16to64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "SignExt32to64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "ZeroExt8to16",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "ZeroExt8to32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "ZeroExt8to64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "ZeroExt16to32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "ZeroExt16to64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "ZeroExt32to64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Trunc16to8",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Trunc32to8",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Trunc32to16",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Trunc64to8",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Trunc64to16",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Trunc64to32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt32to32F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt32to64F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt64to32F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt64to64F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt32Fto32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt32Fto64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt64Fto32",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt64Fto64",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt32Fto64F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt64Fto32F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "CvtBoolToUint8",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Round32F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Round64F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "IsNonNil",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "IsInBounds",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "IsSliceInBounds",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "NilCheck",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "GetG",
+ argLen: 1,
+ zeroWidth: true,
+ generic: true,
+ },
+ {
+ name: "GetClosurePtr",
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "GetCallerPC",
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "GetCallerSP",
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "PtrIndex",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "OffPtr",
+ auxType: auxInt64,
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "SliceMake",
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "SlicePtr",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "SliceLen",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "SliceCap",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "ComplexMake",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "ComplexReal",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "ComplexImag",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "StringMake",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "StringPtr",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "StringLen",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "IMake",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "ITab",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "IData",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "StructMake0",
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "StructMake1",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "StructMake2",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "StructMake3",
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "StructMake4",
+ argLen: 4,
+ generic: true,
+ },
+ {
+ name: "StructSelect",
+ auxType: auxInt64,
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "ArrayMake0",
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "ArrayMake1",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "ArraySelect",
+ auxType: auxInt64,
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "StoreReg",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "LoadReg",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "FwdRef",
+ auxType: auxSym,
+ argLen: 0,
+ symEffect: SymNone,
+ generic: true,
+ },
+ {
+ name: "Unknown",
+ argLen: 0,
+ generic: true,
+ },
+ {
+ name: "VarDef",
+ auxType: auxSym,
+ argLen: 1,
+ zeroWidth: true,
+ symEffect: SymNone,
+ generic: true,
+ },
+ {
+ name: "VarKill",
+ auxType: auxSym,
+ argLen: 1,
+ symEffect: SymNone,
+ generic: true,
+ },
+ {
+ name: "VarLive",
+ auxType: auxSym,
+ argLen: 1,
+ zeroWidth: true,
+ symEffect: SymRead,
+ generic: true,
+ },
+ {
+ name: "KeepAlive",
+ argLen: 2,
+ zeroWidth: true,
+ generic: true,
+ },
+ {
+ name: "InlMark",
+ auxType: auxInt32,
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Int64Make",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Int64Hi",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Int64Lo",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Add32carry",
+ argLen: 2,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Add32withcarry",
+ argLen: 3,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Sub32carry",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Sub32withcarry",
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "Add64carry",
+ argLen: 3,
+ commutative: true,
+ generic: true,
+ },
+ {
+ name: "Sub64borrow",
+ argLen: 3,
+ generic: true,
+ },
+ {
+ name: "Signmask",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Zeromask",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Slicemask",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "SpectreIndex",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "SpectreSliceIndex",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "Cvt32Uto32F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt32Uto64F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt32Fto32U",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt64Fto32U",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt64Uto32F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt64Uto64F",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt32Fto64U",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Cvt64Fto64U",
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "Select0",
+ argLen: 1,
+ zeroWidth: true,
+ generic: true,
+ },
+ {
+ name: "Select1",
+ argLen: 1,
+ zeroWidth: true,
+ generic: true,
+ },
+ {
+ name: "SelectN",
+ auxType: auxInt64,
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "SelectNAddr",
+ auxType: auxInt64,
+ argLen: 1,
+ generic: true,
+ },
+ {
+ name: "MakeResult",
+ argLen: -1,
+ generic: true,
+ },
+ {
+ name: "AtomicLoad8",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "AtomicLoad32",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "AtomicLoad64",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "AtomicLoadPtr",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "AtomicLoadAcq32",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "AtomicLoadAcq64",
+ argLen: 2,
+ generic: true,
+ },
+ {
+ name: "AtomicStore8",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicStore32",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicStore64",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicStorePtrNoWB",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicStoreRel32",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicStoreRel64",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicExchange32",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicExchange64",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicAdd32",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicAdd64",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicCompareAndSwap32",
+ argLen: 4,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicCompareAndSwap64",
+ argLen: 4,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicCompareAndSwapRel32",
+ argLen: 4,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicAnd8",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicAnd32",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicOr8",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicOr32",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicAdd32Variant",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicAdd64Variant",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicExchange32Variant",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicExchange64Variant",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicCompareAndSwap32Variant",
+ argLen: 4,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicCompareAndSwap64Variant",
+ argLen: 4,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicAnd8Variant",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicAnd32Variant",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicOr8Variant",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "AtomicOr32Variant",
+ argLen: 3,
+ hasSideEffects: true,
+ generic: true,
+ },
+ {
+ name: "Clobber",
+ auxType: auxSymOff,
+ argLen: 0,
+ symEffect: SymNone,
+ generic: true,
+ },
+}
+
+func (o Op) Asm() obj.As { return opcodeTable[o].asm }
+func (o Op) Scale() int16 { return int16(opcodeTable[o].scale) }
+func (o Op) String() string { return opcodeTable[o].name }
+func (o Op) UsesScratch() bool { return opcodeTable[o].usesScratch }
+func (o Op) SymEffect() SymEffect { return opcodeTable[o].symEffect }
+func (o Op) IsCall() bool { return opcodeTable[o].call }
+func (o Op) HasSideEffects() bool { return opcodeTable[o].hasSideEffects }
+func (o Op) UnsafePoint() bool { return opcodeTable[o].unsafePoint }
+
+var registers386 = [...]Register{
+ {0, x86.REG_AX, 0, "AX"},
+ {1, x86.REG_CX, 1, "CX"},
+ {2, x86.REG_DX, 2, "DX"},
+ {3, x86.REG_BX, 3, "BX"},
+ {4, x86.REGSP, -1, "SP"},
+ {5, x86.REG_BP, 4, "BP"},
+ {6, x86.REG_SI, 5, "SI"},
+ {7, x86.REG_DI, 6, "DI"},
+ {8, x86.REG_X0, -1, "X0"},
+ {9, x86.REG_X1, -1, "X1"},
+ {10, x86.REG_X2, -1, "X2"},
+ {11, x86.REG_X3, -1, "X3"},
+ {12, x86.REG_X4, -1, "X4"},
+ {13, x86.REG_X5, -1, "X5"},
+ {14, x86.REG_X6, -1, "X6"},
+ {15, x86.REG_X7, -1, "X7"},
+ {16, 0, -1, "SB"},
+}
+var gpRegMask386 = regMask(239)
+var fpRegMask386 = regMask(65280)
+var specialRegMask386 = regMask(0)
+var framepointerReg386 = int8(5)
+var linkReg386 = int8(-1)
+var registersAMD64 = [...]Register{
+ {0, x86.REG_AX, 0, "AX"},
+ {1, x86.REG_CX, 1, "CX"},
+ {2, x86.REG_DX, 2, "DX"},
+ {3, x86.REG_BX, 3, "BX"},
+ {4, x86.REGSP, -1, "SP"},
+ {5, x86.REG_BP, 4, "BP"},
+ {6, x86.REG_SI, 5, "SI"},
+ {7, x86.REG_DI, 6, "DI"},
+ {8, x86.REG_R8, 7, "R8"},
+ {9, x86.REG_R9, 8, "R9"},
+ {10, x86.REG_R10, 9, "R10"},
+ {11, x86.REG_R11, 10, "R11"},
+ {12, x86.REG_R12, 11, "R12"},
+ {13, x86.REG_R13, 12, "R13"},
+ {14, x86.REG_R14, 13, "R14"},
+ {15, x86.REG_R15, 14, "R15"},
+ {16, x86.REG_X0, -1, "X0"},
+ {17, x86.REG_X1, -1, "X1"},
+ {18, x86.REG_X2, -1, "X2"},
+ {19, x86.REG_X3, -1, "X3"},
+ {20, x86.REG_X4, -1, "X4"},
+ {21, x86.REG_X5, -1, "X5"},
+ {22, x86.REG_X6, -1, "X6"},
+ {23, x86.REG_X7, -1, "X7"},
+ {24, x86.REG_X8, -1, "X8"},
+ {25, x86.REG_X9, -1, "X9"},
+ {26, x86.REG_X10, -1, "X10"},
+ {27, x86.REG_X11, -1, "X11"},
+ {28, x86.REG_X12, -1, "X12"},
+ {29, x86.REG_X13, -1, "X13"},
+ {30, x86.REG_X14, -1, "X14"},
+ {31, x86.REG_X15, -1, "X15"},
+ {32, 0, -1, "SB"},
+}
+var gpRegMaskAMD64 = regMask(65519)
+var fpRegMaskAMD64 = regMask(4294901760)
+var specialRegMaskAMD64 = regMask(0)
+var framepointerRegAMD64 = int8(5)
+var linkRegAMD64 = int8(-1)
+var registersARM = [...]Register{
+ {0, arm.REG_R0, 0, "R0"},
+ {1, arm.REG_R1, 1, "R1"},
+ {2, arm.REG_R2, 2, "R2"},
+ {3, arm.REG_R3, 3, "R3"},
+ {4, arm.REG_R4, 4, "R4"},
+ {5, arm.REG_R5, 5, "R5"},
+ {6, arm.REG_R6, 6, "R6"},
+ {7, arm.REG_R7, 7, "R7"},
+ {8, arm.REG_R8, 8, "R8"},
+ {9, arm.REG_R9, 9, "R9"},
+ {10, arm.REGG, -1, "g"},
+ {11, arm.REG_R11, -1, "R11"},
+ {12, arm.REG_R12, 10, "R12"},
+ {13, arm.REGSP, -1, "SP"},
+ {14, arm.REG_R14, 11, "R14"},
+ {15, arm.REG_R15, -1, "R15"},
+ {16, arm.REG_F0, -1, "F0"},
+ {17, arm.REG_F1, -1, "F1"},
+ {18, arm.REG_F2, -1, "F2"},
+ {19, arm.REG_F3, -1, "F3"},
+ {20, arm.REG_F4, -1, "F4"},
+ {21, arm.REG_F5, -1, "F5"},
+ {22, arm.REG_F6, -1, "F6"},
+ {23, arm.REG_F7, -1, "F7"},
+ {24, arm.REG_F8, -1, "F8"},
+ {25, arm.REG_F9, -1, "F9"},
+ {26, arm.REG_F10, -1, "F10"},
+ {27, arm.REG_F11, -1, "F11"},
+ {28, arm.REG_F12, -1, "F12"},
+ {29, arm.REG_F13, -1, "F13"},
+ {30, arm.REG_F14, -1, "F14"},
+ {31, arm.REG_F15, -1, "F15"},
+ {32, 0, -1, "SB"},
+}
+var gpRegMaskARM = regMask(21503)
+var fpRegMaskARM = regMask(4294901760)
+var specialRegMaskARM = regMask(0)
+var framepointerRegARM = int8(-1)
+var linkRegARM = int8(14)
+var registersARM64 = [...]Register{
+ {0, arm64.REG_R0, 0, "R0"},
+ {1, arm64.REG_R1, 1, "R1"},
+ {2, arm64.REG_R2, 2, "R2"},
+ {3, arm64.REG_R3, 3, "R3"},
+ {4, arm64.REG_R4, 4, "R4"},
+ {5, arm64.REG_R5, 5, "R5"},
+ {6, arm64.REG_R6, 6, "R6"},
+ {7, arm64.REG_R7, 7, "R7"},
+ {8, arm64.REG_R8, 8, "R8"},
+ {9, arm64.REG_R9, 9, "R9"},
+ {10, arm64.REG_R10, 10, "R10"},
+ {11, arm64.REG_R11, 11, "R11"},
+ {12, arm64.REG_R12, 12, "R12"},
+ {13, arm64.REG_R13, 13, "R13"},
+ {14, arm64.REG_R14, 14, "R14"},
+ {15, arm64.REG_R15, 15, "R15"},
+ {16, arm64.REG_R16, 16, "R16"},
+ {17, arm64.REG_R17, 17, "R17"},
+ {18, arm64.REG_R18, -1, "R18"},
+ {19, arm64.REG_R19, 18, "R19"},
+ {20, arm64.REG_R20, 19, "R20"},
+ {21, arm64.REG_R21, 20, "R21"},
+ {22, arm64.REG_R22, 21, "R22"},
+ {23, arm64.REG_R23, 22, "R23"},
+ {24, arm64.REG_R24, 23, "R24"},
+ {25, arm64.REG_R25, 24, "R25"},
+ {26, arm64.REG_R26, 25, "R26"},
+ {27, arm64.REGG, -1, "g"},
+ {28, arm64.REG_R29, -1, "R29"},
+ {29, arm64.REG_R30, 26, "R30"},
+ {30, arm64.REGSP, -1, "SP"},
+ {31, arm64.REG_F0, -1, "F0"},
+ {32, arm64.REG_F1, -1, "F1"},
+ {33, arm64.REG_F2, -1, "F2"},
+ {34, arm64.REG_F3, -1, "F3"},
+ {35, arm64.REG_F4, -1, "F4"},
+ {36, arm64.REG_F5, -1, "F5"},
+ {37, arm64.REG_F6, -1, "F6"},
+ {38, arm64.REG_F7, -1, "F7"},
+ {39, arm64.REG_F8, -1, "F8"},
+ {40, arm64.REG_F9, -1, "F9"},
+ {41, arm64.REG_F10, -1, "F10"},
+ {42, arm64.REG_F11, -1, "F11"},
+ {43, arm64.REG_F12, -1, "F12"},
+ {44, arm64.REG_F13, -1, "F13"},
+ {45, arm64.REG_F14, -1, "F14"},
+ {46, arm64.REG_F15, -1, "F15"},
+ {47, arm64.REG_F16, -1, "F16"},
+ {48, arm64.REG_F17, -1, "F17"},
+ {49, arm64.REG_F18, -1, "F18"},
+ {50, arm64.REG_F19, -1, "F19"},
+ {51, arm64.REG_F20, -1, "F20"},
+ {52, arm64.REG_F21, -1, "F21"},
+ {53, arm64.REG_F22, -1, "F22"},
+ {54, arm64.REG_F23, -1, "F23"},
+ {55, arm64.REG_F24, -1, "F24"},
+ {56, arm64.REG_F25, -1, "F25"},
+ {57, arm64.REG_F26, -1, "F26"},
+ {58, arm64.REG_F27, -1, "F27"},
+ {59, arm64.REG_F28, -1, "F28"},
+ {60, arm64.REG_F29, -1, "F29"},
+ {61, arm64.REG_F30, -1, "F30"},
+ {62, arm64.REG_F31, -1, "F31"},
+ {63, 0, -1, "SB"},
+}
+var gpRegMaskARM64 = regMask(670826495)
+var fpRegMaskARM64 = regMask(9223372034707292160)
+var specialRegMaskARM64 = regMask(0)
+var framepointerRegARM64 = int8(-1)
+var linkRegARM64 = int8(29)
+var registersMIPS = [...]Register{
+ {0, mips.REG_R0, -1, "R0"},
+ {1, mips.REG_R1, 0, "R1"},
+ {2, mips.REG_R2, 1, "R2"},
+ {3, mips.REG_R3, 2, "R3"},
+ {4, mips.REG_R4, 3, "R4"},
+ {5, mips.REG_R5, 4, "R5"},
+ {6, mips.REG_R6, 5, "R6"},
+ {7, mips.REG_R7, 6, "R7"},
+ {8, mips.REG_R8, 7, "R8"},
+ {9, mips.REG_R9, 8, "R9"},
+ {10, mips.REG_R10, 9, "R10"},
+ {11, mips.REG_R11, 10, "R11"},
+ {12, mips.REG_R12, 11, "R12"},
+ {13, mips.REG_R13, 12, "R13"},
+ {14, mips.REG_R14, 13, "R14"},
+ {15, mips.REG_R15, 14, "R15"},
+ {16, mips.REG_R16, 15, "R16"},
+ {17, mips.REG_R17, 16, "R17"},
+ {18, mips.REG_R18, 17, "R18"},
+ {19, mips.REG_R19, 18, "R19"},
+ {20, mips.REG_R20, 19, "R20"},
+ {21, mips.REG_R21, 20, "R21"},
+ {22, mips.REG_R22, 21, "R22"},
+ {23, mips.REG_R24, 22, "R24"},
+ {24, mips.REG_R25, 23, "R25"},
+ {25, mips.REG_R28, 24, "R28"},
+ {26, mips.REGSP, -1, "SP"},
+ {27, mips.REGG, -1, "g"},
+ {28, mips.REG_R31, 25, "R31"},
+ {29, mips.REG_F0, -1, "F0"},
+ {30, mips.REG_F2, -1, "F2"},
+ {31, mips.REG_F4, -1, "F4"},
+ {32, mips.REG_F6, -1, "F6"},
+ {33, mips.REG_F8, -1, "F8"},
+ {34, mips.REG_F10, -1, "F10"},
+ {35, mips.REG_F12, -1, "F12"},
+ {36, mips.REG_F14, -1, "F14"},
+ {37, mips.REG_F16, -1, "F16"},
+ {38, mips.REG_F18, -1, "F18"},
+ {39, mips.REG_F20, -1, "F20"},
+ {40, mips.REG_F22, -1, "F22"},
+ {41, mips.REG_F24, -1, "F24"},
+ {42, mips.REG_F26, -1, "F26"},
+ {43, mips.REG_F28, -1, "F28"},
+ {44, mips.REG_F30, -1, "F30"},
+ {45, mips.REG_HI, -1, "HI"},
+ {46, mips.REG_LO, -1, "LO"},
+ {47, 0, -1, "SB"},
+}
+var gpRegMaskMIPS = regMask(335544318)
+var fpRegMaskMIPS = regMask(35183835217920)
+var specialRegMaskMIPS = regMask(105553116266496)
+var framepointerRegMIPS = int8(-1)
+var linkRegMIPS = int8(28)
+var registersMIPS64 = [...]Register{
+ {0, mips.REG_R0, -1, "R0"},
+ {1, mips.REG_R1, 0, "R1"},
+ {2, mips.REG_R2, 1, "R2"},
+ {3, mips.REG_R3, 2, "R3"},
+ {4, mips.REG_R4, 3, "R4"},
+ {5, mips.REG_R5, 4, "R5"},
+ {6, mips.REG_R6, 5, "R6"},
+ {7, mips.REG_R7, 6, "R7"},
+ {8, mips.REG_R8, 7, "R8"},
+ {9, mips.REG_R9, 8, "R9"},
+ {10, mips.REG_R10, 9, "R10"},
+ {11, mips.REG_R11, 10, "R11"},
+ {12, mips.REG_R12, 11, "R12"},
+ {13, mips.REG_R13, 12, "R13"},
+ {14, mips.REG_R14, 13, "R14"},
+ {15, mips.REG_R15, 14, "R15"},
+ {16, mips.REG_R16, 15, "R16"},
+ {17, mips.REG_R17, 16, "R17"},
+ {18, mips.REG_R18, 17, "R18"},
+ {19, mips.REG_R19, 18, "R19"},
+ {20, mips.REG_R20, 19, "R20"},
+ {21, mips.REG_R21, 20, "R21"},
+ {22, mips.REG_R22, 21, "R22"},
+ {23, mips.REG_R24, 22, "R24"},
+ {24, mips.REG_R25, 23, "R25"},
+ {25, mips.REGSP, -1, "SP"},
+ {26, mips.REGG, -1, "g"},
+ {27, mips.REG_R31, 24, "R31"},
+ {28, mips.REG_F0, -1, "F0"},
+ {29, mips.REG_F1, -1, "F1"},
+ {30, mips.REG_F2, -1, "F2"},
+ {31, mips.REG_F3, -1, "F3"},
+ {32, mips.REG_F4, -1, "F4"},
+ {33, mips.REG_F5, -1, "F5"},
+ {34, mips.REG_F6, -1, "F6"},
+ {35, mips.REG_F7, -1, "F7"},
+ {36, mips.REG_F8, -1, "F8"},
+ {37, mips.REG_F9, -1, "F9"},
+ {38, mips.REG_F10, -1, "F10"},
+ {39, mips.REG_F11, -1, "F11"},
+ {40, mips.REG_F12, -1, "F12"},
+ {41, mips.REG_F13, -1, "F13"},
+ {42, mips.REG_F14, -1, "F14"},
+ {43, mips.REG_F15, -1, "F15"},
+ {44, mips.REG_F16, -1, "F16"},
+ {45, mips.REG_F17, -1, "F17"},
+ {46, mips.REG_F18, -1, "F18"},
+ {47, mips.REG_F19, -1, "F19"},
+ {48, mips.REG_F20, -1, "F20"},
+ {49, mips.REG_F21, -1, "F21"},
+ {50, mips.REG_F22, -1, "F22"},
+ {51, mips.REG_F23, -1, "F23"},
+ {52, mips.REG_F24, -1, "F24"},
+ {53, mips.REG_F25, -1, "F25"},
+ {54, mips.REG_F26, -1, "F26"},
+ {55, mips.REG_F27, -1, "F27"},
+ {56, mips.REG_F28, -1, "F28"},
+ {57, mips.REG_F29, -1, "F29"},
+ {58, mips.REG_F30, -1, "F30"},
+ {59, mips.REG_F31, -1, "F31"},
+ {60, mips.REG_HI, -1, "HI"},
+ {61, mips.REG_LO, -1, "LO"},
+ {62, 0, -1, "SB"},
+}
+var gpRegMaskMIPS64 = regMask(167772158)
+var fpRegMaskMIPS64 = regMask(1152921504338411520)
+var specialRegMaskMIPS64 = regMask(3458764513820540928)
+var framepointerRegMIPS64 = int8(-1)
+var linkRegMIPS64 = int8(27)
+var registersPPC64 = [...]Register{
+ {0, ppc64.REG_R0, -1, "R0"},
+ {1, ppc64.REGSP, -1, "SP"},
+ {2, 0, -1, "SB"},
+ {3, ppc64.REG_R3, 0, "R3"},
+ {4, ppc64.REG_R4, 1, "R4"},
+ {5, ppc64.REG_R5, 2, "R5"},
+ {6, ppc64.REG_R6, 3, "R6"},
+ {7, ppc64.REG_R7, 4, "R7"},
+ {8, ppc64.REG_R8, 5, "R8"},
+ {9, ppc64.REG_R9, 6, "R9"},
+ {10, ppc64.REG_R10, 7, "R10"},
+ {11, ppc64.REG_R11, 8, "R11"},
+ {12, ppc64.REG_R12, 9, "R12"},
+ {13, ppc64.REG_R13, -1, "R13"},
+ {14, ppc64.REG_R14, 10, "R14"},
+ {15, ppc64.REG_R15, 11, "R15"},
+ {16, ppc64.REG_R16, 12, "R16"},
+ {17, ppc64.REG_R17, 13, "R17"},
+ {18, ppc64.REG_R18, 14, "R18"},
+ {19, ppc64.REG_R19, 15, "R19"},
+ {20, ppc64.REG_R20, 16, "R20"},
+ {21, ppc64.REG_R21, 17, "R21"},
+ {22, ppc64.REG_R22, 18, "R22"},
+ {23, ppc64.REG_R23, 19, "R23"},
+ {24, ppc64.REG_R24, 20, "R24"},
+ {25, ppc64.REG_R25, 21, "R25"},
+ {26, ppc64.REG_R26, 22, "R26"},
+ {27, ppc64.REG_R27, 23, "R27"},
+ {28, ppc64.REG_R28, 24, "R28"},
+ {29, ppc64.REG_R29, 25, "R29"},
+ {30, ppc64.REGG, -1, "g"},
+ {31, ppc64.REG_R31, -1, "R31"},
+ {32, ppc64.REG_F0, -1, "F0"},
+ {33, ppc64.REG_F1, -1, "F1"},
+ {34, ppc64.REG_F2, -1, "F2"},
+ {35, ppc64.REG_F3, -1, "F3"},
+ {36, ppc64.REG_F4, -1, "F4"},
+ {37, ppc64.REG_F5, -1, "F5"},
+ {38, ppc64.REG_F6, -1, "F6"},
+ {39, ppc64.REG_F7, -1, "F7"},
+ {40, ppc64.REG_F8, -1, "F8"},
+ {41, ppc64.REG_F9, -1, "F9"},
+ {42, ppc64.REG_F10, -1, "F10"},
+ {43, ppc64.REG_F11, -1, "F11"},
+ {44, ppc64.REG_F12, -1, "F12"},
+ {45, ppc64.REG_F13, -1, "F13"},
+ {46, ppc64.REG_F14, -1, "F14"},
+ {47, ppc64.REG_F15, -1, "F15"},
+ {48, ppc64.REG_F16, -1, "F16"},
+ {49, ppc64.REG_F17, -1, "F17"},
+ {50, ppc64.REG_F18, -1, "F18"},
+ {51, ppc64.REG_F19, -1, "F19"},
+ {52, ppc64.REG_F20, -1, "F20"},
+ {53, ppc64.REG_F21, -1, "F21"},
+ {54, ppc64.REG_F22, -1, "F22"},
+ {55, ppc64.REG_F23, -1, "F23"},
+ {56, ppc64.REG_F24, -1, "F24"},
+ {57, ppc64.REG_F25, -1, "F25"},
+ {58, ppc64.REG_F26, -1, "F26"},
+ {59, ppc64.REG_F27, -1, "F27"},
+ {60, ppc64.REG_F28, -1, "F28"},
+ {61, ppc64.REG_F29, -1, "F29"},
+ {62, ppc64.REG_F30, -1, "F30"},
+ {63, ppc64.REG_F31, -1, "F31"},
+}
+var gpRegMaskPPC64 = regMask(1073733624)
+var fpRegMaskPPC64 = regMask(576460743713488896)
+var specialRegMaskPPC64 = regMask(0)
+var framepointerRegPPC64 = int8(1)
+var linkRegPPC64 = int8(-1)
+var registersRISCV64 = [...]Register{
+ {0, riscv.REG_X0, -1, "X0"},
+ {1, riscv.REGSP, -1, "SP"},
+ {2, riscv.REG_X3, 0, "X3"},
+ {3, riscv.REG_X4, -1, "X4"},
+ {4, riscv.REG_X5, 1, "X5"},
+ {5, riscv.REG_X6, 2, "X6"},
+ {6, riscv.REG_X7, 3, "X7"},
+ {7, riscv.REG_X8, 4, "X8"},
+ {8, riscv.REG_X9, 5, "X9"},
+ {9, riscv.REG_X10, 6, "X10"},
+ {10, riscv.REG_X11, 7, "X11"},
+ {11, riscv.REG_X12, 8, "X12"},
+ {12, riscv.REG_X13, 9, "X13"},
+ {13, riscv.REG_X14, 10, "X14"},
+ {14, riscv.REG_X15, 11, "X15"},
+ {15, riscv.REG_X16, 12, "X16"},
+ {16, riscv.REG_X17, 13, "X17"},
+ {17, riscv.REG_X18, 14, "X18"},
+ {18, riscv.REG_X19, 15, "X19"},
+ {19, riscv.REG_X20, 16, "X20"},
+ {20, riscv.REG_X21, 17, "X21"},
+ {21, riscv.REG_X22, 18, "X22"},
+ {22, riscv.REG_X23, 19, "X23"},
+ {23, riscv.REG_X24, 20, "X24"},
+ {24, riscv.REG_X25, 21, "X25"},
+ {25, riscv.REG_X26, 22, "X26"},
+ {26, riscv.REGG, -1, "g"},
+ {27, riscv.REG_X28, 23, "X28"},
+ {28, riscv.REG_X29, 24, "X29"},
+ {29, riscv.REG_X30, 25, "X30"},
+ {30, riscv.REG_X31, -1, "X31"},
+ {31, riscv.REG_F0, -1, "F0"},
+ {32, riscv.REG_F1, -1, "F1"},
+ {33, riscv.REG_F2, -1, "F2"},
+ {34, riscv.REG_F3, -1, "F3"},
+ {35, riscv.REG_F4, -1, "F4"},
+ {36, riscv.REG_F5, -1, "F5"},
+ {37, riscv.REG_F6, -1, "F6"},
+ {38, riscv.REG_F7, -1, "F7"},
+ {39, riscv.REG_F8, -1, "F8"},
+ {40, riscv.REG_F9, -1, "F9"},
+ {41, riscv.REG_F10, -1, "F10"},
+ {42, riscv.REG_F11, -1, "F11"},
+ {43, riscv.REG_F12, -1, "F12"},
+ {44, riscv.REG_F13, -1, "F13"},
+ {45, riscv.REG_F14, -1, "F14"},
+ {46, riscv.REG_F15, -1, "F15"},
+ {47, riscv.REG_F16, -1, "F16"},
+ {48, riscv.REG_F17, -1, "F17"},
+ {49, riscv.REG_F18, -1, "F18"},
+ {50, riscv.REG_F19, -1, "F19"},
+ {51, riscv.REG_F20, -1, "F20"},
+ {52, riscv.REG_F21, -1, "F21"},
+ {53, riscv.REG_F22, -1, "F22"},
+ {54, riscv.REG_F23, -1, "F23"},
+ {55, riscv.REG_F24, -1, "F24"},
+ {56, riscv.REG_F25, -1, "F25"},
+ {57, riscv.REG_F26, -1, "F26"},
+ {58, riscv.REG_F27, -1, "F27"},
+ {59, riscv.REG_F28, -1, "F28"},
+ {60, riscv.REG_F29, -1, "F29"},
+ {61, riscv.REG_F30, -1, "F30"},
+ {62, riscv.REG_F31, -1, "F31"},
+ {63, 0, -1, "SB"},
+}
+var gpRegMaskRISCV64 = regMask(1006632948)
+var fpRegMaskRISCV64 = regMask(9223372034707292160)
+var specialRegMaskRISCV64 = regMask(0)
+var framepointerRegRISCV64 = int8(-1)
+var linkRegRISCV64 = int8(0)
+var registersS390X = [...]Register{
+ {0, s390x.REG_R0, 0, "R0"},
+ {1, s390x.REG_R1, 1, "R1"},
+ {2, s390x.REG_R2, 2, "R2"},
+ {3, s390x.REG_R3, 3, "R3"},
+ {4, s390x.REG_R4, 4, "R4"},
+ {5, s390x.REG_R5, 5, "R5"},
+ {6, s390x.REG_R6, 6, "R6"},
+ {7, s390x.REG_R7, 7, "R7"},
+ {8, s390x.REG_R8, 8, "R8"},
+ {9, s390x.REG_R9, 9, "R9"},
+ {10, s390x.REG_R10, -1, "R10"},
+ {11, s390x.REG_R11, 10, "R11"},
+ {12, s390x.REG_R12, 11, "R12"},
+ {13, s390x.REGG, -1, "g"},
+ {14, s390x.REG_R14, 12, "R14"},
+ {15, s390x.REGSP, -1, "SP"},
+ {16, s390x.REG_F0, -1, "F0"},
+ {17, s390x.REG_F1, -1, "F1"},
+ {18, s390x.REG_F2, -1, "F2"},
+ {19, s390x.REG_F3, -1, "F3"},
+ {20, s390x.REG_F4, -1, "F4"},
+ {21, s390x.REG_F5, -1, "F5"},
+ {22, s390x.REG_F6, -1, "F6"},
+ {23, s390x.REG_F7, -1, "F7"},
+ {24, s390x.REG_F8, -1, "F8"},
+ {25, s390x.REG_F9, -1, "F9"},
+ {26, s390x.REG_F10, -1, "F10"},
+ {27, s390x.REG_F11, -1, "F11"},
+ {28, s390x.REG_F12, -1, "F12"},
+ {29, s390x.REG_F13, -1, "F13"},
+ {30, s390x.REG_F14, -1, "F14"},
+ {31, s390x.REG_F15, -1, "F15"},
+ {32, 0, -1, "SB"},
+}
+var gpRegMaskS390X = regMask(23551)
+var fpRegMaskS390X = regMask(4294901760)
+var specialRegMaskS390X = regMask(0)
+var framepointerRegS390X = int8(-1)
+var linkRegS390X = int8(14)
+var registersWasm = [...]Register{
+ {0, wasm.REG_R0, 0, "R0"},
+ {1, wasm.REG_R1, 1, "R1"},
+ {2, wasm.REG_R2, 2, "R2"},
+ {3, wasm.REG_R3, 3, "R3"},
+ {4, wasm.REG_R4, 4, "R4"},
+ {5, wasm.REG_R5, 5, "R5"},
+ {6, wasm.REG_R6, 6, "R6"},
+ {7, wasm.REG_R7, 7, "R7"},
+ {8, wasm.REG_R8, 8, "R8"},
+ {9, wasm.REG_R9, 9, "R9"},
+ {10, wasm.REG_R10, 10, "R10"},
+ {11, wasm.REG_R11, 11, "R11"},
+ {12, wasm.REG_R12, 12, "R12"},
+ {13, wasm.REG_R13, 13, "R13"},
+ {14, wasm.REG_R14, 14, "R14"},
+ {15, wasm.REG_R15, 15, "R15"},
+ {16, wasm.REG_F0, -1, "F0"},
+ {17, wasm.REG_F1, -1, "F1"},
+ {18, wasm.REG_F2, -1, "F2"},
+ {19, wasm.REG_F3, -1, "F3"},
+ {20, wasm.REG_F4, -1, "F4"},
+ {21, wasm.REG_F5, -1, "F5"},
+ {22, wasm.REG_F6, -1, "F6"},
+ {23, wasm.REG_F7, -1, "F7"},
+ {24, wasm.REG_F8, -1, "F8"},
+ {25, wasm.REG_F9, -1, "F9"},
+ {26, wasm.REG_F10, -1, "F10"},
+ {27, wasm.REG_F11, -1, "F11"},
+ {28, wasm.REG_F12, -1, "F12"},
+ {29, wasm.REG_F13, -1, "F13"},
+ {30, wasm.REG_F14, -1, "F14"},
+ {31, wasm.REG_F15, -1, "F15"},
+ {32, wasm.REG_F16, -1, "F16"},
+ {33, wasm.REG_F17, -1, "F17"},
+ {34, wasm.REG_F18, -1, "F18"},
+ {35, wasm.REG_F19, -1, "F19"},
+ {36, wasm.REG_F20, -1, "F20"},
+ {37, wasm.REG_F21, -1, "F21"},
+ {38, wasm.REG_F22, -1, "F22"},
+ {39, wasm.REG_F23, -1, "F23"},
+ {40, wasm.REG_F24, -1, "F24"},
+ {41, wasm.REG_F25, -1, "F25"},
+ {42, wasm.REG_F26, -1, "F26"},
+ {43, wasm.REG_F27, -1, "F27"},
+ {44, wasm.REG_F28, -1, "F28"},
+ {45, wasm.REG_F29, -1, "F29"},
+ {46, wasm.REG_F30, -1, "F30"},
+ {47, wasm.REG_F31, -1, "F31"},
+ {48, wasm.REGSP, -1, "SP"},
+ {49, wasm.REGG, -1, "g"},
+ {50, 0, -1, "SB"},
+}
+var gpRegMaskWasm = regMask(65535)
+var fpRegMaskWasm = regMask(281474976645120)
+var fp32RegMaskWasm = regMask(4294901760)
+var fp64RegMaskWasm = regMask(281470681743360)
+var specialRegMaskWasm = regMask(0)
+var framepointerRegWasm = int8(-1)
+var linkRegWasm = int8(-1)
diff --git a/src/cmd/compile/internal/ssa/opt.go b/src/cmd/compile/internal/ssa/opt.go
new file mode 100644
index 0000000..128e614
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/opt.go
@@ -0,0 +1,10 @@
+// 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
+
+// machine-independent optimization
+func opt(f *Func) {
+ applyRewrite(f, rewriteBlockgeneric, rewriteValuegeneric, removeDeadValues)
+}
diff --git a/src/cmd/compile/internal/ssa/passbm_test.go b/src/cmd/compile/internal/ssa/passbm_test.go
new file mode 100644
index 0000000..3fd3eb5
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/passbm_test.go
@@ -0,0 +1,101 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "fmt"
+ "testing"
+)
+
+const (
+ blockCount = 1000
+ passCount = 15000
+)
+
+type passFunc func(*Func)
+
+func BenchmarkDSEPass(b *testing.B) { benchFnPass(b, dse, blockCount, genFunction) }
+func BenchmarkDSEPassBlock(b *testing.B) { benchFnBlock(b, dse, genFunction) }
+func BenchmarkCSEPass(b *testing.B) { benchFnPass(b, cse, blockCount, genFunction) }
+func BenchmarkCSEPassBlock(b *testing.B) { benchFnBlock(b, cse, genFunction) }
+func BenchmarkDeadcodePass(b *testing.B) { benchFnPass(b, deadcode, blockCount, genFunction) }
+func BenchmarkDeadcodePassBlock(b *testing.B) { benchFnBlock(b, deadcode, genFunction) }
+
+func multi(f *Func) {
+ cse(f)
+ dse(f)
+ deadcode(f)
+}
+func BenchmarkMultiPass(b *testing.B) { benchFnPass(b, multi, blockCount, genFunction) }
+func BenchmarkMultiPassBlock(b *testing.B) { benchFnBlock(b, multi, genFunction) }
+
+// benchFnPass runs passFunc b.N times across a single function.
+func benchFnPass(b *testing.B, fn passFunc, size int, bg blockGen) {
+ b.ReportAllocs()
+ c := testConfig(b)
+ fun := c.Fun("entry", bg(size)...)
+ CheckFunc(fun.f)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ fn(fun.f)
+ b.StopTimer()
+ CheckFunc(fun.f)
+ b.StartTimer()
+ }
+}
+
+// benchFnPass runs passFunc across a function with b.N blocks.
+func benchFnBlock(b *testing.B, fn passFunc, bg blockGen) {
+ b.ReportAllocs()
+ c := testConfig(b)
+ fun := c.Fun("entry", bg(b.N)...)
+ CheckFunc(fun.f)
+ b.ResetTimer()
+ for i := 0; i < passCount; i++ {
+ fn(fun.f)
+ }
+ b.StopTimer()
+}
+
+func genFunction(size int) []bloc {
+ var blocs []bloc
+ elemType := types.Types[types.TINT64]
+ ptrType := elemType.PtrTo()
+
+ valn := func(s string, m, n int) string { return fmt.Sprintf("%s%d-%d", s, m, n) }
+ blocs = append(blocs,
+ Bloc("entry",
+ Valu(valn("store", 0, 4), OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, types.Types[types.TUINTPTR], 0, nil),
+ Goto(blockn(1)),
+ ),
+ )
+ for i := 1; i < size+1; i++ {
+ blocs = append(blocs, Bloc(blockn(i),
+ Valu(valn("v", i, 0), OpConstBool, types.Types[types.TBOOL], 1, nil),
+ Valu(valn("addr", i, 1), OpAddr, ptrType, 0, nil, "sb"),
+ Valu(valn("addr", i, 2), OpAddr, ptrType, 0, nil, "sb"),
+ Valu(valn("addr", i, 3), OpAddr, ptrType, 0, nil, "sb"),
+ Valu(valn("zero", i, 1), OpZero, types.TypeMem, 8, elemType, valn("addr", i, 3),
+ valn("store", i-1, 4)),
+ Valu(valn("store", i, 1), OpStore, types.TypeMem, 0, elemType, valn("addr", i, 1),
+ valn("v", i, 0), valn("zero", i, 1)),
+ Valu(valn("store", i, 2), OpStore, types.TypeMem, 0, elemType, valn("addr", i, 2),
+ valn("v", i, 0), valn("store", i, 1)),
+ Valu(valn("store", i, 3), OpStore, types.TypeMem, 0, elemType, valn("addr", i, 1),
+ valn("v", i, 0), valn("store", i, 2)),
+ Valu(valn("store", i, 4), OpStore, types.TypeMem, 0, elemType, valn("addr", i, 3),
+ valn("v", i, 0), valn("store", i, 3)),
+ Goto(blockn(i+1))))
+ }
+
+ blocs = append(blocs,
+ Bloc(blockn(size+1), Goto("exit")),
+ Bloc("exit", Exit("store0-4")),
+ )
+
+ return blocs
+}
diff --git a/src/cmd/compile/internal/ssa/phielim.go b/src/cmd/compile/internal/ssa/phielim.go
new file mode 100644
index 0000000..761cb7a
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/phielim.go
@@ -0,0 +1,69 @@
+// 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
+
+// phielim eliminates redundant phi values from f.
+// A phi is redundant if its arguments are all equal. For
+// purposes of counting, ignore the phi itself. Both of
+// these phis are redundant:
+// v = phi(x,x,x)
+// v = phi(x,v,x,v)
+// We repeat this process to also catch situations like:
+// v = phi(x, phi(x, x), phi(x, v))
+// TODO: Can we also simplify cases like:
+// v = phi(v, w, x)
+// w = phi(v, w, x)
+// and would that be useful?
+func phielim(f *Func) {
+ for {
+ change := false
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ copyelimValue(v)
+ change = phielimValue(v) || change
+ }
+ }
+ if !change {
+ break
+ }
+ }
+}
+
+// phielimValue tries to convert the phi v to a copy.
+func phielimValue(v *Value) bool {
+ if v.Op != OpPhi {
+ return false
+ }
+
+ // If there are two distinct args of v which
+ // are not v itself, then the phi must remain.
+ // Otherwise, we can replace it with a copy.
+ var w *Value
+ for _, x := range v.Args {
+ if x == v {
+ continue
+ }
+ if x == w {
+ continue
+ }
+ if w != nil {
+ return false
+ }
+ w = x
+ }
+
+ if w == nil {
+ // v references only itself. It must be in
+ // a dead code loop. Don't bother modifying it.
+ return false
+ }
+ v.Op = OpCopy
+ v.SetArgs1(w)
+ f := v.Block.Func
+ if f.pass.debug > 0 {
+ f.Warnl(v.Pos, "eliminated phi")
+ }
+ return true
+}
diff --git a/src/cmd/compile/internal/ssa/phiopt.go b/src/cmd/compile/internal/ssa/phiopt.go
new file mode 100644
index 0000000..db7b022
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/phiopt.go
@@ -0,0 +1,176 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// phiopt eliminates boolean Phis based on the previous if.
+//
+// Main use case is to transform:
+// x := false
+// if b {
+// x = true
+// }
+// into x = b.
+//
+// In SSA code this appears as
+//
+// b0
+// If b -> b1 b2
+// b1
+// Plain -> b2
+// b2
+// x = (OpPhi (ConstBool [true]) (ConstBool [false]))
+//
+// In this case we can replace x with a copy of b.
+func phiopt(f *Func) {
+ sdom := f.Sdom()
+ for _, b := range f.Blocks {
+ if len(b.Preds) != 2 || len(b.Values) == 0 {
+ // TODO: handle more than 2 predecessors, e.g. a || b || c.
+ continue
+ }
+
+ pb0, b0 := b, b.Preds[0].b
+ for len(b0.Succs) == 1 && len(b0.Preds) == 1 {
+ pb0, b0 = b0, b0.Preds[0].b
+ }
+ if b0.Kind != BlockIf {
+ continue
+ }
+ pb1, b1 := b, b.Preds[1].b
+ for len(b1.Succs) == 1 && len(b1.Preds) == 1 {
+ pb1, b1 = b1, b1.Preds[0].b
+ }
+ if b1 != b0 {
+ continue
+ }
+ // b0 is the if block giving the boolean value.
+
+ // reverse is the predecessor from which the truth value comes.
+ var reverse int
+ if b0.Succs[0].b == pb0 && b0.Succs[1].b == pb1 {
+ reverse = 0
+ } else if b0.Succs[0].b == pb1 && b0.Succs[1].b == pb0 {
+ reverse = 1
+ } else {
+ b.Fatalf("invalid predecessors\n")
+ }
+
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ continue
+ }
+
+ // Look for conversions from bool to 0/1.
+ if v.Type.IsInteger() {
+ phioptint(v, b0, reverse)
+ }
+
+ if !v.Type.IsBoolean() {
+ continue
+ }
+
+ // Replaces
+ // if a { x = true } else { x = false } with x = a
+ // and
+ // if a { x = false } else { x = true } with x = !a
+ if v.Args[0].Op == OpConstBool && v.Args[1].Op == OpConstBool {
+ if v.Args[reverse].AuxInt != v.Args[1-reverse].AuxInt {
+ ops := [2]Op{OpNot, OpCopy}
+ v.reset(ops[v.Args[reverse].AuxInt])
+ v.AddArg(b0.Controls[0])
+ if f.pass.debug > 0 {
+ f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
+ }
+ continue
+ }
+ }
+
+ // Replaces
+ // if a { x = true } else { x = value } with x = a || value.
+ // Requires that value dominates x, meaning that regardless of a,
+ // value is always computed. This guarantees that the side effects
+ // of value are not seen if a is false.
+ if v.Args[reverse].Op == OpConstBool && v.Args[reverse].AuxInt == 1 {
+ if tmp := v.Args[1-reverse]; sdom.IsAncestorEq(tmp.Block, b) {
+ v.reset(OpOrB)
+ v.SetArgs2(b0.Controls[0], tmp)
+ if f.pass.debug > 0 {
+ f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
+ }
+ continue
+ }
+ }
+
+ // Replaces
+ // if a { x = value } else { x = false } with x = a && value.
+ // Requires that value dominates x, meaning that regardless of a,
+ // value is always computed. This guarantees that the side effects
+ // of value are not seen if a is false.
+ if v.Args[1-reverse].Op == OpConstBool && v.Args[1-reverse].AuxInt == 0 {
+ if tmp := v.Args[reverse]; sdom.IsAncestorEq(tmp.Block, b) {
+ v.reset(OpAndB)
+ v.SetArgs2(b0.Controls[0], tmp)
+ if f.pass.debug > 0 {
+ f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
+ }
+ continue
+ }
+ }
+ }
+ }
+}
+
+func phioptint(v *Value, b0 *Block, reverse int) {
+ a0 := v.Args[0]
+ a1 := v.Args[1]
+ if a0.Op != a1.Op {
+ return
+ }
+
+ switch a0.Op {
+ case OpConst8, OpConst16, OpConst32, OpConst64:
+ default:
+ return
+ }
+
+ negate := false
+ switch {
+ case a0.AuxInt == 0 && a1.AuxInt == 1:
+ negate = true
+ case a0.AuxInt == 1 && a1.AuxInt == 0:
+ default:
+ return
+ }
+
+ if reverse == 1 {
+ negate = !negate
+ }
+
+ a := b0.Controls[0]
+ if negate {
+ a = v.Block.NewValue1(v.Pos, OpNot, a.Type, a)
+ }
+ v.AddArg(a)
+
+ cvt := v.Block.NewValue1(v.Pos, OpCvtBoolToUint8, v.Block.Func.Config.Types.UInt8, a)
+ switch v.Type.Size() {
+ case 1:
+ v.reset(OpCopy)
+ case 2:
+ v.reset(OpZeroExt8to16)
+ case 4:
+ v.reset(OpZeroExt8to32)
+ case 8:
+ v.reset(OpZeroExt8to64)
+ default:
+ v.Fatalf("bad int size %d", v.Type.Size())
+ }
+ v.AddArg(cvt)
+
+ f := b0.Func
+ if f.pass.debug > 0 {
+ f.Warnl(v.Block.Pos, "converted OpPhi bool -> int%d", v.Type.Size()*8)
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/poset.go b/src/cmd/compile/internal/ssa/poset.go
new file mode 100644
index 0000000..f5a2b3a
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/poset.go
@@ -0,0 +1,1359 @@
+// Copyright 2018 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"
+ "os"
+)
+
+// If true, check poset integrity after every mutation
+var debugPoset = false
+
+const uintSize = 32 << (^uint(0) >> 32 & 1) // 32 or 64
+
+// bitset is a bit array for dense indexes.
+type bitset []uint
+
+func newBitset(n int) bitset {
+ return make(bitset, (n+uintSize-1)/uintSize)
+}
+
+func (bs bitset) Reset() {
+ for i := range bs {
+ bs[i] = 0
+ }
+}
+
+func (bs bitset) Set(idx uint32) {
+ bs[idx/uintSize] |= 1 << (idx % uintSize)
+}
+
+func (bs bitset) Clear(idx uint32) {
+ bs[idx/uintSize] &^= 1 << (idx % uintSize)
+}
+
+func (bs bitset) Test(idx uint32) bool {
+ return bs[idx/uintSize]&(1<<(idx%uintSize)) != 0
+}
+
+type undoType uint8
+
+const (
+ undoInvalid undoType = iota
+ undoCheckpoint // a checkpoint to group undo passes
+ undoSetChl // change back left child of undo.idx to undo.edge
+ undoSetChr // change back right child of undo.idx to undo.edge
+ undoNonEqual // forget that SSA value undo.ID is non-equal to undo.idx (another ID)
+ undoNewNode // remove new node created for SSA value undo.ID
+ undoNewConstant // remove the constant node idx from the constants map
+ undoAliasNode // unalias SSA value undo.ID so that it points back to node index undo.idx
+ undoNewRoot // remove node undo.idx from root list
+ undoChangeRoot // remove node undo.idx from root list, and put back undo.edge.Target instead
+ undoMergeRoot // remove node undo.idx from root list, and put back its children instead
+)
+
+// posetUndo represents an undo pass to be performed.
+// It's an union of fields that can be used to store information,
+// and typ is the discriminant, that specifies which kind
+// of operation must be performed. Not all fields are always used.
+type posetUndo struct {
+ typ undoType
+ idx uint32
+ ID ID
+ edge posetEdge
+}
+
+const (
+ // Make poset handle constants as unsigned numbers.
+ posetFlagUnsigned = 1 << iota
+)
+
+// A poset edge. The zero value is the null/empty edge.
+// Packs target node index (31 bits) and strict flag (1 bit).
+type posetEdge uint32
+
+func newedge(t uint32, strict bool) posetEdge {
+ s := uint32(0)
+ if strict {
+ s = 1
+ }
+ return posetEdge(t<<1 | s)
+}
+func (e posetEdge) Target() uint32 { return uint32(e) >> 1 }
+func (e posetEdge) Strict() bool { return uint32(e)&1 != 0 }
+func (e posetEdge) String() string {
+ s := fmt.Sprint(e.Target())
+ if e.Strict() {
+ s += "*"
+ }
+ return s
+}
+
+// posetNode is a node of a DAG within the poset.
+type posetNode struct {
+ l, r posetEdge
+}
+
+// poset is a union-find data structure that can represent a partially ordered set
+// of SSA values. Given a binary relation that creates a partial order (eg: '<'),
+// clients can record relations between SSA values using SetOrder, and later
+// check relations (in the transitive closure) with Ordered. For instance,
+// if SetOrder is called to record that A<B and B<C, Ordered will later confirm
+// that A<C.
+//
+// It is possible to record equality relations between SSA values with SetEqual and check
+// equality with Equal. Equality propagates into the transitive closure for the partial
+// order so that if we know that A<B<C and later learn that A==D, Ordered will return
+// true for D<C.
+//
+// It is also possible to record inequality relations between nodes with SetNonEqual;
+// non-equality relations are not transitive, but they can still be useful: for instance
+// if we know that A<=B and later we learn that A!=B, we can deduce that A<B.
+// NonEqual can be used to check whether it is known that the nodes are different, either
+// because SetNonEqual was called before, or because we know that they are strictly ordered.
+//
+// poset will refuse to record new relations that contradict existing relations:
+// for instance if A<B<C, calling SetOrder for C<A will fail returning false; also
+// calling SetEqual for C==A will fail.
+//
+// poset is implemented as a forest of DAGs; in each DAG, if there is a path (directed)
+// from node A to B, it means that A<B (or A<=B). Equality is represented by mapping
+// two SSA values to the same DAG node; when a new equality relation is recorded
+// between two existing nodes,the nodes are merged, adjusting incoming and outgoing edges.
+//
+// Constants are specially treated. When a constant is added to the poset, it is
+// immediately linked to other constants already present; so for instance if the
+// poset knows that x<=3, and then x is tested against 5, 5 is first added and linked
+// 3 (using 3<5), so that the poset knows that x<=3<5; at that point, it is able
+// to answer x<5 correctly. This means that all constants are always within the same
+// DAG; as an implementation detail, we enfoce that the DAG containtining the constants
+// is always the first in the forest.
+//
+// poset is designed to be memory efficient and do little allocations during normal usage.
+// Most internal data structures are pre-allocated and flat, so for instance adding a
+// new relation does not cause any allocation. For performance reasons,
+// each node has only up to two outgoing edges (like a binary tree), so intermediate
+// "dummy" nodes are required to represent more than two relations. For instance,
+// to record that A<I, A<J, A<K (with no known relation between I,J,K), we create the
+// following DAG:
+//
+// A
+// / \
+// I dummy
+// / \
+// J K
+//
+type poset struct {
+ lastidx uint32 // last generated dense index
+ flags uint8 // internal flags
+ values map[ID]uint32 // map SSA values to dense indexes
+ constants map[int64]uint32 // record SSA constants together with their value
+ nodes []posetNode // nodes (in all DAGs)
+ roots []uint32 // list of root nodes (forest)
+ noneq map[uint32]bitset // non-equal relations
+ undo []posetUndo // undo chain
+}
+
+func newPoset() *poset {
+ return &poset{
+ values: make(map[ID]uint32),
+ constants: make(map[int64]uint32, 8),
+ nodes: make([]posetNode, 1, 16),
+ roots: make([]uint32, 0, 4),
+ noneq: make(map[uint32]bitset),
+ undo: make([]posetUndo, 0, 4),
+ }
+}
+
+func (po *poset) SetUnsigned(uns bool) {
+ if uns {
+ po.flags |= posetFlagUnsigned
+ } else {
+ po.flags &^= posetFlagUnsigned
+ }
+}
+
+// Handle children
+func (po *poset) setchl(i uint32, l posetEdge) { po.nodes[i].l = l }
+func (po *poset) setchr(i uint32, r posetEdge) { po.nodes[i].r = r }
+func (po *poset) chl(i uint32) uint32 { return po.nodes[i].l.Target() }
+func (po *poset) chr(i uint32) uint32 { return po.nodes[i].r.Target() }
+func (po *poset) children(i uint32) (posetEdge, posetEdge) {
+ return po.nodes[i].l, po.nodes[i].r
+}
+
+// upush records a new undo step. It can be used for simple
+// undo passes that record up to one index and one edge.
+func (po *poset) upush(typ undoType, p uint32, e posetEdge) {
+ po.undo = append(po.undo, posetUndo{typ: typ, idx: p, edge: e})
+}
+
+// upushnew pushes an undo pass for a new node
+func (po *poset) upushnew(id ID, idx uint32) {
+ po.undo = append(po.undo, posetUndo{typ: undoNewNode, ID: id, idx: idx})
+}
+
+// upushneq pushes a new undo pass for a nonequal relation
+func (po *poset) upushneq(idx1 uint32, idx2 uint32) {
+ po.undo = append(po.undo, posetUndo{typ: undoNonEqual, ID: ID(idx1), idx: idx2})
+}
+
+// upushalias pushes a new undo pass for aliasing two nodes
+func (po *poset) upushalias(id ID, i2 uint32) {
+ po.undo = append(po.undo, posetUndo{typ: undoAliasNode, ID: id, idx: i2})
+}
+
+// upushconst pushes a new undo pass for a new constant
+func (po *poset) upushconst(idx uint32, old uint32) {
+ po.undo = append(po.undo, posetUndo{typ: undoNewConstant, idx: idx, ID: ID(old)})
+}
+
+// addchild adds i2 as direct child of i1.
+func (po *poset) addchild(i1, i2 uint32, strict bool) {
+ i1l, i1r := po.children(i1)
+ e2 := newedge(i2, strict)
+
+ if i1l == 0 {
+ po.setchl(i1, e2)
+ po.upush(undoSetChl, i1, 0)
+ } else if i1r == 0 {
+ po.setchr(i1, e2)
+ po.upush(undoSetChr, i1, 0)
+ } else {
+ // If n1 already has two children, add an intermediate dummy
+ // node to record the relation correctly (without relating
+ // n2 to other existing nodes). Use a non-deterministic value
+ // to decide whether to append on the left or the right, to avoid
+ // creating degenerated chains.
+ //
+ // n1
+ // / \
+ // i1l dummy
+ // / \
+ // i1r n2
+ //
+ dummy := po.newnode(nil)
+ if (i1^i2)&1 != 0 { // non-deterministic
+ po.setchl(dummy, i1r)
+ po.setchr(dummy, e2)
+ po.setchr(i1, newedge(dummy, false))
+ po.upush(undoSetChr, i1, i1r)
+ } else {
+ po.setchl(dummy, i1l)
+ po.setchr(dummy, e2)
+ po.setchl(i1, newedge(dummy, false))
+ po.upush(undoSetChl, i1, i1l)
+ }
+ }
+}
+
+// newnode allocates a new node bound to SSA value n.
+// If n is nil, this is a dummy node (= only used internally).
+func (po *poset) newnode(n *Value) uint32 {
+ i := po.lastidx + 1
+ po.lastidx++
+ po.nodes = append(po.nodes, posetNode{})
+ if n != nil {
+ if po.values[n.ID] != 0 {
+ panic("newnode for Value already inserted")
+ }
+ po.values[n.ID] = i
+ po.upushnew(n.ID, i)
+ } else {
+ po.upushnew(0, i)
+ }
+ return i
+}
+
+// lookup searches for a SSA value into the forest of DAGS, and return its node.
+// Constants are materialized on the fly during lookup.
+func (po *poset) lookup(n *Value) (uint32, bool) {
+ i, f := po.values[n.ID]
+ if !f && n.isGenericIntConst() {
+ po.newconst(n)
+ i, f = po.values[n.ID]
+ }
+ return i, f
+}
+
+// newconst creates a node for a constant. It links it to other constants, so
+// that n<=5 is detected true when n<=3 is known to be true.
+// TODO: this is O(N), fix it.
+func (po *poset) newconst(n *Value) {
+ if !n.isGenericIntConst() {
+ panic("newconst on non-constant")
+ }
+
+ // If the same constant is already present in the poset through a different
+ // Value, just alias to it without allocating a new node.
+ val := n.AuxInt
+ if po.flags&posetFlagUnsigned != 0 {
+ val = int64(n.AuxUnsigned())
+ }
+ if c, found := po.constants[val]; found {
+ po.values[n.ID] = c
+ po.upushalias(n.ID, 0)
+ return
+ }
+
+ // Create the new node for this constant
+ i := po.newnode(n)
+
+ // If this is the first constant, put it as a new root, as
+ // we can't record an existing connection so we don't have
+ // a specific DAG to add it to. Notice that we want all
+ // constants to be in root #0, so make sure the new root
+ // goes there.
+ if len(po.constants) == 0 {
+ idx := len(po.roots)
+ po.roots = append(po.roots, i)
+ po.roots[0], po.roots[idx] = po.roots[idx], po.roots[0]
+ po.upush(undoNewRoot, i, 0)
+ po.constants[val] = i
+ po.upushconst(i, 0)
+ return
+ }
+
+ // Find the lower and upper bound among existing constants. That is,
+ // find the higher constant that is lower than the one that we're adding,
+ // and the lower constant that is higher.
+ // The loop is duplicated to handle signed and unsigned comparison,
+ // depending on how the poset was configured.
+ var lowerptr, higherptr uint32
+
+ if po.flags&posetFlagUnsigned != 0 {
+ var lower, higher uint64
+ val1 := n.AuxUnsigned()
+ for val2, ptr := range po.constants {
+ val2 := uint64(val2)
+ if val1 == val2 {
+ panic("unreachable")
+ }
+ if val2 < val1 && (lowerptr == 0 || val2 > lower) {
+ lower = val2
+ lowerptr = ptr
+ } else if val2 > val1 && (higherptr == 0 || val2 < higher) {
+ higher = val2
+ higherptr = ptr
+ }
+ }
+ } else {
+ var lower, higher int64
+ val1 := n.AuxInt
+ for val2, ptr := range po.constants {
+ if val1 == val2 {
+ panic("unreachable")
+ }
+ if val2 < val1 && (lowerptr == 0 || val2 > lower) {
+ lower = val2
+ lowerptr = ptr
+ } else if val2 > val1 && (higherptr == 0 || val2 < higher) {
+ higher = val2
+ higherptr = ptr
+ }
+ }
+ }
+
+ if lowerptr == 0 && higherptr == 0 {
+ // This should not happen, as at least one
+ // other constant must exist if we get here.
+ panic("no constant found")
+ }
+
+ // Create the new node and connect it to the bounds, so that
+ // lower < n < higher. We could have found both bounds or only one
+ // of them, depending on what other constants are present in the poset.
+ // Notice that we always link constants together, so they
+ // are always part of the same DAG.
+ switch {
+ case lowerptr != 0 && higherptr != 0:
+ // Both bounds are present, record lower < n < higher.
+ po.addchild(lowerptr, i, true)
+ po.addchild(i, higherptr, true)
+
+ case lowerptr != 0:
+ // Lower bound only, record lower < n.
+ po.addchild(lowerptr, i, true)
+
+ case higherptr != 0:
+ // Higher bound only. To record n < higher, we need
+ // a dummy root:
+ //
+ // dummy
+ // / \
+ // root \
+ // / n
+ // .... /
+ // \ /
+ // higher
+ //
+ i2 := higherptr
+ r2 := po.findroot(i2)
+ if r2 != po.roots[0] { // all constants should be in root #0
+ panic("constant not in root #0")
+ }
+ dummy := po.newnode(nil)
+ po.changeroot(r2, dummy)
+ po.upush(undoChangeRoot, dummy, newedge(r2, false))
+ po.addchild(dummy, r2, false)
+ po.addchild(dummy, i, false)
+ po.addchild(i, i2, true)
+ }
+
+ po.constants[val] = i
+ po.upushconst(i, 0)
+}
+
+// aliasnewnode records that a single node n2 (not in the poset yet) is an alias
+// of the master node n1.
+func (po *poset) aliasnewnode(n1, n2 *Value) {
+ i1, i2 := po.values[n1.ID], po.values[n2.ID]
+ if i1 == 0 || i2 != 0 {
+ panic("aliasnewnode invalid arguments")
+ }
+
+ po.values[n2.ID] = i1
+ po.upushalias(n2.ID, 0)
+}
+
+// aliasnodes records that all the nodes i2s are aliases of a single master node n1.
+// aliasnodes takes care of rearranging the DAG, changing references of parent/children
+// of nodes in i2s, so that they point to n1 instead.
+// Complexity is O(n) (with n being the total number of nodes in the poset, not just
+// the number of nodes being aliased).
+func (po *poset) aliasnodes(n1 *Value, i2s bitset) {
+ i1 := po.values[n1.ID]
+ if i1 == 0 {
+ panic("aliasnode for non-existing node")
+ }
+ if i2s.Test(i1) {
+ panic("aliasnode i2s contains n1 node")
+ }
+
+ // Go through all the nodes to adjust parent/chidlren of nodes in i2s
+ for idx, n := range po.nodes {
+ // Do not touch i1 itself, otherwise we can create useless self-loops
+ if uint32(idx) == i1 {
+ continue
+ }
+ l, r := n.l, n.r
+
+ // Rename all references to i2s into i1
+ if i2s.Test(l.Target()) {
+ po.setchl(uint32(idx), newedge(i1, l.Strict()))
+ po.upush(undoSetChl, uint32(idx), l)
+ }
+ if i2s.Test(r.Target()) {
+ po.setchr(uint32(idx), newedge(i1, r.Strict()))
+ po.upush(undoSetChr, uint32(idx), r)
+ }
+
+ // Connect all chidren of i2s to i1 (unless those children
+ // are in i2s as well, in which case it would be useless)
+ if i2s.Test(uint32(idx)) {
+ if l != 0 && !i2s.Test(l.Target()) {
+ po.addchild(i1, l.Target(), l.Strict())
+ }
+ if r != 0 && !i2s.Test(r.Target()) {
+ po.addchild(i1, r.Target(), r.Strict())
+ }
+ po.setchl(uint32(idx), 0)
+ po.setchr(uint32(idx), 0)
+ po.upush(undoSetChl, uint32(idx), l)
+ po.upush(undoSetChr, uint32(idx), r)
+ }
+ }
+
+ // Reassign all existing IDs that point to i2 to i1.
+ // This includes n2.ID.
+ for k, v := range po.values {
+ if i2s.Test(v) {
+ po.values[k] = i1
+ po.upushalias(k, v)
+ }
+ }
+
+ // If one of the aliased nodes is a constant, then make sure
+ // po.constants is updated to point to the master node.
+ for val, idx := range po.constants {
+ if i2s.Test(idx) {
+ po.constants[val] = i1
+ po.upushconst(i1, idx)
+ }
+ }
+}
+
+func (po *poset) isroot(r uint32) bool {
+ for i := range po.roots {
+ if po.roots[i] == r {
+ return true
+ }
+ }
+ return false
+}
+
+func (po *poset) changeroot(oldr, newr uint32) {
+ for i := range po.roots {
+ if po.roots[i] == oldr {
+ po.roots[i] = newr
+ return
+ }
+ }
+ panic("changeroot on non-root")
+}
+
+func (po *poset) removeroot(r uint32) {
+ for i := range po.roots {
+ if po.roots[i] == r {
+ po.roots = append(po.roots[:i], po.roots[i+1:]...)
+ return
+ }
+ }
+ panic("removeroot on non-root")
+}
+
+// dfs performs a depth-first search within the DAG whose root is r.
+// f is the visit function called for each node; if it returns true,
+// the search is aborted and true is returned. The root node is
+// visited too.
+// If strict, ignore edges across a path until at least one
+// strict edge is found. For instance, for a chain A<=B<=C<D<=E<F,
+// a strict walk visits D,E,F.
+// If the visit ends, false is returned.
+func (po *poset) dfs(r uint32, strict bool, f func(i uint32) bool) bool {
+ closed := newBitset(int(po.lastidx + 1))
+ open := make([]uint32, 1, 64)
+ open[0] = r
+
+ if strict {
+ // Do a first DFS; walk all paths and stop when we find a strict
+ // edge, building a "next" list of nodes reachable through strict
+ // edges. This will be the bootstrap open list for the real DFS.
+ next := make([]uint32, 0, 64)
+
+ for len(open) > 0 {
+ i := open[len(open)-1]
+ open = open[:len(open)-1]
+
+ // Don't visit the same node twice. Notice that all nodes
+ // across non-strict paths are still visited at least once, so
+ // a non-strict path can never obscure a strict path to the
+ // same node.
+ if !closed.Test(i) {
+ closed.Set(i)
+
+ l, r := po.children(i)
+ if l != 0 {
+ if l.Strict() {
+ next = append(next, l.Target())
+ } else {
+ open = append(open, l.Target())
+ }
+ }
+ if r != 0 {
+ if r.Strict() {
+ next = append(next, r.Target())
+ } else {
+ open = append(open, r.Target())
+ }
+ }
+ }
+ }
+ open = next
+ closed.Reset()
+ }
+
+ for len(open) > 0 {
+ i := open[len(open)-1]
+ open = open[:len(open)-1]
+
+ if !closed.Test(i) {
+ if f(i) {
+ return true
+ }
+ closed.Set(i)
+ l, r := po.children(i)
+ if l != 0 {
+ open = append(open, l.Target())
+ }
+ if r != 0 {
+ open = append(open, r.Target())
+ }
+ }
+ }
+ return false
+}
+
+// Returns true if there is a path from i1 to i2.
+// If strict == true: if the function returns true, then i1 < i2.
+// If strict == false: if the function returns true, then i1 <= i2.
+// If the function returns false, no relation is known.
+func (po *poset) reaches(i1, i2 uint32, strict bool) bool {
+ return po.dfs(i1, strict, func(n uint32) bool {
+ return n == i2
+ })
+}
+
+// findroot finds i's root, that is which DAG contains i.
+// Returns the root; if i is itself a root, it is returned.
+// Panic if i is not in any DAG.
+func (po *poset) findroot(i uint32) uint32 {
+ // TODO(rasky): if needed, a way to speed up this search is
+ // storing a bitset for each root using it as a mini bloom filter
+ // of nodes present under that root.
+ for _, r := range po.roots {
+ if po.reaches(r, i, false) {
+ return r
+ }
+ }
+ panic("findroot didn't find any root")
+}
+
+// mergeroot merges two DAGs into one DAG by creating a new dummy root
+func (po *poset) mergeroot(r1, r2 uint32) uint32 {
+ // Root #0 is special as it contains all constants. Since mergeroot
+ // discards r2 as root and keeps r1, make sure that r2 is not root #0,
+ // otherwise constants would move to a different root.
+ if r2 == po.roots[0] {
+ r1, r2 = r2, r1
+ }
+ r := po.newnode(nil)
+ po.setchl(r, newedge(r1, false))
+ po.setchr(r, newedge(r2, false))
+ po.changeroot(r1, r)
+ po.removeroot(r2)
+ po.upush(undoMergeRoot, r, 0)
+ return r
+}
+
+// collapsepath marks n1 and n2 as equal and collapses as equal all
+// nodes across all paths between n1 and n2. If a strict edge is
+// found, the function does not modify the DAG and returns false.
+// Complexity is O(n).
+func (po *poset) collapsepath(n1, n2 *Value) bool {
+ i1, i2 := po.values[n1.ID], po.values[n2.ID]
+ if po.reaches(i1, i2, true) {
+ return false
+ }
+
+ // Find all the paths from i1 to i2
+ paths := po.findpaths(i1, i2)
+ // Mark all nodes in all the paths as aliases of n1
+ // (excluding n1 itself)
+ paths.Clear(i1)
+ po.aliasnodes(n1, paths)
+ return true
+}
+
+// findpaths is a recursive function that calculates all paths from cur to dst
+// and return them as a bitset (the index of a node is set in the bitset if
+// that node is on at least one path from cur to dst).
+// We do a DFS from cur (stopping going deep any time we reach dst, if ever),
+// and mark as part of the paths any node that has a children which is already
+// part of the path (or is dst itself).
+func (po *poset) findpaths(cur, dst uint32) bitset {
+ seen := newBitset(int(po.lastidx + 1))
+ path := newBitset(int(po.lastidx + 1))
+ path.Set(dst)
+ po.findpaths1(cur, dst, seen, path)
+ return path
+}
+
+func (po *poset) findpaths1(cur, dst uint32, seen bitset, path bitset) {
+ if cur == dst {
+ return
+ }
+ seen.Set(cur)
+ l, r := po.chl(cur), po.chr(cur)
+ if !seen.Test(l) {
+ po.findpaths1(l, dst, seen, path)
+ }
+ if !seen.Test(r) {
+ po.findpaths1(r, dst, seen, path)
+ }
+ if path.Test(l) || path.Test(r) {
+ path.Set(cur)
+ }
+}
+
+// Check whether it is recorded that i1!=i2
+func (po *poset) isnoneq(i1, i2 uint32) bool {
+ if i1 == i2 {
+ return false
+ }
+ if i1 < i2 {
+ i1, i2 = i2, i1
+ }
+
+ // Check if we recorded a non-equal relation before
+ if bs, ok := po.noneq[i1]; ok && bs.Test(i2) {
+ return true
+ }
+ return false
+}
+
+// Record that i1!=i2
+func (po *poset) setnoneq(n1, n2 *Value) {
+ i1, f1 := po.lookup(n1)
+ i2, f2 := po.lookup(n2)
+
+ // If any of the nodes do not exist in the poset, allocate them. Since
+ // we don't know any relation (in the partial order) about them, they must
+ // become independent roots.
+ if !f1 {
+ i1 = po.newnode(n1)
+ po.roots = append(po.roots, i1)
+ po.upush(undoNewRoot, i1, 0)
+ }
+ if !f2 {
+ i2 = po.newnode(n2)
+ po.roots = append(po.roots, i2)
+ po.upush(undoNewRoot, i2, 0)
+ }
+
+ if i1 == i2 {
+ panic("setnoneq on same node")
+ }
+ if i1 < i2 {
+ i1, i2 = i2, i1
+ }
+ bs := po.noneq[i1]
+ if bs == nil {
+ // Given that we record non-equality relations using the
+ // higher index as a key, the bitsize will never change size.
+ // TODO(rasky): if memory is a problem, consider allocating
+ // a small bitset and lazily grow it when higher indices arrive.
+ bs = newBitset(int(i1))
+ po.noneq[i1] = bs
+ } else if bs.Test(i2) {
+ // Already recorded
+ return
+ }
+ bs.Set(i2)
+ po.upushneq(i1, i2)
+}
+
+// CheckIntegrity verifies internal integrity of a poset. It is intended
+// for debugging purposes.
+func (po *poset) CheckIntegrity() {
+ // Record which index is a constant
+ constants := newBitset(int(po.lastidx + 1))
+ for _, c := range po.constants {
+ constants.Set(c)
+ }
+
+ // Verify that each node appears in a single DAG, and that
+ // all constants are within the first DAG
+ seen := newBitset(int(po.lastidx + 1))
+ for ridx, r := range po.roots {
+ if r == 0 {
+ panic("empty root")
+ }
+
+ po.dfs(r, false, func(i uint32) bool {
+ if seen.Test(i) {
+ panic("duplicate node")
+ }
+ seen.Set(i)
+ if constants.Test(i) {
+ if ridx != 0 {
+ panic("constants not in the first DAG")
+ }
+ }
+ return false
+ })
+ }
+
+ // Verify that values contain the minimum set
+ for id, idx := range po.values {
+ if !seen.Test(idx) {
+ panic(fmt.Errorf("spurious value [%d]=%d", id, idx))
+ }
+ }
+
+ // Verify that only existing nodes have non-zero children
+ for i, n := range po.nodes {
+ if n.l|n.r != 0 {
+ if !seen.Test(uint32(i)) {
+ panic(fmt.Errorf("children of unknown node %d->%v", i, n))
+ }
+ if n.l.Target() == uint32(i) || n.r.Target() == uint32(i) {
+ panic(fmt.Errorf("self-loop on node %d", i))
+ }
+ }
+ }
+}
+
+// CheckEmpty checks that a poset is completely empty.
+// It can be used for debugging purposes, as a poset is supposed to
+// be empty after it's fully rolled back through Undo.
+func (po *poset) CheckEmpty() error {
+ if len(po.nodes) != 1 {
+ return fmt.Errorf("non-empty nodes list: %v", po.nodes)
+ }
+ if len(po.values) != 0 {
+ return fmt.Errorf("non-empty value map: %v", po.values)
+ }
+ if len(po.roots) != 0 {
+ return fmt.Errorf("non-empty root list: %v", po.roots)
+ }
+ if len(po.constants) != 0 {
+ return fmt.Errorf("non-empty constants: %v", po.constants)
+ }
+ if len(po.undo) != 0 {
+ return fmt.Errorf("non-empty undo list: %v", po.undo)
+ }
+ if po.lastidx != 0 {
+ return fmt.Errorf("lastidx index is not zero: %v", po.lastidx)
+ }
+ for _, bs := range po.noneq {
+ for _, x := range bs {
+ if x != 0 {
+ return fmt.Errorf("non-empty noneq map")
+ }
+ }
+ }
+ return nil
+}
+
+// DotDump dumps the poset in graphviz format to file fn, with the specified title.
+func (po *poset) DotDump(fn string, title string) error {
+ f, err := os.Create(fn)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ // Create reverse index mapping (taking aliases into account)
+ names := make(map[uint32]string)
+ for id, i := range po.values {
+ s := names[i]
+ if s == "" {
+ s = fmt.Sprintf("v%d", id)
+ } else {
+ s += fmt.Sprintf(", v%d", id)
+ }
+ names[i] = s
+ }
+
+ // Create reverse constant mapping
+ consts := make(map[uint32]int64)
+ for val, idx := range po.constants {
+ consts[idx] = val
+ }
+
+ fmt.Fprintf(f, "digraph poset {\n")
+ fmt.Fprintf(f, "\tedge [ fontsize=10 ]\n")
+ for ridx, r := range po.roots {
+ fmt.Fprintf(f, "\tsubgraph root%d {\n", ridx)
+ po.dfs(r, false, func(i uint32) bool {
+ if val, ok := consts[i]; ok {
+ // Constant
+ var vals string
+ if po.flags&posetFlagUnsigned != 0 {
+ vals = fmt.Sprint(uint64(val))
+ } else {
+ vals = fmt.Sprint(int64(val))
+ }
+ fmt.Fprintf(f, "\t\tnode%d [shape=box style=filled fillcolor=cadetblue1 label=<%s <font point-size=\"6\">%s [%d]</font>>]\n",
+ i, vals, names[i], i)
+ } else {
+ // Normal SSA value
+ fmt.Fprintf(f, "\t\tnode%d [label=<%s <font point-size=\"6\">[%d]</font>>]\n", i, names[i], i)
+ }
+ chl, chr := po.children(i)
+ for _, ch := range []posetEdge{chl, chr} {
+ if ch != 0 {
+ if ch.Strict() {
+ fmt.Fprintf(f, "\t\tnode%d -> node%d [label=\" <\" color=\"red\"]\n", i, ch.Target())
+ } else {
+ fmt.Fprintf(f, "\t\tnode%d -> node%d [label=\" <=\" color=\"green\"]\n", i, ch.Target())
+ }
+ }
+ }
+ return false
+ })
+ fmt.Fprintf(f, "\t}\n")
+ }
+ fmt.Fprintf(f, "\tlabelloc=\"t\"\n")
+ fmt.Fprintf(f, "\tlabeldistance=\"3.0\"\n")
+ fmt.Fprintf(f, "\tlabel=%q\n", title)
+ fmt.Fprintf(f, "}\n")
+ return nil
+}
+
+// Ordered reports whether n1<n2. It returns false either when it is
+// certain that n1<n2 is false, or if there is not enough information
+// to tell.
+// Complexity is O(n).
+func (po *poset) Ordered(n1, n2 *Value) bool {
+ if debugPoset {
+ defer po.CheckIntegrity()
+ }
+ if n1.ID == n2.ID {
+ panic("should not call Ordered with n1==n2")
+ }
+
+ i1, f1 := po.lookup(n1)
+ i2, f2 := po.lookup(n2)
+ if !f1 || !f2 {
+ return false
+ }
+
+ return i1 != i2 && po.reaches(i1, i2, true)
+}
+
+// Ordered reports whether n1<=n2. It returns false either when it is
+// certain that n1<=n2 is false, or if there is not enough information
+// to tell.
+// Complexity is O(n).
+func (po *poset) OrderedOrEqual(n1, n2 *Value) bool {
+ if debugPoset {
+ defer po.CheckIntegrity()
+ }
+ if n1.ID == n2.ID {
+ panic("should not call Ordered with n1==n2")
+ }
+
+ i1, f1 := po.lookup(n1)
+ i2, f2 := po.lookup(n2)
+ if !f1 || !f2 {
+ return false
+ }
+
+ return i1 == i2 || po.reaches(i1, i2, false)
+}
+
+// Equal reports whether n1==n2. It returns false either when it is
+// certain that n1==n2 is false, or if there is not enough information
+// to tell.
+// Complexity is O(1).
+func (po *poset) Equal(n1, n2 *Value) bool {
+ if debugPoset {
+ defer po.CheckIntegrity()
+ }
+ if n1.ID == n2.ID {
+ panic("should not call Equal with n1==n2")
+ }
+
+ i1, f1 := po.lookup(n1)
+ i2, f2 := po.lookup(n2)
+ return f1 && f2 && i1 == i2
+}
+
+// NonEqual reports whether n1!=n2. It returns false either when it is
+// certain that n1!=n2 is false, or if there is not enough information
+// to tell.
+// Complexity is O(n) (because it internally calls Ordered to see if we
+// can infer n1!=n2 from n1<n2 or n2<n1).
+func (po *poset) NonEqual(n1, n2 *Value) bool {
+ if debugPoset {
+ defer po.CheckIntegrity()
+ }
+ if n1.ID == n2.ID {
+ panic("should not call NonEqual with n1==n2")
+ }
+
+ // If we never saw the nodes before, we don't
+ // have a recorded non-equality.
+ i1, f1 := po.lookup(n1)
+ i2, f2 := po.lookup(n2)
+ if !f1 || !f2 {
+ return false
+ }
+
+ // Check if we recored inequality
+ if po.isnoneq(i1, i2) {
+ return true
+ }
+
+ // Check if n1<n2 or n2<n1, in which case we can infer that n1!=n2
+ if po.Ordered(n1, n2) || po.Ordered(n2, n1) {
+ return true
+ }
+
+ return false
+}
+
+// setOrder records that n1<n2 or n1<=n2 (depending on strict). Returns false
+// if this is a contradiction.
+// Implements SetOrder() and SetOrderOrEqual()
+func (po *poset) setOrder(n1, n2 *Value, strict bool) bool {
+ i1, f1 := po.lookup(n1)
+ i2, f2 := po.lookup(n2)
+
+ switch {
+ case !f1 && !f2:
+ // Neither n1 nor n2 are in the poset, so they are not related
+ // in any way to existing nodes.
+ // Create a new DAG to record the relation.
+ i1, i2 = po.newnode(n1), po.newnode(n2)
+ po.roots = append(po.roots, i1)
+ po.upush(undoNewRoot, i1, 0)
+ po.addchild(i1, i2, strict)
+
+ case f1 && !f2:
+ // n1 is in one of the DAGs, while n2 is not. Add n2 as children
+ // of n1.
+ i2 = po.newnode(n2)
+ po.addchild(i1, i2, strict)
+
+ case !f1 && f2:
+ // n1 is not in any DAG but n2 is. If n2 is a root, we can put
+ // n1 in its place as a root; otherwise, we need to create a new
+ // dummy root to record the relation.
+ i1 = po.newnode(n1)
+
+ if po.isroot(i2) {
+ po.changeroot(i2, i1)
+ po.upush(undoChangeRoot, i1, newedge(i2, strict))
+ po.addchild(i1, i2, strict)
+ return true
+ }
+
+ // Search for i2's root; this requires a O(n) search on all
+ // DAGs
+ r := po.findroot(i2)
+
+ // Re-parent as follows:
+ //
+ // dummy
+ // r / \
+ // \ ===> r i1
+ // i2 \ /
+ // i2
+ //
+ dummy := po.newnode(nil)
+ po.changeroot(r, dummy)
+ po.upush(undoChangeRoot, dummy, newedge(r, false))
+ po.addchild(dummy, r, false)
+ po.addchild(dummy, i1, false)
+ po.addchild(i1, i2, strict)
+
+ case f1 && f2:
+ // If the nodes are aliased, fail only if we're setting a strict order
+ // (that is, we cannot set n1<n2 if n1==n2).
+ if i1 == i2 {
+ return !strict
+ }
+
+ // If we are trying to record n1<=n2 but we learned that n1!=n2,
+ // record n1<n2, as it provides more information.
+ if !strict && po.isnoneq(i1, i2) {
+ strict = true
+ }
+
+ // Both n1 and n2 are in the poset. This is the complex part of the algorithm
+ // as we need to find many different cases and DAG shapes.
+
+ // Check if n1 somehow reaches n2
+ if po.reaches(i1, i2, false) {
+ // This is the table of all cases we need to handle:
+ //
+ // DAG New Action
+ // ---------------------------------------------------
+ // #1: N1<=X<=N2 | N1<=N2 | do nothing
+ // #2: N1<=X<=N2 | N1<N2 | add strict edge (N1<N2)
+ // #3: N1<X<N2 | N1<=N2 | do nothing (we already know more)
+ // #4: N1<X<N2 | N1<N2 | do nothing
+
+ // Check if we're in case #2
+ if strict && !po.reaches(i1, i2, true) {
+ po.addchild(i1, i2, true)
+ return true
+ }
+
+ // Case #1, #3 o #4: nothing to do
+ return true
+ }
+
+ // Check if n2 somehow reaches n1
+ if po.reaches(i2, i1, false) {
+ // This is the table of all cases we need to handle:
+ //
+ // DAG New Action
+ // ---------------------------------------------------
+ // #5: N2<=X<=N1 | N1<=N2 | collapse path (learn that N1=X=N2)
+ // #6: N2<=X<=N1 | N1<N2 | contradiction
+ // #7: N2<X<N1 | N1<=N2 | contradiction in the path
+ // #8: N2<X<N1 | N1<N2 | contradiction
+
+ if strict {
+ // Cases #6 and #8: contradiction
+ return false
+ }
+
+ // We're in case #5 or #7. Try to collapse path, and that will
+ // fail if it realizes that we are in case #7.
+ return po.collapsepath(n2, n1)
+ }
+
+ // We don't know of any existing relation between n1 and n2. They could
+ // be part of the same DAG or not.
+ // Find their roots to check whether they are in the same DAG.
+ r1, r2 := po.findroot(i1), po.findroot(i2)
+ if r1 != r2 {
+ // We need to merge the two DAGs to record a relation between the nodes
+ po.mergeroot(r1, r2)
+ }
+
+ // Connect n1 and n2
+ po.addchild(i1, i2, strict)
+ }
+
+ return true
+}
+
+// SetOrder records that n1<n2. Returns false if this is a contradiction
+// Complexity is O(1) if n2 was never seen before, or O(n) otherwise.
+func (po *poset) SetOrder(n1, n2 *Value) bool {
+ if debugPoset {
+ defer po.CheckIntegrity()
+ }
+ if n1.ID == n2.ID {
+ panic("should not call SetOrder with n1==n2")
+ }
+ return po.setOrder(n1, n2, true)
+}
+
+// SetOrderOrEqual records that n1<=n2. Returns false if this is a contradiction
+// Complexity is O(1) if n2 was never seen before, or O(n) otherwise.
+func (po *poset) SetOrderOrEqual(n1, n2 *Value) bool {
+ if debugPoset {
+ defer po.CheckIntegrity()
+ }
+ if n1.ID == n2.ID {
+ panic("should not call SetOrder with n1==n2")
+ }
+ return po.setOrder(n1, n2, false)
+}
+
+// SetEqual records that n1==n2. Returns false if this is a contradiction
+// (that is, if it is already recorded that n1<n2 or n2<n1).
+// Complexity is O(1) if n2 was never seen before, or O(n) otherwise.
+func (po *poset) SetEqual(n1, n2 *Value) bool {
+ if debugPoset {
+ defer po.CheckIntegrity()
+ }
+ if n1.ID == n2.ID {
+ panic("should not call Add with n1==n2")
+ }
+
+ i1, f1 := po.lookup(n1)
+ i2, f2 := po.lookup(n2)
+
+ switch {
+ case !f1 && !f2:
+ i1 = po.newnode(n1)
+ po.roots = append(po.roots, i1)
+ po.upush(undoNewRoot, i1, 0)
+ po.aliasnewnode(n1, n2)
+ case f1 && !f2:
+ po.aliasnewnode(n1, n2)
+ case !f1 && f2:
+ po.aliasnewnode(n2, n1)
+ case f1 && f2:
+ if i1 == i2 {
+ // Already aliased, ignore
+ return true
+ }
+
+ // If we recorded that n1!=n2, this is a contradiction.
+ if po.isnoneq(i1, i2) {
+ return false
+ }
+
+ // If we already knew that n1<=n2, we can collapse the path to
+ // record n1==n2 (and viceversa).
+ if po.reaches(i1, i2, false) {
+ return po.collapsepath(n1, n2)
+ }
+ if po.reaches(i2, i1, false) {
+ return po.collapsepath(n2, n1)
+ }
+
+ r1 := po.findroot(i1)
+ r2 := po.findroot(i2)
+ if r1 != r2 {
+ // Merge the two DAGs so we can record relations between the nodes
+ po.mergeroot(r1, r2)
+ }
+
+ // Set n2 as alias of n1. This will also update all the references
+ // to n2 to become references to n1
+ i2s := newBitset(int(po.lastidx) + 1)
+ i2s.Set(i2)
+ po.aliasnodes(n1, i2s)
+ }
+ return true
+}
+
+// SetNonEqual records that n1!=n2. Returns false if this is a contradiction
+// (that is, if it is already recorded that n1==n2).
+// Complexity is O(n).
+func (po *poset) SetNonEqual(n1, n2 *Value) bool {
+ if debugPoset {
+ defer po.CheckIntegrity()
+ }
+ if n1.ID == n2.ID {
+ panic("should not call SetNonEqual with n1==n2")
+ }
+
+ // Check whether the nodes are already in the poset
+ i1, f1 := po.lookup(n1)
+ i2, f2 := po.lookup(n2)
+
+ // If either node wasn't present, we just record the new relation
+ // and exit.
+ if !f1 || !f2 {
+ po.setnoneq(n1, n2)
+ return true
+ }
+
+ // See if we already know this, in which case there's nothing to do.
+ if po.isnoneq(i1, i2) {
+ return true
+ }
+
+ // Check if we're contradicting an existing equality relation
+ if po.Equal(n1, n2) {
+ return false
+ }
+
+ // Record non-equality
+ po.setnoneq(n1, n2)
+
+ // If we know that i1<=i2 but not i1<i2, learn that as we
+ // now know that they are not equal. Do the same for i2<=i1.
+ // Do this check only if both nodes were already in the DAG,
+ // otherwise there cannot be an existing relation.
+ if po.reaches(i1, i2, false) && !po.reaches(i1, i2, true) {
+ po.addchild(i1, i2, true)
+ }
+ if po.reaches(i2, i1, false) && !po.reaches(i2, i1, true) {
+ po.addchild(i2, i1, true)
+ }
+
+ return true
+}
+
+// Checkpoint saves the current state of the DAG so that it's possible
+// to later undo this state.
+// Complexity is O(1).
+func (po *poset) Checkpoint() {
+ po.undo = append(po.undo, posetUndo{typ: undoCheckpoint})
+}
+
+// Undo restores the state of the poset to the previous checkpoint.
+// Complexity depends on the type of operations that were performed
+// since the last checkpoint; each Set* operation creates an undo
+// pass which Undo has to revert with a worst-case complexity of O(n).
+func (po *poset) Undo() {
+ if len(po.undo) == 0 {
+ panic("empty undo stack")
+ }
+ if debugPoset {
+ defer po.CheckIntegrity()
+ }
+
+ for len(po.undo) > 0 {
+ pass := po.undo[len(po.undo)-1]
+ po.undo = po.undo[:len(po.undo)-1]
+
+ switch pass.typ {
+ case undoCheckpoint:
+ return
+
+ case undoSetChl:
+ po.setchl(pass.idx, pass.edge)
+
+ case undoSetChr:
+ po.setchr(pass.idx, pass.edge)
+
+ case undoNonEqual:
+ po.noneq[uint32(pass.ID)].Clear(pass.idx)
+
+ case undoNewNode:
+ if pass.idx != po.lastidx {
+ panic("invalid newnode index")
+ }
+ if pass.ID != 0 {
+ if po.values[pass.ID] != pass.idx {
+ panic("invalid newnode undo pass")
+ }
+ delete(po.values, pass.ID)
+ }
+ po.setchl(pass.idx, 0)
+ po.setchr(pass.idx, 0)
+ po.nodes = po.nodes[:pass.idx]
+ po.lastidx--
+
+ case undoNewConstant:
+ // FIXME: remove this O(n) loop
+ var val int64
+ var i uint32
+ for val, i = range po.constants {
+ if i == pass.idx {
+ break
+ }
+ }
+ if i != pass.idx {
+ panic("constant not found in undo pass")
+ }
+ if pass.ID == 0 {
+ delete(po.constants, val)
+ } else {
+ // Restore previous index as constant node
+ // (also restoring the invariant on correct bounds)
+ oldidx := uint32(pass.ID)
+ po.constants[val] = oldidx
+ }
+
+ case undoAliasNode:
+ ID, prev := pass.ID, pass.idx
+ cur := po.values[ID]
+ if prev == 0 {
+ // Born as an alias, die as an alias
+ delete(po.values, ID)
+ } else {
+ if cur == prev {
+ panic("invalid aliasnode undo pass")
+ }
+ // Give it back previous value
+ po.values[ID] = prev
+ }
+
+ case undoNewRoot:
+ i := pass.idx
+ l, r := po.children(i)
+ if l|r != 0 {
+ panic("non-empty root in undo newroot")
+ }
+ po.removeroot(i)
+
+ case undoChangeRoot:
+ i := pass.idx
+ l, r := po.children(i)
+ if l|r != 0 {
+ panic("non-empty root in undo changeroot")
+ }
+ po.changeroot(i, pass.edge.Target())
+
+ case undoMergeRoot:
+ i := pass.idx
+ l, r := po.children(i)
+ po.changeroot(i, l.Target())
+ po.roots = append(po.roots, r.Target())
+
+ default:
+ panic(pass.typ)
+ }
+ }
+
+ if debugPoset && po.CheckEmpty() != nil {
+ panic("poset not empty at the end of undo")
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/poset_test.go b/src/cmd/compile/internal/ssa/poset_test.go
new file mode 100644
index 0000000..a6db1d1
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/poset_test.go
@@ -0,0 +1,800 @@
+// Copyright 2018 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"
+ "testing"
+)
+
+const (
+ SetOrder = "SetOrder"
+ SetOrder_Fail = "SetOrder_Fail"
+ SetOrderOrEqual = "SetOrderOrEqual"
+ SetOrderOrEqual_Fail = "SetOrderOrEqual_Fail"
+ Ordered = "Ordered"
+ Ordered_Fail = "Ordered_Fail"
+ OrderedOrEqual = "OrderedOrEqual"
+ OrderedOrEqual_Fail = "OrderedOrEqual_Fail"
+ SetEqual = "SetEqual"
+ SetEqual_Fail = "SetEqual_Fail"
+ Equal = "Equal"
+ Equal_Fail = "Equal_Fail"
+ SetNonEqual = "SetNonEqual"
+ SetNonEqual_Fail = "SetNonEqual_Fail"
+ NonEqual = "NonEqual"
+ NonEqual_Fail = "NonEqual_Fail"
+ Checkpoint = "Checkpoint"
+ Undo = "Undo"
+)
+
+type posetTestOp struct {
+ typ string
+ a, b int
+}
+
+func vconst(i int) int {
+ if i < -128 || i >= 128 {
+ panic("invalid const")
+ }
+ return 1000 + 128 + i
+}
+
+func vconst2(i int) int {
+ if i < -128 || i >= 128 {
+ panic("invalid const")
+ }
+ return 1000 + 256 + i
+}
+
+func testPosetOps(t *testing.T, unsigned bool, ops []posetTestOp) {
+ var v [1512]*Value
+ for i := range v {
+ v[i] = new(Value)
+ v[i].ID = ID(i)
+ if i >= 1000 && i < 1256 {
+ v[i].Op = OpConst64
+ v[i].AuxInt = int64(i - 1000 - 128)
+ }
+ if i >= 1256 && i < 1512 {
+ v[i].Op = OpConst64
+ v[i].AuxInt = int64(i - 1000 - 256)
+ }
+ }
+
+ po := newPoset()
+ po.SetUnsigned(unsigned)
+ for idx, op := range ops {
+ t.Logf("op%d%v", idx, op)
+ switch op.typ {
+ case SetOrder:
+ if !po.SetOrder(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v failed", idx, op)
+ }
+ case SetOrder_Fail:
+ if po.SetOrder(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v passed", idx, op)
+ }
+ case SetOrderOrEqual:
+ if !po.SetOrderOrEqual(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v failed", idx, op)
+ }
+ case SetOrderOrEqual_Fail:
+ if po.SetOrderOrEqual(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v passed", idx, op)
+ }
+ case Ordered:
+ if !po.Ordered(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v failed", idx, op)
+ }
+ case Ordered_Fail:
+ if po.Ordered(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v passed", idx, op)
+ }
+ case OrderedOrEqual:
+ if !po.OrderedOrEqual(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v failed", idx, op)
+ }
+ case OrderedOrEqual_Fail:
+ if po.OrderedOrEqual(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v passed", idx, op)
+ }
+ case SetEqual:
+ if !po.SetEqual(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v failed", idx, op)
+ }
+ case SetEqual_Fail:
+ if po.SetEqual(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v passed", idx, op)
+ }
+ case Equal:
+ if !po.Equal(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v failed", idx, op)
+ }
+ case Equal_Fail:
+ if po.Equal(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v passed", idx, op)
+ }
+ case SetNonEqual:
+ if !po.SetNonEqual(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v failed", idx, op)
+ }
+ case SetNonEqual_Fail:
+ if po.SetNonEqual(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v passed", idx, op)
+ }
+ case NonEqual:
+ if !po.NonEqual(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v failed", idx, op)
+ }
+ case NonEqual_Fail:
+ if po.NonEqual(v[op.a], v[op.b]) {
+ t.Errorf("FAILED: op%d%v passed", idx, op)
+ }
+ case Checkpoint:
+ po.Checkpoint()
+ case Undo:
+ t.Log("Undo stack", po.undo)
+ po.Undo()
+ default:
+ panic("unimplemented")
+ }
+
+ if false {
+ po.DotDump(fmt.Sprintf("op%d.dot", idx), fmt.Sprintf("Last op: %v", op))
+ }
+
+ po.CheckIntegrity()
+ }
+
+ // Check that the poset is completely empty
+ if err := po.CheckEmpty(); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPoset(t *testing.T) {
+ testPosetOps(t, false, []posetTestOp{
+ {Ordered_Fail, 123, 124},
+
+ // Dag #0: 100<101
+ {Checkpoint, 0, 0},
+ {SetOrder, 100, 101},
+ {Ordered, 100, 101},
+ {Ordered_Fail, 101, 100},
+ {SetOrder_Fail, 101, 100},
+ {SetOrder, 100, 101}, // repeat
+ {NonEqual, 100, 101},
+ {NonEqual, 101, 100},
+ {SetEqual_Fail, 100, 101},
+
+ // Dag #1: 4<=7<12
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, 4, 7},
+ {OrderedOrEqual, 4, 7},
+ {SetOrder, 7, 12},
+ {Ordered, 7, 12},
+ {Ordered, 4, 12},
+ {Ordered_Fail, 12, 4},
+ {NonEqual, 4, 12},
+ {NonEqual, 12, 4},
+ {NonEqual_Fail, 4, 100},
+ {OrderedOrEqual, 4, 12},
+ {OrderedOrEqual_Fail, 12, 4},
+ {OrderedOrEqual, 4, 7},
+ {OrderedOrEqual_Fail, 7, 4},
+
+ // Dag #1: 1<4<=7<12
+ {Checkpoint, 0, 0},
+ {SetOrder, 1, 4},
+ {Ordered, 1, 4},
+ {Ordered, 1, 12},
+ {Ordered_Fail, 12, 1},
+
+ // Dag #1: 1<4<=7<12, 6<7
+ {Checkpoint, 0, 0},
+ {SetOrder, 6, 7},
+ {Ordered, 6, 7},
+ {Ordered, 6, 12},
+ {SetOrder_Fail, 7, 4},
+ {SetOrder_Fail, 7, 6},
+ {SetOrder_Fail, 7, 1},
+
+ // Dag #1: 1<4<=7<12, 1<6<7
+ {Checkpoint, 0, 0},
+ {Ordered_Fail, 1, 6},
+ {SetOrder, 1, 6},
+ {Ordered, 1, 6},
+ {SetOrder_Fail, 6, 1},
+
+ // Dag #1: 1<4<=7<12, 1<4<6<7
+ {Checkpoint, 0, 0},
+ {Ordered_Fail, 4, 6},
+ {Ordered_Fail, 4, 7},
+ {SetOrder, 4, 6},
+ {Ordered, 4, 6},
+ {OrderedOrEqual, 4, 6},
+ {Ordered, 4, 7},
+ {OrderedOrEqual, 4, 7},
+ {SetOrder_Fail, 6, 4},
+ {Ordered_Fail, 7, 6},
+ {Ordered_Fail, 7, 4},
+ {OrderedOrEqual_Fail, 7, 6},
+ {OrderedOrEqual_Fail, 7, 4},
+
+ // Merge: 1<4<6, 4<=7<12, 6<101
+ {Checkpoint, 0, 0},
+ {Ordered_Fail, 6, 101},
+ {SetOrder, 6, 101},
+ {Ordered, 6, 101},
+ {Ordered, 1, 101},
+
+ // Merge: 1<4<6, 4<=7<12, 6<100<101
+ {Checkpoint, 0, 0},
+ {Ordered_Fail, 6, 100},
+ {SetOrder, 6, 100},
+ {Ordered, 1, 100},
+
+ // Undo: 1<4<6<7<12, 6<101
+ {Ordered, 100, 101},
+ {Undo, 0, 0},
+ {Ordered, 100, 101},
+ {Ordered_Fail, 6, 100},
+ {Ordered, 6, 101},
+ {Ordered, 1, 101},
+
+ // Undo: 1<4<6<7<12, 100<101
+ {Undo, 0, 0},
+ {Ordered_Fail, 1, 100},
+ {Ordered_Fail, 1, 101},
+ {Ordered_Fail, 6, 100},
+ {Ordered_Fail, 6, 101},
+
+ // Merge: 1<4<6<7<12, 6<100<101
+ {Checkpoint, 0, 0},
+ {Ordered, 100, 101},
+ {SetOrder, 6, 100},
+ {Ordered, 6, 100},
+ {Ordered, 6, 101},
+ {Ordered, 1, 101},
+
+ // Undo 2 times: 1<4<7<12, 1<6<7
+ {Undo, 0, 0},
+ {Undo, 0, 0},
+ {Ordered, 1, 6},
+ {Ordered, 4, 12},
+ {Ordered_Fail, 4, 6},
+ {SetOrder_Fail, 6, 1},
+
+ // Undo 2 times: 1<4<7<12
+ {Undo, 0, 0},
+ {Undo, 0, 0},
+ {Ordered, 1, 12},
+ {Ordered, 7, 12},
+ {Ordered_Fail, 1, 6},
+ {Ordered_Fail, 6, 7},
+ {Ordered, 100, 101},
+ {Ordered_Fail, 1, 101},
+
+ // Undo: 4<7<12
+ {Undo, 0, 0},
+ {Ordered_Fail, 1, 12},
+ {Ordered_Fail, 1, 4},
+ {Ordered, 4, 12},
+ {Ordered, 100, 101},
+
+ // Undo: 100<101
+ {Undo, 0, 0},
+ {Ordered_Fail, 4, 7},
+ {Ordered_Fail, 7, 12},
+ {Ordered, 100, 101},
+
+ // Recreated DAG #1 from scratch, reusing same nodes.
+ // This also stresses that Undo has done its job correctly.
+ // DAG: 1<2<(5|6), 101<102<(105|106<107)
+ {Checkpoint, 0, 0},
+ {SetOrder, 101, 102},
+ {SetOrder, 102, 105},
+ {SetOrder, 102, 106},
+ {SetOrder, 106, 107},
+ {SetOrder, 1, 2},
+ {SetOrder, 2, 5},
+ {SetOrder, 2, 6},
+ {SetEqual_Fail, 1, 6},
+ {SetEqual_Fail, 107, 102},
+
+ // Now Set 2 == 102
+ // New DAG: (1|101)<2==102<(5|6|105|106<107)
+ {Checkpoint, 0, 0},
+ {SetEqual, 2, 102},
+ {Equal, 2, 102},
+ {SetEqual, 2, 102}, // trivially pass
+ {SetNonEqual_Fail, 2, 102}, // trivially fail
+ {Ordered, 1, 107},
+ {Ordered, 101, 6},
+ {Ordered, 101, 105},
+ {Ordered, 2, 106},
+ {Ordered, 102, 6},
+
+ // Undo SetEqual
+ {Undo, 0, 0},
+ {Equal_Fail, 2, 102},
+ {Ordered_Fail, 2, 102},
+ {Ordered_Fail, 1, 107},
+ {Ordered_Fail, 101, 6},
+ {Checkpoint, 0, 0},
+ {SetEqual, 2, 100},
+ {Ordered, 1, 107},
+ {Ordered, 100, 6},
+
+ // SetEqual with new node
+ {Undo, 0, 0},
+ {Checkpoint, 0, 0},
+ {SetEqual, 2, 400},
+ {SetEqual, 401, 2},
+ {Equal, 400, 401},
+ {Ordered, 1, 400},
+ {Ordered, 400, 6},
+ {Ordered, 1, 401},
+ {Ordered, 401, 6},
+ {Ordered_Fail, 2, 401},
+
+ // SetEqual unseen nodes and then connect
+ {Checkpoint, 0, 0},
+ {SetEqual, 500, 501},
+ {SetEqual, 102, 501},
+ {Equal, 500, 102},
+ {Ordered, 501, 106},
+ {Ordered, 100, 500},
+ {SetEqual, 500, 501},
+ {Ordered_Fail, 500, 501},
+ {Ordered_Fail, 102, 501},
+
+ // SetNonEqual relations
+ {Undo, 0, 0},
+ {Checkpoint, 0, 0},
+ {SetNonEqual, 600, 601},
+ {NonEqual, 600, 601},
+ {SetNonEqual, 601, 602},
+ {NonEqual, 601, 602},
+ {NonEqual_Fail, 600, 602}, // non-transitive
+ {SetEqual_Fail, 601, 602},
+
+ // Undo back to beginning, leave the poset empty
+ {Undo, 0, 0},
+ {Undo, 0, 0},
+ {Undo, 0, 0},
+ {Undo, 0, 0},
+ })
+}
+
+func TestPosetStrict(t *testing.T) {
+
+ testPosetOps(t, false, []posetTestOp{
+ {Checkpoint, 0, 0},
+ // Build: 20!=30, 10<20<=30<40. The 20<=30 will become 20<30.
+ {SetNonEqual, 20, 30},
+ {SetOrder, 10, 20},
+ {SetOrderOrEqual, 20, 30}, // this is affected by 20!=30
+ {SetOrder, 30, 40},
+
+ {Ordered, 10, 30},
+ {Ordered, 20, 30},
+ {Ordered, 10, 40},
+ {OrderedOrEqual, 10, 30},
+ {OrderedOrEqual, 20, 30},
+ {OrderedOrEqual, 10, 40},
+
+ {Undo, 0, 0},
+
+ // Now do the opposite: first build the DAG and then learn non-equality
+ {Checkpoint, 0, 0},
+ {SetOrder, 10, 20},
+ {SetOrderOrEqual, 20, 30}, // this is affected by 20!=30
+ {SetOrder, 30, 40},
+
+ {Ordered, 10, 30},
+ {Ordered_Fail, 20, 30},
+ {Ordered, 10, 40},
+ {OrderedOrEqual, 10, 30},
+ {OrderedOrEqual, 20, 30},
+ {OrderedOrEqual, 10, 40},
+
+ {Checkpoint, 0, 0},
+ {SetNonEqual, 20, 30},
+ {Ordered, 10, 30},
+ {Ordered, 20, 30},
+ {Ordered, 10, 40},
+ {OrderedOrEqual, 10, 30},
+ {OrderedOrEqual, 20, 30},
+ {OrderedOrEqual, 10, 40},
+ {Undo, 0, 0},
+
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, 30, 35},
+ {OrderedOrEqual, 20, 35},
+ {Ordered_Fail, 20, 35},
+ {SetNonEqual, 20, 35},
+ {Ordered, 20, 35},
+ {Undo, 0, 0},
+
+ // Learn <= and >=
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, 50, 60},
+ {SetOrderOrEqual, 60, 50},
+ {OrderedOrEqual, 50, 60},
+ {OrderedOrEqual, 60, 50},
+ {Ordered_Fail, 50, 60},
+ {Ordered_Fail, 60, 50},
+ {Equal, 50, 60},
+ {Equal, 60, 50},
+ {NonEqual_Fail, 50, 60},
+ {NonEqual_Fail, 60, 50},
+ {Undo, 0, 0},
+
+ {Undo, 0, 0},
+ })
+}
+
+func TestPosetCollapse(t *testing.T) {
+ testPosetOps(t, false, []posetTestOp{
+ {Checkpoint, 0, 0},
+ // Create a complex graph of <= relations among nodes between 10 and 25.
+ {SetOrderOrEqual, 10, 15},
+ {SetOrderOrEqual, 15, 20},
+ {SetOrderOrEqual, 20, vconst(20)},
+ {SetOrderOrEqual, vconst(20), 25},
+ {SetOrderOrEqual, 10, 12},
+ {SetOrderOrEqual, 12, 16},
+ {SetOrderOrEqual, 16, vconst(20)},
+ {SetOrderOrEqual, 10, 17},
+ {SetOrderOrEqual, 17, 25},
+ {SetOrderOrEqual, 15, 18},
+ {SetOrderOrEqual, 18, vconst(20)},
+ {SetOrderOrEqual, 15, 19},
+ {SetOrderOrEqual, 19, 25},
+
+ // These are other paths not part of the main collapsing path
+ {SetOrderOrEqual, 10, 11},
+ {SetOrderOrEqual, 11, 26},
+ {SetOrderOrEqual, 13, 25},
+ {SetOrderOrEqual, 100, 25},
+ {SetOrderOrEqual, 101, 15},
+ {SetOrderOrEqual, 102, 10},
+ {SetOrderOrEqual, 25, 103},
+ {SetOrderOrEqual, 20, 104},
+
+ {Checkpoint, 0, 0},
+ // Collapse everything by setting 10 >= 25: this should make everything equal
+ {SetOrderOrEqual, 25, 10},
+
+ // Check that all nodes are pairwise equal now
+ {Equal, 10, 12},
+ {Equal, 10, 15},
+ {Equal, 10, 16},
+ {Equal, 10, 17},
+ {Equal, 10, 18},
+ {Equal, 10, 19},
+ {Equal, 10, vconst(20)},
+ {Equal, 10, vconst2(20)},
+ {Equal, 10, 25},
+
+ {Equal, 12, 15},
+ {Equal, 12, 16},
+ {Equal, 12, 17},
+ {Equal, 12, 18},
+ {Equal, 12, 19},
+ {Equal, 12, vconst(20)},
+ {Equal, 12, vconst2(20)},
+ {Equal, 12, 25},
+
+ {Equal, 15, 16},
+ {Equal, 15, 17},
+ {Equal, 15, 18},
+ {Equal, 15, 19},
+ {Equal, 15, vconst(20)},
+ {Equal, 15, vconst2(20)},
+ {Equal, 15, 25},
+
+ {Equal, 16, 17},
+ {Equal, 16, 18},
+ {Equal, 16, 19},
+ {Equal, 16, vconst(20)},
+ {Equal, 16, vconst2(20)},
+ {Equal, 16, 25},
+
+ {Equal, 17, 18},
+ {Equal, 17, 19},
+ {Equal, 17, vconst(20)},
+ {Equal, 17, vconst2(20)},
+ {Equal, 17, 25},
+
+ {Equal, 18, 19},
+ {Equal, 18, vconst(20)},
+ {Equal, 18, vconst2(20)},
+ {Equal, 18, 25},
+
+ {Equal, 19, vconst(20)},
+ {Equal, 19, vconst2(20)},
+ {Equal, 19, 25},
+
+ {Equal, vconst(20), vconst2(20)},
+ {Equal, vconst(20), 25},
+
+ {Equal, vconst2(20), 25},
+
+ // ... but not 11/26/100/101/102, which were on a different path
+ {Equal_Fail, 10, 11},
+ {Equal_Fail, 10, 26},
+ {Equal_Fail, 10, 100},
+ {Equal_Fail, 10, 101},
+ {Equal_Fail, 10, 102},
+ {OrderedOrEqual, 10, 26},
+ {OrderedOrEqual, 25, 26},
+ {OrderedOrEqual, 13, 25},
+ {OrderedOrEqual, 13, 10},
+
+ {Undo, 0, 0},
+ {OrderedOrEqual, 10, 25},
+ {Equal_Fail, 10, 12},
+ {Equal_Fail, 10, 15},
+ {Equal_Fail, 10, 25},
+
+ {Undo, 0, 0},
+ })
+
+ testPosetOps(t, false, []posetTestOp{
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, 10, 15},
+ {SetOrderOrEqual, 15, 20},
+ {SetOrderOrEqual, 20, 25},
+ {SetOrder, 10, 16},
+ {SetOrderOrEqual, 16, 20},
+ // Check that we cannot collapse here because of the strict relation 10<16
+ {SetOrderOrEqual_Fail, 20, 10},
+ {Undo, 0, 0},
+ })
+}
+
+func TestPosetSetEqual(t *testing.T) {
+ testPosetOps(t, false, []posetTestOp{
+ // 10<=20<=30<40, 20<=100<110
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, 10, 20},
+ {SetOrderOrEqual, 20, 30},
+ {SetOrder, 30, 40},
+ {SetOrderOrEqual, 20, 100},
+ {SetOrder, 100, 110},
+ {OrderedOrEqual, 10, 30},
+ {OrderedOrEqual_Fail, 30, 10},
+ {Ordered_Fail, 10, 30},
+ {Ordered_Fail, 30, 10},
+ {Ordered, 10, 40},
+ {Ordered_Fail, 40, 10},
+
+ // Try learning 10==20.
+ {Checkpoint, 0, 0},
+ {SetEqual, 10, 20},
+ {OrderedOrEqual, 10, 20},
+ {Ordered_Fail, 10, 20},
+ {Equal, 10, 20},
+ {SetOrderOrEqual, 10, 20},
+ {SetOrderOrEqual, 20, 10},
+ {SetOrder_Fail, 10, 20},
+ {SetOrder_Fail, 20, 10},
+ {Undo, 0, 0},
+
+ // Try learning 20==10.
+ {Checkpoint, 0, 0},
+ {SetEqual, 20, 10},
+ {OrderedOrEqual, 10, 20},
+ {Ordered_Fail, 10, 20},
+ {Equal, 10, 20},
+ {Undo, 0, 0},
+
+ // Try learning 10==40 or 30==40 or 10==110.
+ {Checkpoint, 0, 0},
+ {SetEqual_Fail, 10, 40},
+ {SetEqual_Fail, 40, 10},
+ {SetEqual_Fail, 30, 40},
+ {SetEqual_Fail, 40, 30},
+ {SetEqual_Fail, 10, 110},
+ {SetEqual_Fail, 110, 10},
+ {Undo, 0, 0},
+
+ // Try learning 40==110, and then 10==40 or 10=110
+ {Checkpoint, 0, 0},
+ {SetEqual, 40, 110},
+ {SetEqual_Fail, 10, 40},
+ {SetEqual_Fail, 40, 10},
+ {SetEqual_Fail, 10, 110},
+ {SetEqual_Fail, 110, 10},
+ {Undo, 0, 0},
+
+ // Try learning 40<20 or 30<20 or 110<10
+ {Checkpoint, 0, 0},
+ {SetOrder_Fail, 40, 20},
+ {SetOrder_Fail, 30, 20},
+ {SetOrder_Fail, 110, 10},
+ {Undo, 0, 0},
+
+ // Try learning 30<=20
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, 30, 20},
+ {Equal, 30, 20},
+ {OrderedOrEqual, 30, 100},
+ {Ordered, 30, 110},
+ {Undo, 0, 0},
+
+ {Undo, 0, 0},
+ })
+}
+
+func TestPosetConst(t *testing.T) {
+ testPosetOps(t, false, []posetTestOp{
+ {Checkpoint, 0, 0},
+ {SetOrder, 1, vconst(15)},
+ {SetOrderOrEqual, 100, vconst(120)},
+ {Ordered, 1, vconst(15)},
+ {Ordered, 1, vconst(120)},
+ {OrderedOrEqual, 1, vconst(120)},
+ {OrderedOrEqual, 100, vconst(120)},
+ {Ordered_Fail, 100, vconst(15)},
+ {Ordered_Fail, vconst(15), 100},
+
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, 1, 5},
+ {SetOrderOrEqual, 5, 25},
+ {SetEqual, 20, vconst(20)},
+ {SetEqual, 25, vconst(25)},
+ {Ordered, 1, 20},
+ {Ordered, 1, vconst(30)},
+ {Undo, 0, 0},
+
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, 1, 5},
+ {SetOrderOrEqual, 5, 25},
+ {SetEqual, vconst(-20), 5},
+ {SetEqual, vconst(-25), 1},
+ {Ordered, 1, 5},
+ {Ordered, vconst(-30), 1},
+ {Undo, 0, 0},
+
+ {Checkpoint, 0, 0},
+ {SetNonEqual, 1, vconst(4)},
+ {SetNonEqual, 1, vconst(6)},
+ {NonEqual, 1, vconst(4)},
+ {NonEqual_Fail, 1, vconst(5)},
+ {NonEqual, 1, vconst(6)},
+ {Equal_Fail, 1, vconst(4)},
+ {Equal_Fail, 1, vconst(5)},
+ {Equal_Fail, 1, vconst(6)},
+ {Equal_Fail, 1, vconst(7)},
+ {Undo, 0, 0},
+
+ {Undo, 0, 0},
+ })
+
+ testPosetOps(t, true, []posetTestOp{
+ {Checkpoint, 0, 0},
+ {SetOrder, 1, vconst(15)},
+ {SetOrderOrEqual, 100, vconst(-5)}, // -5 is a very big number in unsigned
+ {Ordered, 1, vconst(15)},
+ {Ordered, 1, vconst(-5)},
+ {OrderedOrEqual, 1, vconst(-5)},
+ {OrderedOrEqual, 100, vconst(-5)},
+ {Ordered_Fail, 100, vconst(15)},
+ {Ordered_Fail, vconst(15), 100},
+
+ {Undo, 0, 0},
+ })
+
+ testPosetOps(t, false, []posetTestOp{
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, 1, vconst(3)},
+ {SetNonEqual, 1, vconst(0)},
+ {Ordered_Fail, 1, vconst(0)},
+ {Undo, 0, 0},
+ })
+
+ testPosetOps(t, false, []posetTestOp{
+ // Check relations of a constant with itself
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, vconst(3), vconst2(3)},
+ {Undo, 0, 0},
+ {Checkpoint, 0, 0},
+ {SetEqual, vconst(3), vconst2(3)},
+ {Undo, 0, 0},
+ {Checkpoint, 0, 0},
+ {SetNonEqual_Fail, vconst(3), vconst2(3)},
+ {Undo, 0, 0},
+ {Checkpoint, 0, 0},
+ {SetOrder_Fail, vconst(3), vconst2(3)},
+ {Undo, 0, 0},
+
+ // Check relations of two constants among them, using
+ // different instances of the same constant
+ {Checkpoint, 0, 0},
+ {SetOrderOrEqual, vconst(3), vconst(4)},
+ {OrderedOrEqual, vconst(3), vconst2(4)},
+ {Undo, 0, 0},
+ {Checkpoint, 0, 0},
+ {SetOrder, vconst(3), vconst(4)},
+ {Ordered, vconst(3), vconst2(4)},
+ {Undo, 0, 0},
+ {Checkpoint, 0, 0},
+ {SetEqual_Fail, vconst(3), vconst(4)},
+ {SetEqual_Fail, vconst(3), vconst2(4)},
+ {Undo, 0, 0},
+ {Checkpoint, 0, 0},
+ {NonEqual, vconst(3), vconst(4)},
+ {NonEqual, vconst(3), vconst2(4)},
+ {Undo, 0, 0},
+ {Checkpoint, 0, 0},
+ {Equal_Fail, vconst(3), vconst(4)},
+ {Equal_Fail, vconst(3), vconst2(4)},
+ {Undo, 0, 0},
+ {Checkpoint, 0, 0},
+ {SetNonEqual, vconst(3), vconst(4)},
+ {SetNonEqual, vconst(3), vconst2(4)},
+ {Undo, 0, 0},
+ })
+}
+
+func TestPosetNonEqual(t *testing.T) {
+ testPosetOps(t, false, []posetTestOp{
+ {Equal_Fail, 10, 20},
+ {NonEqual_Fail, 10, 20},
+
+ // Learn 10!=20
+ {Checkpoint, 0, 0},
+ {SetNonEqual, 10, 20},
+ {Equal_Fail, 10, 20},
+ {NonEqual, 10, 20},
+ {SetEqual_Fail, 10, 20},
+
+ // Learn again 10!=20
+ {Checkpoint, 0, 0},
+ {SetNonEqual, 10, 20},
+ {Equal_Fail, 10, 20},
+ {NonEqual, 10, 20},
+
+ // Undo. We still know 10!=20
+ {Undo, 0, 0},
+ {Equal_Fail, 10, 20},
+ {NonEqual, 10, 20},
+ {SetEqual_Fail, 10, 20},
+
+ // Undo again. Now we know nothing
+ {Undo, 0, 0},
+ {Equal_Fail, 10, 20},
+ {NonEqual_Fail, 10, 20},
+
+ // Learn 10==20
+ {Checkpoint, 0, 0},
+ {SetEqual, 10, 20},
+ {Equal, 10, 20},
+ {NonEqual_Fail, 10, 20},
+ {SetNonEqual_Fail, 10, 20},
+
+ // Learn again 10==20
+ {Checkpoint, 0, 0},
+ {SetEqual, 10, 20},
+ {Equal, 10, 20},
+ {NonEqual_Fail, 10, 20},
+ {SetNonEqual_Fail, 10, 20},
+
+ // Undo. We still know 10==20
+ {Undo, 0, 0},
+ {Equal, 10, 20},
+ {NonEqual_Fail, 10, 20},
+ {SetNonEqual_Fail, 10, 20},
+
+ // Undo. We know nothing
+ {Undo, 0, 0},
+ {Equal_Fail, 10, 20},
+ {NonEqual_Fail, 10, 20},
+ })
+}
diff --git a/src/cmd/compile/internal/ssa/print.go b/src/cmd/compile/internal/ssa/print.go
new file mode 100644
index 0000000..36f09c3
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/print.go
@@ -0,0 +1,159 @@
+// 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 (
+ "bytes"
+ "crypto/sha256"
+ "fmt"
+ "io"
+)
+
+func printFunc(f *Func) {
+ f.Logf("%s", f)
+}
+
+func hashFunc(f *Func) []byte {
+ h := sha256.New()
+ p := stringFuncPrinter{w: h}
+ fprintFunc(p, f)
+ return h.Sum(nil)
+}
+
+func (f *Func) String() string {
+ var buf bytes.Buffer
+ p := stringFuncPrinter{w: &buf}
+ fprintFunc(p, f)
+ return buf.String()
+}
+
+type funcPrinter interface {
+ header(f *Func)
+ startBlock(b *Block, reachable bool)
+ endBlock(b *Block)
+ value(v *Value, live bool)
+ startDepCycle()
+ endDepCycle()
+ named(n LocalSlot, vals []*Value)
+}
+
+type stringFuncPrinter struct {
+ w io.Writer
+}
+
+func (p stringFuncPrinter) header(f *Func) {
+ fmt.Fprint(p.w, f.Name)
+ fmt.Fprint(p.w, " ")
+ fmt.Fprintln(p.w, f.Type)
+}
+
+func (p stringFuncPrinter) startBlock(b *Block, reachable bool) {
+ fmt.Fprintf(p.w, " b%d:", b.ID)
+ if len(b.Preds) > 0 {
+ io.WriteString(p.w, " <-")
+ for _, e := range b.Preds {
+ pred := e.b
+ fmt.Fprintf(p.w, " b%d", pred.ID)
+ }
+ }
+ if !reachable {
+ fmt.Fprint(p.w, " DEAD")
+ }
+ io.WriteString(p.w, "\n")
+}
+
+func (p stringFuncPrinter) endBlock(b *Block) {
+ fmt.Fprintln(p.w, " "+b.LongString())
+}
+
+func (p stringFuncPrinter) value(v *Value, live bool) {
+ fmt.Fprint(p.w, " ")
+ //fmt.Fprint(p.w, v.Block.Func.fe.Pos(v.Pos))
+ //fmt.Fprint(p.w, ": ")
+ fmt.Fprint(p.w, v.LongString())
+ if !live {
+ fmt.Fprint(p.w, " DEAD")
+ }
+ fmt.Fprintln(p.w)
+}
+
+func (p stringFuncPrinter) startDepCycle() {
+ fmt.Fprintln(p.w, "dependency cycle!")
+}
+
+func (p stringFuncPrinter) endDepCycle() {}
+
+func (p stringFuncPrinter) named(n LocalSlot, vals []*Value) {
+ fmt.Fprintf(p.w, "name %s: %v\n", n, vals)
+}
+
+func fprintFunc(p funcPrinter, f *Func) {
+ reachable, live := findlive(f)
+ defer f.retDeadcodeLive(live)
+ p.header(f)
+ printed := make([]bool, f.NumValues())
+ for _, b := range f.Blocks {
+ p.startBlock(b, reachable[b.ID])
+
+ if f.scheduled {
+ // Order of Values has been decided - print in that order.
+ for _, v := range b.Values {
+ p.value(v, live[v.ID])
+ printed[v.ID] = true
+ }
+ p.endBlock(b)
+ continue
+ }
+
+ // print phis first since all value cycles contain a phi
+ n := 0
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ continue
+ }
+ p.value(v, live[v.ID])
+ printed[v.ID] = true
+ n++
+ }
+
+ // print rest of values in dependency order
+ for n < len(b.Values) {
+ m := n
+ outer:
+ for _, v := range b.Values {
+ if printed[v.ID] {
+ continue
+ }
+ for _, w := range v.Args {
+ // w == nil shouldn't happen, but if it does,
+ // don't panic; we'll get a better diagnosis later.
+ if w != nil && w.Block == b && !printed[w.ID] {
+ continue outer
+ }
+ }
+ p.value(v, live[v.ID])
+ printed[v.ID] = true
+ n++
+ }
+ if m == n {
+ p.startDepCycle()
+ for _, v := range b.Values {
+ if printed[v.ID] {
+ continue
+ }
+ p.value(v, live[v.ID])
+ printed[v.ID] = true
+ n++
+ }
+ p.endDepCycle()
+ }
+ }
+
+ p.endBlock(b)
+ }
+ for _, name := range f.Names {
+ p.named(name, f.NamedValues[name])
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/prove.go b/src/cmd/compile/internal/ssa/prove.go
new file mode 100644
index 0000000..8a2e7c0
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/prove.go
@@ -0,0 +1,1426 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "cmd/internal/src"
+ "fmt"
+ "math"
+)
+
+type branch int
+
+const (
+ unknown branch = iota
+ positive
+ negative
+)
+
+// relation represents the set of possible relations between
+// pairs of variables (v, w). Without a priori knowledge the
+// mask is lt | eq | gt meaning v can be less than, equal to or
+// greater than w. When the execution path branches on the condition
+// `v op w` the set of relations is updated to exclude any
+// relation not possible due to `v op w` being true (or false).
+//
+// E.g.
+//
+// r := relation(...)
+//
+// if v < w {
+// newR := r & lt
+// }
+// if v >= w {
+// newR := r & (eq|gt)
+// }
+// if v != w {
+// newR := r & (lt|gt)
+// }
+type relation uint
+
+const (
+ lt relation = 1 << iota
+ eq
+ gt
+)
+
+var relationStrings = [...]string{
+ 0: "none", lt: "<", eq: "==", lt | eq: "<=",
+ gt: ">", gt | lt: "!=", gt | eq: ">=", gt | eq | lt: "any",
+}
+
+func (r relation) String() string {
+ if r < relation(len(relationStrings)) {
+ return relationStrings[r]
+ }
+ return fmt.Sprintf("relation(%d)", uint(r))
+}
+
+// domain represents the domain of a variable pair in which a set
+// of relations is known. For example, relations learned for unsigned
+// pairs cannot be transferred to signed pairs because the same bit
+// representation can mean something else.
+type domain uint
+
+const (
+ signed domain = 1 << iota
+ unsigned
+ pointer
+ boolean
+)
+
+var domainStrings = [...]string{
+ "signed", "unsigned", "pointer", "boolean",
+}
+
+func (d domain) String() string {
+ s := ""
+ for i, ds := range domainStrings {
+ if d&(1<<uint(i)) != 0 {
+ if len(s) != 0 {
+ s += "|"
+ }
+ s += ds
+ d &^= 1 << uint(i)
+ }
+ }
+ if d != 0 {
+ if len(s) != 0 {
+ s += "|"
+ }
+ s += fmt.Sprintf("0x%x", uint(d))
+ }
+ return s
+}
+
+type pair struct {
+ v, w *Value // a pair of values, ordered by ID.
+ // v can be nil, to mean the zero value.
+ // for booleans the zero value (v == nil) is false.
+ d domain
+}
+
+// fact is a pair plus a relation for that pair.
+type fact struct {
+ p pair
+ r relation
+}
+
+// a limit records known upper and lower bounds for a value.
+type limit struct {
+ min, max int64 // min <= value <= max, signed
+ umin, umax uint64 // umin <= value <= umax, unsigned
+}
+
+func (l limit) String() string {
+ return fmt.Sprintf("sm,SM,um,UM=%d,%d,%d,%d", l.min, l.max, l.umin, l.umax)
+}
+
+func (l limit) intersect(l2 limit) limit {
+ if l.min < l2.min {
+ l.min = l2.min
+ }
+ if l.umin < l2.umin {
+ l.umin = l2.umin
+ }
+ if l.max > l2.max {
+ l.max = l2.max
+ }
+ if l.umax > l2.umax {
+ l.umax = l2.umax
+ }
+ return l
+}
+
+var noLimit = limit{math.MinInt64, math.MaxInt64, 0, math.MaxUint64}
+
+// a limitFact is a limit known for a particular value.
+type limitFact struct {
+ vid ID
+ limit limit
+}
+
+// factsTable keeps track of relations between pairs of values.
+//
+// The fact table logic is sound, but incomplete. Outside of a few
+// special cases, it performs no deduction or arithmetic. While there
+// are known decision procedures for this, the ad hoc approach taken
+// by the facts table is effective for real code while remaining very
+// efficient.
+type factsTable struct {
+ // unsat is true if facts contains a contradiction.
+ //
+ // Note that the factsTable logic is incomplete, so if unsat
+ // is false, the assertions in factsTable could be satisfiable
+ // *or* unsatisfiable.
+ unsat bool // true if facts contains a contradiction
+ unsatDepth int // number of unsat checkpoints
+
+ facts map[pair]relation // current known set of relation
+ stack []fact // previous sets of relations
+
+ // order is a couple of partial order sets that record information
+ // about relations between SSA values in the signed and unsigned
+ // domain.
+ orderS *poset
+ orderU *poset
+
+ // known lower and upper bounds on individual values.
+ limits map[ID]limit
+ limitStack []limitFact // previous entries
+
+ // For each slice s, a map from s to a len(s)/cap(s) value (if any)
+ // TODO: check if there are cases that matter where we have
+ // more than one len(s) for a slice. We could keep a list if necessary.
+ lens map[ID]*Value
+ caps map[ID]*Value
+
+ // zero is a zero-valued constant
+ zero *Value
+}
+
+// checkpointFact is an invalid value used for checkpointing
+// and restoring factsTable.
+var checkpointFact = fact{}
+var checkpointBound = limitFact{}
+
+func newFactsTable(f *Func) *factsTable {
+ ft := &factsTable{}
+ ft.orderS = f.newPoset()
+ ft.orderU = f.newPoset()
+ ft.orderS.SetUnsigned(false)
+ ft.orderU.SetUnsigned(true)
+ ft.facts = make(map[pair]relation)
+ ft.stack = make([]fact, 4)
+ ft.limits = make(map[ID]limit)
+ ft.limitStack = make([]limitFact, 4)
+ ft.zero = f.ConstInt64(f.Config.Types.Int64, 0)
+ return ft
+}
+
+// update updates the set of relations between v and w in domain d
+// restricting it to r.
+func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) {
+ if parent.Func.pass.debug > 2 {
+ parent.Func.Warnl(parent.Pos, "parent=%s, update %s %s %s", parent, v, w, r)
+ }
+ // No need to do anything else if we already found unsat.
+ if ft.unsat {
+ return
+ }
+
+ // Self-fact. It's wasteful to register it into the facts
+ // table, so just note whether it's satisfiable
+ if v == w {
+ if r&eq == 0 {
+ ft.unsat = true
+ }
+ return
+ }
+
+ if d == signed || d == unsigned {
+ var ok bool
+ order := ft.orderS
+ if d == unsigned {
+ order = ft.orderU
+ }
+ switch r {
+ case lt:
+ ok = order.SetOrder(v, w)
+ case gt:
+ ok = order.SetOrder(w, v)
+ case lt | eq:
+ ok = order.SetOrderOrEqual(v, w)
+ case gt | eq:
+ ok = order.SetOrderOrEqual(w, v)
+ case eq:
+ ok = order.SetEqual(v, w)
+ case lt | gt:
+ ok = order.SetNonEqual(v, w)
+ default:
+ panic("unknown relation")
+ }
+ if !ok {
+ if parent.Func.pass.debug > 2 {
+ parent.Func.Warnl(parent.Pos, "unsat %s %s %s", v, w, r)
+ }
+ ft.unsat = true
+ return
+ }
+ } else {
+ if lessByID(w, v) {
+ v, w = w, v
+ r = reverseBits[r]
+ }
+
+ p := pair{v, w, d}
+ oldR, ok := ft.facts[p]
+ if !ok {
+ if v == w {
+ oldR = eq
+ } else {
+ oldR = lt | eq | gt
+ }
+ }
+ // No changes compared to information already in facts table.
+ if oldR == r {
+ return
+ }
+ ft.stack = append(ft.stack, fact{p, oldR})
+ ft.facts[p] = oldR & r
+ // If this relation is not satisfiable, mark it and exit right away
+ if oldR&r == 0 {
+ if parent.Func.pass.debug > 2 {
+ parent.Func.Warnl(parent.Pos, "unsat %s %s %s", v, w, r)
+ }
+ ft.unsat = true
+ return
+ }
+ }
+
+ // Extract bounds when comparing against constants
+ if v.isGenericIntConst() {
+ v, w = w, v
+ r = reverseBits[r]
+ }
+ if v != nil && w.isGenericIntConst() {
+ // Note: all the +1/-1 below could overflow/underflow. Either will
+ // still generate correct results, it will just lead to imprecision.
+ // In fact if there is overflow/underflow, the corresponding
+ // code is unreachable because the known range is outside the range
+ // of the value's type.
+ old, ok := ft.limits[v.ID]
+ if !ok {
+ old = noLimit
+ if v.isGenericIntConst() {
+ switch d {
+ case signed:
+ old.min, old.max = v.AuxInt, v.AuxInt
+ if v.AuxInt >= 0 {
+ old.umin, old.umax = uint64(v.AuxInt), uint64(v.AuxInt)
+ }
+ case unsigned:
+ old.umin = v.AuxUnsigned()
+ old.umax = old.umin
+ if int64(old.umin) >= 0 {
+ old.min, old.max = int64(old.umin), int64(old.umin)
+ }
+ }
+ }
+ }
+ lim := noLimit
+ switch d {
+ case signed:
+ c := w.AuxInt
+ switch r {
+ case lt:
+ lim.max = c - 1
+ case lt | eq:
+ lim.max = c
+ case gt | eq:
+ lim.min = c
+ case gt:
+ lim.min = c + 1
+ case lt | gt:
+ lim = old
+ if c == lim.min {
+ lim.min++
+ }
+ if c == lim.max {
+ lim.max--
+ }
+ case eq:
+ lim.min = c
+ lim.max = c
+ }
+ if lim.min >= 0 {
+ // int(x) >= 0 && int(x) >= N ⇒ uint(x) >= N
+ lim.umin = uint64(lim.min)
+ }
+ if lim.max != noLimit.max && old.min >= 0 && lim.max >= 0 {
+ // 0 <= int(x) <= N ⇒ 0 <= uint(x) <= N
+ // This is for a max update, so the lower bound
+ // comes from what we already know (old).
+ lim.umax = uint64(lim.max)
+ }
+ case unsigned:
+ uc := w.AuxUnsigned()
+ switch r {
+ case lt:
+ lim.umax = uc - 1
+ case lt | eq:
+ lim.umax = uc
+ case gt | eq:
+ lim.umin = uc
+ case gt:
+ lim.umin = uc + 1
+ case lt | gt:
+ lim = old
+ if uc == lim.umin {
+ lim.umin++
+ }
+ if uc == lim.umax {
+ lim.umax--
+ }
+ case eq:
+ lim.umin = uc
+ lim.umax = uc
+ }
+ // We could use the contrapositives of the
+ // signed implications to derive signed facts,
+ // but it turns out not to matter.
+ }
+ ft.limitStack = append(ft.limitStack, limitFact{v.ID, old})
+ lim = old.intersect(lim)
+ ft.limits[v.ID] = lim
+ if v.Block.Func.pass.debug > 2 {
+ v.Block.Func.Warnl(parent.Pos, "parent=%s, new limits %s %s %s %s", parent, v, w, r, lim.String())
+ }
+ if lim.min > lim.max || lim.umin > lim.umax {
+ ft.unsat = true
+ return
+ }
+ }
+
+ // Derived facts below here are only about numbers.
+ if d != signed && d != unsigned {
+ return
+ }
+
+ // Additional facts we know given the relationship between len and cap.
+ //
+ // TODO: Since prove now derives transitive relations, it
+ // should be sufficient to learn that len(w) <= cap(w) at the
+ // beginning of prove where we look for all len/cap ops.
+ if v.Op == OpSliceLen && r&lt == 0 && ft.caps[v.Args[0].ID] != nil {
+ // len(s) > w implies cap(s) > w
+ // len(s) >= w implies cap(s) >= w
+ // len(s) == w implies cap(s) >= w
+ ft.update(parent, ft.caps[v.Args[0].ID], w, d, r|gt)
+ }
+ if w.Op == OpSliceLen && r&gt == 0 && ft.caps[w.Args[0].ID] != nil {
+ // same, length on the RHS.
+ ft.update(parent, v, ft.caps[w.Args[0].ID], d, r|lt)
+ }
+ if v.Op == OpSliceCap && r&gt == 0 && ft.lens[v.Args[0].ID] != nil {
+ // cap(s) < w implies len(s) < w
+ // cap(s) <= w implies len(s) <= w
+ // cap(s) == w implies len(s) <= w
+ ft.update(parent, ft.lens[v.Args[0].ID], w, d, r|lt)
+ }
+ if w.Op == OpSliceCap && r&lt == 0 && ft.lens[w.Args[0].ID] != nil {
+ // same, capacity on the RHS.
+ ft.update(parent, v, ft.lens[w.Args[0].ID], d, r|gt)
+ }
+
+ // Process fence-post implications.
+ //
+ // First, make the condition > or >=.
+ if r == lt || r == lt|eq {
+ v, w = w, v
+ r = reverseBits[r]
+ }
+ switch r {
+ case gt:
+ if x, delta := isConstDelta(v); x != nil && delta == 1 {
+ // x+1 > w ⇒ x >= w
+ //
+ // This is useful for eliminating the
+ // growslice branch of append.
+ ft.update(parent, x, w, d, gt|eq)
+ } else if x, delta := isConstDelta(w); x != nil && delta == -1 {
+ // v > x-1 ⇒ v >= x
+ ft.update(parent, v, x, d, gt|eq)
+ }
+ case gt | eq:
+ if x, delta := isConstDelta(v); x != nil && delta == -1 {
+ // x-1 >= w && x > min ⇒ x > w
+ //
+ // Useful for i > 0; s[i-1].
+ lim, ok := ft.limits[x.ID]
+ if ok && ((d == signed && lim.min > opMin[v.Op]) || (d == unsigned && lim.umin > 0)) {
+ ft.update(parent, x, w, d, gt)
+ }
+ } else if x, delta := isConstDelta(w); x != nil && delta == 1 {
+ // v >= x+1 && x < max ⇒ v > x
+ lim, ok := ft.limits[x.ID]
+ if ok && ((d == signed && lim.max < opMax[w.Op]) || (d == unsigned && lim.umax < opUMax[w.Op])) {
+ ft.update(parent, v, x, d, gt)
+ }
+ }
+ }
+
+ // Process: x+delta > w (with delta constant)
+ // Only signed domain for now (useful for accesses to slices in loops).
+ if r == gt || r == gt|eq {
+ if x, delta := isConstDelta(v); x != nil && d == signed {
+ if parent.Func.pass.debug > 1 {
+ parent.Func.Warnl(parent.Pos, "x+d %s w; x:%v %v delta:%v w:%v d:%v", r, x, parent.String(), delta, w.AuxInt, d)
+ }
+ if !w.isGenericIntConst() {
+ // If we know that x+delta > w but w is not constant, we can derive:
+ // if delta < 0 and x > MinInt - delta, then x > w (because x+delta cannot underflow)
+ // This is useful for loops with bounds "len(slice)-K" (delta = -K)
+ if l, has := ft.limits[x.ID]; has && delta < 0 {
+ if (x.Type.Size() == 8 && l.min >= math.MinInt64-delta) ||
+ (x.Type.Size() == 4 && l.min >= math.MinInt32-delta) {
+ ft.update(parent, x, w, signed, r)
+ }
+ }
+ } else {
+ // With w,delta constants, we want to derive: x+delta > w ⇒ x > w-delta
+ //
+ // We compute (using integers of the correct size):
+ // min = w - delta
+ // max = MaxInt - delta
+ //
+ // And we prove that:
+ // if min<max: min < x AND x <= max
+ // if min>max: min < x OR x <= max
+ //
+ // This is always correct, even in case of overflow.
+ //
+ // If the initial fact is x+delta >= w instead, the derived conditions are:
+ // if min<max: min <= x AND x <= max
+ // if min>max: min <= x OR x <= max
+ //
+ // Notice the conditions for max are still <=, as they handle overflows.
+ var min, max int64
+ var vmin, vmax *Value
+ switch x.Type.Size() {
+ case 8:
+ min = w.AuxInt - delta
+ max = int64(^uint64(0)>>1) - delta
+
+ vmin = parent.NewValue0I(parent.Pos, OpConst64, parent.Func.Config.Types.Int64, min)
+ vmax = parent.NewValue0I(parent.Pos, OpConst64, parent.Func.Config.Types.Int64, max)
+
+ case 4:
+ min = int64(int32(w.AuxInt) - int32(delta))
+ max = int64(int32(^uint32(0)>>1) - int32(delta))
+
+ vmin = parent.NewValue0I(parent.Pos, OpConst32, parent.Func.Config.Types.Int32, min)
+ vmax = parent.NewValue0I(parent.Pos, OpConst32, parent.Func.Config.Types.Int32, max)
+
+ default:
+ panic("unimplemented")
+ }
+
+ if min < max {
+ // Record that x > min and max >= x
+ ft.update(parent, x, vmin, d, r)
+ ft.update(parent, vmax, x, d, r|eq)
+ } else {
+ // We know that either x>min OR x<=max. factsTable cannot record OR conditions,
+ // so let's see if we can already prove that one of them is false, in which case
+ // the other must be true
+ if l, has := ft.limits[x.ID]; has {
+ if l.max <= min {
+ if r&eq == 0 || l.max < min {
+ // x>min (x>=min) is impossible, so it must be x<=max
+ ft.update(parent, vmax, x, d, r|eq)
+ }
+ } else if l.min > max {
+ // x<=max is impossible, so it must be x>min
+ ft.update(parent, x, vmin, d, r)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Look through value-preserving extensions.
+ // If the domain is appropriate for the pre-extension Type,
+ // repeat the update with the pre-extension Value.
+ if isCleanExt(v) {
+ switch {
+ case d == signed && v.Args[0].Type.IsSigned():
+ fallthrough
+ case d == unsigned && !v.Args[0].Type.IsSigned():
+ ft.update(parent, v.Args[0], w, d, r)
+ }
+ }
+ if isCleanExt(w) {
+ switch {
+ case d == signed && w.Args[0].Type.IsSigned():
+ fallthrough
+ case d == unsigned && !w.Args[0].Type.IsSigned():
+ ft.update(parent, v, w.Args[0], d, r)
+ }
+ }
+}
+
+var opMin = map[Op]int64{
+ OpAdd64: math.MinInt64, OpSub64: math.MinInt64,
+ OpAdd32: math.MinInt32, OpSub32: math.MinInt32,
+}
+
+var opMax = map[Op]int64{
+ OpAdd64: math.MaxInt64, OpSub64: math.MaxInt64,
+ OpAdd32: math.MaxInt32, OpSub32: math.MaxInt32,
+}
+
+var opUMax = map[Op]uint64{
+ OpAdd64: math.MaxUint64, OpSub64: math.MaxUint64,
+ OpAdd32: math.MaxUint32, OpSub32: math.MaxUint32,
+}
+
+// isNonNegative reports whether v is known to be non-negative.
+func (ft *factsTable) isNonNegative(v *Value) bool {
+ if isNonNegative(v) {
+ return true
+ }
+
+ var max int64
+ switch v.Type.Size() {
+ case 1:
+ max = math.MaxInt8
+ case 2:
+ max = math.MaxInt16
+ case 4:
+ max = math.MaxInt32
+ case 8:
+ max = math.MaxInt64
+ default:
+ panic("unexpected integer size")
+ }
+
+ // Check if the recorded limits can prove that the value is positive
+
+ if l, has := ft.limits[v.ID]; has && (l.min >= 0 || l.umax <= uint64(max)) {
+ return true
+ }
+
+ // Check if v = x+delta, and we can use x's limits to prove that it's positive
+ if x, delta := isConstDelta(v); x != nil {
+ if l, has := ft.limits[x.ID]; has {
+ if delta > 0 && l.min >= -delta && l.max <= max-delta {
+ return true
+ }
+ if delta < 0 && l.min >= -delta {
+ return true
+ }
+ }
+ }
+
+ // Check if v is a value-preserving extension of a non-negative value.
+ if isCleanExt(v) && ft.isNonNegative(v.Args[0]) {
+ return true
+ }
+
+ // Check if the signed poset can prove that the value is >= 0
+ return ft.orderS.OrderedOrEqual(ft.zero, v)
+}
+
+// checkpoint saves the current state of known relations.
+// Called when descending on a branch.
+func (ft *factsTable) checkpoint() {
+ if ft.unsat {
+ ft.unsatDepth++
+ }
+ ft.stack = append(ft.stack, checkpointFact)
+ ft.limitStack = append(ft.limitStack, checkpointBound)
+ ft.orderS.Checkpoint()
+ ft.orderU.Checkpoint()
+}
+
+// restore restores known relation to the state just
+// before the previous checkpoint.
+// Called when backing up on a branch.
+func (ft *factsTable) restore() {
+ if ft.unsatDepth > 0 {
+ ft.unsatDepth--
+ } else {
+ ft.unsat = false
+ }
+ for {
+ old := ft.stack[len(ft.stack)-1]
+ ft.stack = ft.stack[:len(ft.stack)-1]
+ if old == checkpointFact {
+ break
+ }
+ if old.r == lt|eq|gt {
+ delete(ft.facts, old.p)
+ } else {
+ ft.facts[old.p] = old.r
+ }
+ }
+ for {
+ old := ft.limitStack[len(ft.limitStack)-1]
+ ft.limitStack = ft.limitStack[:len(ft.limitStack)-1]
+ if old.vid == 0 { // checkpointBound
+ break
+ }
+ if old.limit == noLimit {
+ delete(ft.limits, old.vid)
+ } else {
+ ft.limits[old.vid] = old.limit
+ }
+ }
+ ft.orderS.Undo()
+ ft.orderU.Undo()
+}
+
+func lessByID(v, w *Value) bool {
+ if v == nil && w == nil {
+ // Should not happen, but just in case.
+ return false
+ }
+ if v == nil {
+ return true
+ }
+ return w != nil && v.ID < w.ID
+}
+
+var (
+ reverseBits = [...]relation{0, 4, 2, 6, 1, 5, 3, 7}
+
+ // maps what we learn when the positive branch is taken.
+ // For example:
+ // OpLess8: {signed, lt},
+ // v1 = (OpLess8 v2 v3).
+ // If v1 branch is taken then we learn that the rangeMask
+ // can be at most lt.
+ domainRelationTable = map[Op]struct {
+ d domain
+ r relation
+ }{
+ OpEq8: {signed | unsigned, eq},
+ OpEq16: {signed | unsigned, eq},
+ OpEq32: {signed | unsigned, eq},
+ OpEq64: {signed | unsigned, eq},
+ OpEqPtr: {pointer, eq},
+
+ OpNeq8: {signed | unsigned, lt | gt},
+ OpNeq16: {signed | unsigned, lt | gt},
+ OpNeq32: {signed | unsigned, lt | gt},
+ OpNeq64: {signed | unsigned, lt | gt},
+ OpNeqPtr: {pointer, lt | gt},
+
+ OpLess8: {signed, lt},
+ OpLess8U: {unsigned, lt},
+ OpLess16: {signed, lt},
+ OpLess16U: {unsigned, lt},
+ OpLess32: {signed, lt},
+ OpLess32U: {unsigned, lt},
+ OpLess64: {signed, lt},
+ OpLess64U: {unsigned, lt},
+
+ OpLeq8: {signed, lt | eq},
+ OpLeq8U: {unsigned, lt | eq},
+ OpLeq16: {signed, lt | eq},
+ OpLeq16U: {unsigned, lt | eq},
+ OpLeq32: {signed, lt | eq},
+ OpLeq32U: {unsigned, lt | eq},
+ OpLeq64: {signed, lt | eq},
+ OpLeq64U: {unsigned, lt | eq},
+
+ // For these ops, the negative branch is different: we can only
+ // prove signed/GE (signed/GT) if we can prove that arg0 is non-negative.
+ // See the special case in addBranchRestrictions.
+ OpIsInBounds: {signed | unsigned, lt}, // 0 <= arg0 < arg1
+ OpIsSliceInBounds: {signed | unsigned, lt | eq}, // 0 <= arg0 <= arg1
+ }
+)
+
+// prove removes redundant BlockIf branches that can be inferred
+// from previous dominating comparisons.
+//
+// By far, the most common redundant pair are generated by bounds checking.
+// For example for the code:
+//
+// a[i] = 4
+// foo(a[i])
+//
+// The compiler will generate the following code:
+//
+// if i >= len(a) {
+// panic("not in bounds")
+// }
+// a[i] = 4
+// if i >= len(a) {
+// panic("not in bounds")
+// }
+// foo(a[i])
+//
+// The second comparison i >= len(a) is clearly redundant because if the
+// else branch of the first comparison is executed, we already know that i < len(a).
+// The code for the second panic can be removed.
+//
+// prove works by finding contradictions and trimming branches whose
+// conditions are unsatisfiable given the branches leading up to them.
+// It tracks a "fact table" of branch conditions. For each branching
+// block, it asserts the branch conditions that uniquely dominate that
+// block, and then separately asserts the block's branch condition and
+// its negation. If either leads to a contradiction, it can trim that
+// successor.
+func prove(f *Func) {
+ ft := newFactsTable(f)
+ ft.checkpoint()
+
+ var lensVars map[*Block][]*Value
+
+ // Find length and capacity ops.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Uses == 0 {
+ // We don't care about dead values.
+ // (There can be some that are CSEd but not removed yet.)
+ continue
+ }
+ switch v.Op {
+ case OpStringLen:
+ ft.update(b, v, ft.zero, signed, gt|eq)
+ case OpSliceLen:
+ if ft.lens == nil {
+ ft.lens = map[ID]*Value{}
+ }
+ ft.lens[v.Args[0].ID] = v
+ ft.update(b, v, ft.zero, signed, gt|eq)
+ if v.Args[0].Op == OpSliceMake {
+ if lensVars == nil {
+ lensVars = make(map[*Block][]*Value)
+ }
+ lensVars[b] = append(lensVars[b], v)
+ }
+ case OpSliceCap:
+ if ft.caps == nil {
+ ft.caps = map[ID]*Value{}
+ }
+ ft.caps[v.Args[0].ID] = v
+ ft.update(b, v, ft.zero, signed, gt|eq)
+ if v.Args[0].Op == OpSliceMake {
+ if lensVars == nil {
+ lensVars = make(map[*Block][]*Value)
+ }
+ lensVars[b] = append(lensVars[b], v)
+ }
+ }
+ }
+ }
+
+ // Find induction variables. Currently, findIndVars
+ // is limited to one induction variable per block.
+ var indVars map[*Block]indVar
+ for _, v := range findIndVar(f) {
+ if indVars == nil {
+ indVars = make(map[*Block]indVar)
+ }
+ indVars[v.entry] = v
+ }
+
+ // current node state
+ type walkState int
+ const (
+ descend walkState = iota
+ simplify
+ )
+ // work maintains the DFS stack.
+ type bp struct {
+ block *Block // current handled block
+ state walkState // what's to do
+ }
+ work := make([]bp, 0, 256)
+ work = append(work, bp{
+ block: f.Entry,
+ state: descend,
+ })
+
+ idom := f.Idom()
+ sdom := f.Sdom()
+
+ // DFS on the dominator tree.
+ //
+ // For efficiency, we consider only the dominator tree rather
+ // than the entire flow graph. On the way down, we consider
+ // incoming branches and accumulate conditions that uniquely
+ // dominate the current block. If we discover a contradiction,
+ // we can eliminate the entire block and all of its children.
+ // On the way back up, we consider outgoing branches that
+ // haven't already been considered. This way we consider each
+ // branch condition only once.
+ for len(work) > 0 {
+ node := work[len(work)-1]
+ work = work[:len(work)-1]
+ parent := idom[node.block.ID]
+ branch := getBranch(sdom, parent, node.block)
+
+ switch node.state {
+ case descend:
+ ft.checkpoint()
+
+ // Entering the block, add the block-depending facts that we collected
+ // at the beginning: induction variables and lens/caps of slices.
+ if iv, ok := indVars[node.block]; ok {
+ addIndVarRestrictions(ft, parent, iv)
+ }
+ if lens, ok := lensVars[node.block]; ok {
+ for _, v := range lens {
+ switch v.Op {
+ case OpSliceLen:
+ ft.update(node.block, v, v.Args[0].Args[1], signed, eq)
+ case OpSliceCap:
+ ft.update(node.block, v, v.Args[0].Args[2], signed, eq)
+ }
+ }
+ }
+
+ if branch != unknown {
+ addBranchRestrictions(ft, parent, branch)
+ if ft.unsat {
+ // node.block is unreachable.
+ // Remove it and don't visit
+ // its children.
+ removeBranch(parent, branch)
+ ft.restore()
+ break
+ }
+ // Otherwise, we can now commit to
+ // taking this branch. We'll restore
+ // ft when we unwind.
+ }
+
+ // Add inductive facts for phis in this block.
+ addLocalInductiveFacts(ft, node.block)
+
+ work = append(work, bp{
+ block: node.block,
+ state: simplify,
+ })
+ for s := sdom.Child(node.block); s != nil; s = sdom.Sibling(s) {
+ work = append(work, bp{
+ block: s,
+ state: descend,
+ })
+ }
+
+ case simplify:
+ simplifyBlock(sdom, ft, node.block)
+ ft.restore()
+ }
+ }
+
+ ft.restore()
+
+ // Return the posets to the free list
+ for _, po := range []*poset{ft.orderS, ft.orderU} {
+ // Make sure it's empty as it should be. A non-empty poset
+ // might cause errors and miscompilations if reused.
+ if checkEnabled {
+ if err := po.CheckEmpty(); err != nil {
+ f.Fatalf("prove poset not empty after function %s: %v", f.Name, err)
+ }
+ }
+ f.retPoset(po)
+ }
+}
+
+// getBranch returns the range restrictions added by p
+// when reaching b. p is the immediate dominator of b.
+func getBranch(sdom SparseTree, p *Block, b *Block) branch {
+ if p == nil || p.Kind != BlockIf {
+ return unknown
+ }
+ // If p and p.Succs[0] are dominators it means that every path
+ // from entry to b passes through p and p.Succs[0]. We care that
+ // no path from entry to b passes through p.Succs[1]. If p.Succs[0]
+ // has one predecessor then (apart from the degenerate case),
+ // there is no path from entry that can reach b through p.Succs[1].
+ // TODO: how about p->yes->b->yes, i.e. a loop in yes.
+ if sdom.IsAncestorEq(p.Succs[0].b, b) && len(p.Succs[0].b.Preds) == 1 {
+ return positive
+ }
+ if sdom.IsAncestorEq(p.Succs[1].b, b) && len(p.Succs[1].b.Preds) == 1 {
+ return negative
+ }
+ return unknown
+}
+
+// addIndVarRestrictions updates the factsTables ft with the facts
+// learned from the induction variable indVar which drives the loop
+// starting in Block b.
+func addIndVarRestrictions(ft *factsTable, b *Block, iv indVar) {
+ d := signed
+ if ft.isNonNegative(iv.min) && ft.isNonNegative(iv.max) {
+ d |= unsigned
+ }
+
+ if iv.flags&indVarMinExc == 0 {
+ addRestrictions(b, ft, d, iv.min, iv.ind, lt|eq)
+ } else {
+ addRestrictions(b, ft, d, iv.min, iv.ind, lt)
+ }
+
+ if iv.flags&indVarMaxInc == 0 {
+ addRestrictions(b, ft, d, iv.ind, iv.max, lt)
+ } else {
+ addRestrictions(b, ft, d, iv.ind, iv.max, lt|eq)
+ }
+}
+
+// addBranchRestrictions updates the factsTables ft with the facts learned when
+// branching from Block b in direction br.
+func addBranchRestrictions(ft *factsTable, b *Block, br branch) {
+ c := b.Controls[0]
+ switch br {
+ case negative:
+ addRestrictions(b, ft, boolean, nil, c, eq)
+ case positive:
+ addRestrictions(b, ft, boolean, nil, c, lt|gt)
+ default:
+ panic("unknown branch")
+ }
+ if tr, has := domainRelationTable[c.Op]; has {
+ // When we branched from parent we learned a new set of
+ // restrictions. Update the factsTable accordingly.
+ d := tr.d
+ if d == signed && ft.isNonNegative(c.Args[0]) && ft.isNonNegative(c.Args[1]) {
+ d |= unsigned
+ }
+ switch c.Op {
+ case OpIsInBounds, OpIsSliceInBounds:
+ // 0 <= a0 < a1 (or 0 <= a0 <= a1)
+ //
+ // On the positive branch, we learn:
+ // signed: 0 <= a0 < a1 (or 0 <= a0 <= a1)
+ // unsigned: a0 < a1 (or a0 <= a1)
+ //
+ // On the negative branch, we learn (0 > a0 ||
+ // a0 >= a1). In the unsigned domain, this is
+ // simply a0 >= a1 (which is the reverse of the
+ // positive branch, so nothing surprising).
+ // But in the signed domain, we can't express the ||
+ // condition, so check if a0 is non-negative instead,
+ // to be able to learn something.
+ switch br {
+ case negative:
+ d = unsigned
+ if ft.isNonNegative(c.Args[0]) {
+ d |= signed
+ }
+ addRestrictions(b, ft, d, c.Args[0], c.Args[1], tr.r^(lt|gt|eq))
+ case positive:
+ addRestrictions(b, ft, signed, ft.zero, c.Args[0], lt|eq)
+ addRestrictions(b, ft, d, c.Args[0], c.Args[1], tr.r)
+ }
+ default:
+ switch br {
+ case negative:
+ addRestrictions(b, ft, d, c.Args[0], c.Args[1], tr.r^(lt|gt|eq))
+ case positive:
+ addRestrictions(b, ft, d, c.Args[0], c.Args[1], tr.r)
+ }
+ }
+
+ }
+}
+
+// addRestrictions updates restrictions from the immediate
+// dominating block (p) using r.
+func addRestrictions(parent *Block, ft *factsTable, t domain, v, w *Value, r relation) {
+ if t == 0 {
+ // Trivial case: nothing to do.
+ // Shoult not happen, but just in case.
+ return
+ }
+ for i := domain(1); i <= t; i <<= 1 {
+ if t&i == 0 {
+ continue
+ }
+ ft.update(parent, v, w, i, r)
+ }
+}
+
+// addLocalInductiveFacts adds inductive facts when visiting b, where
+// b is a join point in a loop. In contrast with findIndVar, this
+// depends on facts established for b, which is why it happens when
+// visiting b. addLocalInductiveFacts specifically targets the pattern
+// created by OFORUNTIL, which isn't detected by findIndVar.
+//
+// TODO: It would be nice to combine this with findIndVar.
+func addLocalInductiveFacts(ft *factsTable, b *Block) {
+ // This looks for a specific pattern of induction:
+ //
+ // 1. i1 = OpPhi(min, i2) in b
+ // 2. i2 = i1 + 1
+ // 3. i2 < max at exit from b.Preds[1]
+ // 4. min < max
+ //
+ // If all of these conditions are true, then i1 < max and i1 >= min.
+
+ // To ensure this is a loop header node.
+ if len(b.Preds) != 2 {
+ return
+ }
+
+ for _, i1 := range b.Values {
+ if i1.Op != OpPhi {
+ continue
+ }
+
+ // Check for conditions 1 and 2. This is easy to do
+ // and will throw out most phis.
+ min, i2 := i1.Args[0], i1.Args[1]
+ if i1q, delta := isConstDelta(i2); i1q != i1 || delta != 1 {
+ continue
+ }
+
+ // Try to prove condition 3. We can't just query the
+ // fact table for this because we don't know what the
+ // facts of b.Preds[1] are (in general, b.Preds[1] is
+ // a loop-back edge, so we haven't even been there
+ // yet). As a conservative approximation, we look for
+ // this condition in the predecessor chain until we
+ // hit a join point.
+ uniquePred := func(b *Block) *Block {
+ if len(b.Preds) == 1 {
+ return b.Preds[0].b
+ }
+ return nil
+ }
+ pred, child := b.Preds[1].b, b
+ for ; pred != nil; pred, child = uniquePred(pred), pred {
+ if pred.Kind != BlockIf {
+ continue
+ }
+ control := pred.Controls[0]
+
+ br := unknown
+ if pred.Succs[0].b == child {
+ br = positive
+ }
+ if pred.Succs[1].b == child {
+ if br != unknown {
+ continue
+ }
+ br = negative
+ }
+ if br == unknown {
+ continue
+ }
+
+ tr, has := domainRelationTable[control.Op]
+ if !has {
+ continue
+ }
+ r := tr.r
+ if br == negative {
+ // Negative branch taken to reach b.
+ // Complement the relations.
+ r = (lt | eq | gt) ^ r
+ }
+
+ // Check for i2 < max or max > i2.
+ var max *Value
+ if r == lt && control.Args[0] == i2 {
+ max = control.Args[1]
+ } else if r == gt && control.Args[1] == i2 {
+ max = control.Args[0]
+ } else {
+ continue
+ }
+
+ // Check condition 4 now that we have a
+ // candidate max. For this we can query the
+ // fact table. We "prove" min < max by showing
+ // that min >= max is unsat. (This may simply
+ // compare two constants; that's fine.)
+ ft.checkpoint()
+ ft.update(b, min, max, tr.d, gt|eq)
+ proved := ft.unsat
+ ft.restore()
+
+ if proved {
+ // We know that min <= i1 < max.
+ if b.Func.pass.debug > 0 {
+ printIndVar(b, i1, min, max, 1, 0)
+ }
+ ft.update(b, min, i1, tr.d, lt|eq)
+ ft.update(b, i1, max, tr.d, lt)
+ }
+ }
+ }
+}
+
+var ctzNonZeroOp = map[Op]Op{OpCtz8: OpCtz8NonZero, OpCtz16: OpCtz16NonZero, OpCtz32: OpCtz32NonZero, OpCtz64: OpCtz64NonZero}
+var mostNegativeDividend = map[Op]int64{
+ OpDiv16: -1 << 15,
+ OpMod16: -1 << 15,
+ OpDiv32: -1 << 31,
+ OpMod32: -1 << 31,
+ OpDiv64: -1 << 63,
+ OpMod64: -1 << 63}
+
+// simplifyBlock simplifies some constant values in b and evaluates
+// branches to non-uniquely dominated successors of b.
+func simplifyBlock(sdom SparseTree, ft *factsTable, b *Block) {
+ for _, v := range b.Values {
+ switch v.Op {
+ case OpSlicemask:
+ // Replace OpSlicemask operations in b with constants where possible.
+ x, delta := isConstDelta(v.Args[0])
+ if x == nil {
+ continue
+ }
+ // slicemask(x + y)
+ // if x is larger than -y (y is negative), then slicemask is -1.
+ lim, ok := ft.limits[x.ID]
+ if !ok {
+ continue
+ }
+ if lim.umin > uint64(-delta) {
+ if v.Args[0].Op == OpAdd64 {
+ v.reset(OpConst64)
+ } else {
+ v.reset(OpConst32)
+ }
+ if b.Func.pass.debug > 0 {
+ b.Func.Warnl(v.Pos, "Proved slicemask not needed")
+ }
+ v.AuxInt = -1
+ }
+ case OpCtz8, OpCtz16, OpCtz32, OpCtz64:
+ // On some architectures, notably amd64, we can generate much better
+ // code for CtzNN if we know that the argument is non-zero.
+ // Capture that information here for use in arch-specific optimizations.
+ x := v.Args[0]
+ lim, ok := ft.limits[x.ID]
+ if !ok {
+ continue
+ }
+ if lim.umin > 0 || lim.min > 0 || lim.max < 0 {
+ if b.Func.pass.debug > 0 {
+ b.Func.Warnl(v.Pos, "Proved %v non-zero", v.Op)
+ }
+ v.Op = ctzNonZeroOp[v.Op]
+ }
+ case OpRsh8x8, OpRsh8x16, OpRsh8x32, OpRsh8x64,
+ OpRsh16x8, OpRsh16x16, OpRsh16x32, OpRsh16x64,
+ OpRsh32x8, OpRsh32x16, OpRsh32x32, OpRsh32x64,
+ OpRsh64x8, OpRsh64x16, OpRsh64x32, OpRsh64x64:
+ // Check whether, for a >> b, we know that a is non-negative
+ // and b is all of a's bits except the MSB. If so, a is shifted to zero.
+ bits := 8 * v.Type.Size()
+ if v.Args[1].isGenericIntConst() && v.Args[1].AuxInt >= bits-1 && ft.isNonNegative(v.Args[0]) {
+ if b.Func.pass.debug > 0 {
+ b.Func.Warnl(v.Pos, "Proved %v shifts to zero", v.Op)
+ }
+ switch bits {
+ case 64:
+ v.reset(OpConst64)
+ case 32:
+ v.reset(OpConst32)
+ case 16:
+ v.reset(OpConst16)
+ case 8:
+ v.reset(OpConst8)
+ default:
+ panic("unexpected integer size")
+ }
+ v.AuxInt = 0
+ continue // Be sure not to fallthrough - this is no longer OpRsh.
+ }
+ // If the Rsh hasn't been replaced with 0, still check if it is bounded.
+ fallthrough
+ case OpLsh8x8, OpLsh8x16, OpLsh8x32, OpLsh8x64,
+ OpLsh16x8, OpLsh16x16, OpLsh16x32, OpLsh16x64,
+ OpLsh32x8, OpLsh32x16, OpLsh32x32, OpLsh32x64,
+ OpLsh64x8, OpLsh64x16, OpLsh64x32, OpLsh64x64,
+ OpRsh8Ux8, OpRsh8Ux16, OpRsh8Ux32, OpRsh8Ux64,
+ OpRsh16Ux8, OpRsh16Ux16, OpRsh16Ux32, OpRsh16Ux64,
+ OpRsh32Ux8, OpRsh32Ux16, OpRsh32Ux32, OpRsh32Ux64,
+ OpRsh64Ux8, OpRsh64Ux16, OpRsh64Ux32, OpRsh64Ux64:
+ // Check whether, for a << b, we know that b
+ // is strictly less than the number of bits in a.
+ by := v.Args[1]
+ lim, ok := ft.limits[by.ID]
+ if !ok {
+ continue
+ }
+ bits := 8 * v.Args[0].Type.Size()
+ if lim.umax < uint64(bits) || (lim.max < bits && ft.isNonNegative(by)) {
+ v.AuxInt = 1 // see shiftIsBounded
+ if b.Func.pass.debug > 0 {
+ b.Func.Warnl(v.Pos, "Proved %v bounded", v.Op)
+ }
+ }
+ case OpDiv16, OpDiv32, OpDiv64, OpMod16, OpMod32, OpMod64:
+ // On amd64 and 386 fix-up code can be avoided if we know
+ // the divisor is not -1 or the dividend > MinIntNN.
+ // Don't modify AuxInt on other architectures,
+ // as that can interfere with CSE.
+ // TODO: add other architectures?
+ if b.Func.Config.arch != "386" && b.Func.Config.arch != "amd64" {
+ break
+ }
+ divr := v.Args[1]
+ divrLim, divrLimok := ft.limits[divr.ID]
+ divd := v.Args[0]
+ divdLim, divdLimok := ft.limits[divd.ID]
+ if (divrLimok && (divrLim.max < -1 || divrLim.min > -1)) ||
+ (divdLimok && divdLim.min > mostNegativeDividend[v.Op]) {
+ // See DivisionNeedsFixUp in rewrite.go.
+ // v.AuxInt = 1 means we have proved both that the divisor is not -1
+ // and that the dividend is not the most negative integer,
+ // so we do not need to add fix-up code.
+ v.AuxInt = 1
+ if b.Func.pass.debug > 0 {
+ b.Func.Warnl(v.Pos, "Proved %v does not need fix-up", v.Op)
+ }
+ }
+ }
+ }
+
+ if b.Kind != BlockIf {
+ return
+ }
+
+ // Consider outgoing edges from this block.
+ parent := b
+ for i, branch := range [...]branch{positive, negative} {
+ child := parent.Succs[i].b
+ if getBranch(sdom, parent, child) != unknown {
+ // For edges to uniquely dominated blocks, we
+ // already did this when we visited the child.
+ continue
+ }
+ // For edges to other blocks, this can trim a branch
+ // even if we couldn't get rid of the child itself.
+ ft.checkpoint()
+ addBranchRestrictions(ft, parent, branch)
+ unsat := ft.unsat
+ ft.restore()
+ if unsat {
+ // This branch is impossible, so remove it
+ // from the block.
+ removeBranch(parent, branch)
+ // No point in considering the other branch.
+ // (It *is* possible for both to be
+ // unsatisfiable since the fact table is
+ // incomplete. We could turn this into a
+ // BlockExit, but it doesn't seem worth it.)
+ break
+ }
+ }
+}
+
+func removeBranch(b *Block, branch branch) {
+ c := b.Controls[0]
+ if b.Func.pass.debug > 0 {
+ verb := "Proved"
+ if branch == positive {
+ verb = "Disproved"
+ }
+ if b.Func.pass.debug > 1 {
+ b.Func.Warnl(b.Pos, "%s %s (%s)", verb, c.Op, c)
+ } else {
+ b.Func.Warnl(b.Pos, "%s %s", verb, c.Op)
+ }
+ }
+ if c != nil && c.Pos.IsStmt() == src.PosIsStmt && c.Pos.SameFileAndLine(b.Pos) {
+ // attempt to preserve statement marker.
+ b.Pos = b.Pos.WithIsStmt()
+ }
+ b.Kind = BlockFirst
+ b.ResetControls()
+ if branch == positive {
+ b.swapSuccessors()
+ }
+}
+
+// isNonNegative reports whether v is known to be greater or equal to zero.
+func isNonNegative(v *Value) bool {
+ if !v.Type.IsInteger() {
+ v.Fatalf("isNonNegative bad type: %v", v.Type)
+ }
+ // TODO: return true if !v.Type.IsSigned()
+ // SSA isn't type-safe enough to do that now (issue 37753).
+ // The checks below depend only on the pattern of bits.
+
+ switch v.Op {
+ case OpConst64:
+ return v.AuxInt >= 0
+
+ case OpConst32:
+ return int32(v.AuxInt) >= 0
+
+ case OpConst16:
+ return int16(v.AuxInt) >= 0
+
+ case OpConst8:
+ return int8(v.AuxInt) >= 0
+
+ case OpStringLen, OpSliceLen, OpSliceCap,
+ OpZeroExt8to64, OpZeroExt16to64, OpZeroExt32to64,
+ OpZeroExt8to32, OpZeroExt16to32, OpZeroExt8to16,
+ OpCtz64, OpCtz32, OpCtz16, OpCtz8:
+ return true
+
+ case OpRsh64Ux64, OpRsh32Ux64:
+ by := v.Args[1]
+ return by.Op == OpConst64 && by.AuxInt > 0
+
+ case OpRsh64x64, OpRsh32x64, OpRsh8x64, OpRsh16x64, OpRsh32x32, OpRsh64x32,
+ OpSignExt32to64, OpSignExt16to64, OpSignExt8to64, OpSignExt16to32, OpSignExt8to32:
+ return isNonNegative(v.Args[0])
+
+ case OpAnd64, OpAnd32, OpAnd16, OpAnd8:
+ return isNonNegative(v.Args[0]) || isNonNegative(v.Args[1])
+
+ case OpMod64, OpMod32, OpMod16, OpMod8,
+ OpDiv64, OpDiv32, OpDiv16, OpDiv8,
+ OpOr64, OpOr32, OpOr16, OpOr8,
+ OpXor64, OpXor32, OpXor16, OpXor8:
+ return isNonNegative(v.Args[0]) && isNonNegative(v.Args[1])
+
+ // We could handle OpPhi here, but the improvements from doing
+ // so are very minor, and it is neither simple nor cheap.
+ }
+ return false
+}
+
+// isConstDelta returns non-nil if v is equivalent to w+delta (signed).
+func isConstDelta(v *Value) (w *Value, delta int64) {
+ cop := OpConst64
+ switch v.Op {
+ case OpAdd32, OpSub32:
+ cop = OpConst32
+ }
+ switch v.Op {
+ case OpAdd64, OpAdd32:
+ if v.Args[0].Op == cop {
+ return v.Args[1], v.Args[0].AuxInt
+ }
+ if v.Args[1].Op == cop {
+ return v.Args[0], v.Args[1].AuxInt
+ }
+ case OpSub64, OpSub32:
+ if v.Args[1].Op == cop {
+ aux := v.Args[1].AuxInt
+ if aux != -aux { // Overflow; too bad
+ return v.Args[0], -aux
+ }
+ }
+ }
+ return nil, 0
+}
+
+// isCleanExt reports whether v is the result of a value-preserving
+// sign or zero extension
+func isCleanExt(v *Value) bool {
+ switch v.Op {
+ case OpSignExt8to16, OpSignExt8to32, OpSignExt8to64,
+ OpSignExt16to32, OpSignExt16to64, OpSignExt32to64:
+ // signed -> signed is the only value-preserving sign extension
+ return v.Args[0].Type.IsSigned() && v.Type.IsSigned()
+
+ case OpZeroExt8to16, OpZeroExt8to32, OpZeroExt8to64,
+ OpZeroExt16to32, OpZeroExt16to64, OpZeroExt32to64:
+ // unsigned -> signed/unsigned are value-preserving zero extensions
+ return !v.Args[0].Type.IsSigned()
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/redblack32.go b/src/cmd/compile/internal/ssa/redblack32.go
new file mode 100644
index 0000000..fc9cc71
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/redblack32.go
@@ -0,0 +1,429 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import "fmt"
+
+const (
+ rankLeaf rbrank = 1
+ rankZero rbrank = 0
+)
+
+type rbrank int8
+
+// RBTint32 is a red-black tree with data stored at internal nodes,
+// following Tarjan, Data Structures and Network Algorithms,
+// pp 48-52, using explicit rank instead of red and black.
+// Deletion is not yet implemented because it is not yet needed.
+// Extra operations glb, lub, glbEq, lubEq are provided for
+// use in sparse lookup algorithms.
+type RBTint32 struct {
+ root *node32
+ // An extra-clever implementation will have special cases
+ // for small sets, but we are not extra-clever today.
+}
+
+func (t *RBTint32) String() string {
+ if t.root == nil {
+ return "[]"
+ }
+ return "[" + t.root.String() + "]"
+}
+
+func (t *node32) String() string {
+ s := ""
+ if t.left != nil {
+ s = t.left.String() + " "
+ }
+ s = s + fmt.Sprintf("k=%d,d=%v", t.key, t.data)
+ if t.right != nil {
+ s = s + " " + t.right.String()
+ }
+ return s
+}
+
+type node32 struct {
+ // Standard conventions hold for left = smaller, right = larger
+ left, right, parent *node32
+ data interface{}
+ key int32
+ rank rbrank // From Tarjan pp 48-49:
+ // If x is a node with a parent, then x.rank <= x.parent.rank <= x.rank+1.
+ // If x is a node with a grandparent, then x.rank < x.parent.parent.rank.
+ // If x is an "external [null] node", then x.rank = 0 && x.parent.rank = 1.
+ // Any node with one or more null children should have rank = 1.
+}
+
+// makeNode returns a new leaf node with the given key and nil data.
+func (t *RBTint32) makeNode(key int32) *node32 {
+ return &node32{key: key, rank: rankLeaf}
+}
+
+// IsEmpty reports whether t is empty.
+func (t *RBTint32) IsEmpty() bool {
+ return t.root == nil
+}
+
+// IsSingle reports whether t is a singleton (leaf).
+func (t *RBTint32) IsSingle() bool {
+ return t.root != nil && t.root.isLeaf()
+}
+
+// VisitInOrder applies f to the key and data pairs in t,
+// with keys ordered from smallest to largest.
+func (t *RBTint32) VisitInOrder(f func(int32, interface{})) {
+ if t.root == nil {
+ return
+ }
+ t.root.visitInOrder(f)
+}
+
+func (n *node32) Data() interface{} {
+ if n == nil {
+ return nil
+ }
+ return n.data
+}
+
+func (n *node32) keyAndData() (k int32, d interface{}) {
+ if n == nil {
+ k = 0
+ d = nil
+ } else {
+ k = n.key
+ d = n.data
+ }
+ return
+}
+
+func (n *node32) Rank() rbrank {
+ if n == nil {
+ return 0
+ }
+ return n.rank
+}
+
+// Find returns the data associated with key in the tree, or
+// nil if key is not in the tree.
+func (t *RBTint32) Find(key int32) interface{} {
+ return t.root.find(key).Data()
+}
+
+// Insert adds key to the tree and associates key with data.
+// If key was already in the tree, it updates the associated data.
+// Insert returns the previous data associated with key,
+// or nil if key was not present.
+// Insert panics if data is nil.
+func (t *RBTint32) Insert(key int32, data interface{}) interface{} {
+ if data == nil {
+ panic("Cannot insert nil data into tree")
+ }
+ n := t.root
+ var newroot *node32
+ if n == nil {
+ n = t.makeNode(key)
+ newroot = n
+ } else {
+ newroot, n = n.insert(key, t)
+ }
+ r := n.data
+ n.data = data
+ t.root = newroot
+ return r
+}
+
+// Min returns the minimum element of t and its associated data.
+// If t is empty, then (0, nil) is returned.
+func (t *RBTint32) Min() (k int32, d interface{}) {
+ return t.root.min().keyAndData()
+}
+
+// Max returns the maximum element of t and its associated data.
+// If t is empty, then (0, nil) is returned.
+func (t *RBTint32) Max() (k int32, d interface{}) {
+ return t.root.max().keyAndData()
+}
+
+// Glb returns the greatest-lower-bound-exclusive of x and its associated
+// data. If x has no glb in the tree, then (0, nil) is returned.
+func (t *RBTint32) Glb(x int32) (k int32, d interface{}) {
+ return t.root.glb(x, false).keyAndData()
+}
+
+// GlbEq returns the greatest-lower-bound-inclusive of x and its associated
+// data. If x has no glbEQ in the tree, then (0, nil) is returned.
+func (t *RBTint32) GlbEq(x int32) (k int32, d interface{}) {
+ return t.root.glb(x, true).keyAndData()
+}
+
+// Lub returns the least-upper-bound-exclusive of x and its associated
+// data. If x has no lub in the tree, then (0, nil) is returned.
+func (t *RBTint32) Lub(x int32) (k int32, d interface{}) {
+ return t.root.lub(x, false).keyAndData()
+}
+
+// LubEq returns the least-upper-bound-inclusive of x and its associated
+// data. If x has no lubEq in the tree, then (0, nil) is returned.
+func (t *RBTint32) LubEq(x int32) (k int32, d interface{}) {
+ return t.root.lub(x, true).keyAndData()
+}
+
+func (t *node32) isLeaf() bool {
+ return t.left == nil && t.right == nil
+}
+
+func (t *node32) visitInOrder(f func(int32, interface{})) {
+ if t.left != nil {
+ t.left.visitInOrder(f)
+ }
+ f(t.key, t.data)
+ if t.right != nil {
+ t.right.visitInOrder(f)
+ }
+}
+
+func (t *node32) maxChildRank() rbrank {
+ if t.left == nil {
+ if t.right == nil {
+ return rankZero
+ }
+ return t.right.rank
+ }
+ if t.right == nil {
+ return t.left.rank
+ }
+ if t.right.rank > t.left.rank {
+ return t.right.rank
+ }
+ return t.left.rank
+}
+
+func (t *node32) minChildRank() rbrank {
+ if t.left == nil || t.right == nil {
+ return rankZero
+ }
+ if t.right.rank < t.left.rank {
+ return t.right.rank
+ }
+ return t.left.rank
+}
+
+func (t *node32) find(key int32) *node32 {
+ for t != nil {
+ if key < t.key {
+ t = t.left
+ } else if key > t.key {
+ t = t.right
+ } else {
+ return t
+ }
+ }
+ return nil
+}
+
+func (t *node32) min() *node32 {
+ if t == nil {
+ return t
+ }
+ for t.left != nil {
+ t = t.left
+ }
+ return t
+}
+
+func (t *node32) max() *node32 {
+ if t == nil {
+ return t
+ }
+ for t.right != nil {
+ t = t.right
+ }
+ return t
+}
+
+func (t *node32) glb(key int32, allow_eq bool) *node32 {
+ var best *node32
+ for t != nil {
+ if key <= t.key {
+ if key == t.key && allow_eq {
+ return t
+ }
+ // t is too big, glb is to left.
+ t = t.left
+ } else {
+ // t is a lower bound, record it and seek a better one.
+ best = t
+ t = t.right
+ }
+ }
+ return best
+}
+
+func (t *node32) lub(key int32, allow_eq bool) *node32 {
+ var best *node32
+ for t != nil {
+ if key >= t.key {
+ if key == t.key && allow_eq {
+ return t
+ }
+ // t is too small, lub is to right.
+ t = t.right
+ } else {
+ // t is a upper bound, record it and seek a better one.
+ best = t
+ t = t.left
+ }
+ }
+ return best
+}
+
+func (t *node32) insert(x int32, w *RBTint32) (newroot, newnode *node32) {
+ // defaults
+ newroot = t
+ newnode = t
+ if x == t.key {
+ return
+ }
+ if x < t.key {
+ if t.left == nil {
+ n := w.makeNode(x)
+ n.parent = t
+ t.left = n
+ newnode = n
+ return
+ }
+ var new_l *node32
+ new_l, newnode = t.left.insert(x, w)
+ t.left = new_l
+ new_l.parent = t
+ newrank := 1 + new_l.maxChildRank()
+ if newrank > t.rank {
+ if newrank > 1+t.right.Rank() { // rotations required
+ if new_l.left.Rank() < new_l.right.Rank() {
+ // double rotation
+ t.left = new_l.rightToRoot()
+ }
+ newroot = t.leftToRoot()
+ return
+ } else {
+ t.rank = newrank
+ }
+ }
+ } else { // x > t.key
+ if t.right == nil {
+ n := w.makeNode(x)
+ n.parent = t
+ t.right = n
+ newnode = n
+ return
+ }
+ var new_r *node32
+ new_r, newnode = t.right.insert(x, w)
+ t.right = new_r
+ new_r.parent = t
+ newrank := 1 + new_r.maxChildRank()
+ if newrank > t.rank {
+ if newrank > 1+t.left.Rank() { // rotations required
+ if new_r.right.Rank() < new_r.left.Rank() {
+ // double rotation
+ t.right = new_r.leftToRoot()
+ }
+ newroot = t.rightToRoot()
+ return
+ } else {
+ t.rank = newrank
+ }
+ }
+ }
+ return
+}
+
+func (t *node32) rightToRoot() *node32 {
+ // this
+ // left right
+ // rl rr
+ //
+ // becomes
+ //
+ // right
+ // this rr
+ // left rl
+ //
+ right := t.right
+ rl := right.left
+ right.parent = t.parent
+ right.left = t
+ t.parent = right
+ // parent's child ptr fixed in caller
+ t.right = rl
+ if rl != nil {
+ rl.parent = t
+ }
+ return right
+}
+
+func (t *node32) leftToRoot() *node32 {
+ // this
+ // left right
+ // ll lr
+ //
+ // becomes
+ //
+ // left
+ // ll this
+ // lr right
+ //
+ left := t.left
+ lr := left.right
+ left.parent = t.parent
+ left.right = t
+ t.parent = left
+ // parent's child ptr fixed in caller
+ t.left = lr
+ if lr != nil {
+ lr.parent = t
+ }
+ return left
+}
+
+// next returns the successor of t in a left-to-right
+// walk of the tree in which t is embedded.
+func (t *node32) next() *node32 {
+ // If there is a right child, it is to the right
+ r := t.right
+ if r != nil {
+ return r.min()
+ }
+ // if t is p.left, then p, else repeat.
+ p := t.parent
+ for p != nil {
+ if p.left == t {
+ return p
+ }
+ t = p
+ p = t.parent
+ }
+ return nil
+}
+
+// prev returns the predecessor of t in a left-to-right
+// walk of the tree in which t is embedded.
+func (t *node32) prev() *node32 {
+ // If there is a left child, it is to the left
+ l := t.left
+ if l != nil {
+ return l.max()
+ }
+ // if t is p.right, then p, else repeat.
+ p := t.parent
+ for p != nil {
+ if p.right == t {
+ return p
+ }
+ t = p
+ p = t.parent
+ }
+ return nil
+}
diff --git a/src/cmd/compile/internal/ssa/redblack32_test.go b/src/cmd/compile/internal/ssa/redblack32_test.go
new file mode 100644
index 0000000..376e8cf
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/redblack32_test.go
@@ -0,0 +1,274 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "fmt"
+ "testing"
+)
+
+type sstring string
+
+func (s sstring) String() string {
+ return string(s)
+}
+
+// wellFormed ensures that a red-black tree meets
+// all of its invariants and returns a string identifying
+// the first problem encountered. If there is no problem
+// then the returned string is empty. The size is also
+// returned to allow comparison of calculated tree size
+// with expected.
+func (t *RBTint32) wellFormed() (s string, i int) {
+ if t.root == nil {
+ s = ""
+ i = 0
+ return
+ }
+ return t.root.wellFormedSubtree(nil, -0x80000000, 0x7fffffff)
+}
+
+// wellFormedSubtree ensures that a red-black subtree meets
+// all of its invariants and returns a string identifying
+// the first problem encountered. If there is no problem
+// then the returned string is empty. The size is also
+// returned to allow comparison of calculated tree size
+// with expected.
+func (t *node32) wellFormedSubtree(parent *node32, min, max int32) (s string, i int) {
+ i = -1 // initialize to a failing value
+ s = "" // s is the reason for failure; empty means okay.
+
+ if t.parent != parent {
+ s = "t.parent != parent"
+ return
+ }
+
+ if min >= t.key {
+ s = "min >= t.key"
+ return
+ }
+
+ if max <= t.key {
+ s = "max <= t.key"
+ return
+ }
+
+ l := t.left
+ r := t.right
+ if l == nil && r == nil {
+ if t.rank != rankLeaf {
+ s = "leaf rank wrong"
+ return
+ }
+ }
+ if l != nil {
+ if t.rank < l.rank {
+ s = "t.rank < l.rank"
+ } else if t.rank > 1+l.rank {
+ s = "t.rank > 1+l.rank"
+ } else if t.rank <= l.maxChildRank() {
+ s = "t.rank <= l.maxChildRank()"
+ } else if t.key <= l.key {
+ s = "t.key <= l.key"
+ }
+ if s != "" {
+ return
+ }
+ } else {
+ if t.rank != 1 {
+ s = "t w/ left nil has rank != 1"
+ return
+ }
+ }
+ if r != nil {
+ if t.rank < r.rank {
+ s = "t.rank < r.rank"
+ } else if t.rank > 1+r.rank {
+ s = "t.rank > 1+r.rank"
+ } else if t.rank <= r.maxChildRank() {
+ s = "t.rank <= r.maxChildRank()"
+ } else if t.key >= r.key {
+ s = "t.key >= r.key"
+ }
+ if s != "" {
+ return
+ }
+ } else {
+ if t.rank != 1 {
+ s = "t w/ right nil has rank != 1"
+ return
+ }
+ }
+ ii := 1
+ if l != nil {
+ res, il := l.wellFormedSubtree(t, min, t.key)
+ if res != "" {
+ s = "L." + res
+ return
+ }
+ ii += il
+ }
+ if r != nil {
+ res, ir := r.wellFormedSubtree(t, t.key, max)
+ if res != "" {
+ s = "R." + res
+ return
+ }
+ ii += ir
+ }
+ i = ii
+ return
+}
+
+func (t *RBTint32) DebugString() string {
+ if t.root == nil {
+ return ""
+ }
+ return t.root.DebugString()
+}
+
+// DebugString prints the tree with nested information
+// to allow an eyeball check on the tree balance.
+func (t *node32) DebugString() string {
+ s := ""
+ if t.left != nil {
+ s += "["
+ s += t.left.DebugString()
+ s += "]"
+ }
+ s += fmt.Sprintf("%v=%v:%d", t.key, t.data, t.rank)
+ if t.right != nil {
+ s += "["
+ s += t.right.DebugString()
+ s += "]"
+ }
+ return s
+}
+
+func allRBT32Ops(te *testing.T, x []int32) {
+ t := &RBTint32{}
+ for i, d := range x {
+ x[i] = d + d // Double everything for glb/lub testing
+ }
+
+ // fmt.Printf("Inserting double of %v", x)
+ k := 0
+ min := int32(0x7fffffff)
+ max := int32(-0x80000000)
+ for _, d := range x {
+ if d < min {
+ min = d
+ }
+
+ if d > max {
+ max = d
+ }
+
+ t.Insert(d, sstring(fmt.Sprintf("%v", d)))
+ k++
+ s, i := t.wellFormed()
+ if i != k {
+ te.Errorf("Wrong tree size %v, expected %v for %v", i, k, t.DebugString())
+ }
+ if s != "" {
+ te.Errorf("Tree consistency problem at %v", s)
+ return
+ }
+ }
+
+ oops := false
+
+ for _, d := range x {
+ s := fmt.Sprintf("%v", d)
+ f := t.Find(d)
+
+ // data
+ if s != fmt.Sprintf("%v", f) {
+ te.Errorf("s(%v) != f(%v)", s, f)
+ oops = true
+ }
+ }
+
+ if !oops {
+ for _, d := range x {
+ s := fmt.Sprintf("%v", d)
+
+ kg, g := t.Glb(d + 1)
+ kge, ge := t.GlbEq(d)
+ kl, l := t.Lub(d - 1)
+ kle, le := t.LubEq(d)
+
+ // keys
+ if d != kg {
+ te.Errorf("d(%v) != kg(%v)", d, kg)
+ }
+ if d != kl {
+ te.Errorf("d(%v) != kl(%v)", d, kl)
+ }
+ if d != kge {
+ te.Errorf("d(%v) != kge(%v)", d, kge)
+ }
+ if d != kle {
+ te.Errorf("d(%v) != kle(%v)", d, kle)
+ }
+ // data
+ if s != fmt.Sprintf("%v", g) {
+ te.Errorf("s(%v) != g(%v)", s, g)
+ }
+ if s != fmt.Sprintf("%v", l) {
+ te.Errorf("s(%v) != l(%v)", s, l)
+ }
+ if s != fmt.Sprintf("%v", ge) {
+ te.Errorf("s(%v) != ge(%v)", s, ge)
+ }
+ if s != fmt.Sprintf("%v", le) {
+ te.Errorf("s(%v) != le(%v)", s, le)
+ }
+ }
+
+ for _, d := range x {
+ s := fmt.Sprintf("%v", d)
+ kge, ge := t.GlbEq(d + 1)
+ kle, le := t.LubEq(d - 1)
+ if d != kge {
+ te.Errorf("d(%v) != kge(%v)", d, kge)
+ }
+ if d != kle {
+ te.Errorf("d(%v) != kle(%v)", d, kle)
+ }
+ if s != fmt.Sprintf("%v", ge) {
+ te.Errorf("s(%v) != ge(%v)", s, ge)
+ }
+ if s != fmt.Sprintf("%v", le) {
+ te.Errorf("s(%v) != le(%v)", s, le)
+ }
+ }
+
+ kg, g := t.Glb(min)
+ kge, ge := t.GlbEq(min - 1)
+ kl, l := t.Lub(max)
+ kle, le := t.LubEq(max + 1)
+ fmin := t.Find(min - 1)
+ fmax := t.Find(min + 11)
+
+ if kg != 0 || kge != 0 || kl != 0 || kle != 0 {
+ te.Errorf("Got non-zero-key for missing query")
+ }
+
+ if g != nil || ge != nil || l != nil || le != nil || fmin != nil || fmax != nil {
+ te.Errorf("Got non-error-data for missing query")
+ }
+
+ }
+}
+
+func TestAllRBTreeOps(t *testing.T) {
+ allRBT32Ops(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25})
+ allRBT32Ops(t, []int32{22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 3, 2, 1, 25, 24, 23, 12, 11, 10, 9, 8, 7, 6, 5, 4})
+ allRBT32Ops(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
+ allRBT32Ops(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24})
+ allRBT32Ops(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2})
+ allRBT32Ops(t, []int32{24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25})
+}
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
new file mode 100644
index 0000000..0339b07
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -0,0 +1,2696 @@
+// 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.
+
+// Register allocation.
+//
+// We use a version of a linear scan register allocator. We treat the
+// whole function as a single long basic block and run through
+// it using a greedy register allocator. Then all merge edges
+// (those targeting a block with len(Preds)>1) are processed to
+// shuffle data into the place that the target of the edge expects.
+//
+// The greedy allocator moves values into registers just before they
+// are used, spills registers only when necessary, and spills the
+// value whose next use is farthest in the future.
+//
+// The register allocator requires that a block is not scheduled until
+// at least one of its predecessors have been scheduled. The most recent
+// such predecessor provides the starting register state for a block.
+//
+// It also requires that there are no critical edges (critical =
+// comes from a block with >1 successor and goes to a block with >1
+// predecessor). This makes it easy to add fixup code on merge edges -
+// the source of a merge edge has only one successor, so we can add
+// fixup code to the end of that block.
+
+// Spilling
+//
+// During the normal course of the allocator, we might throw a still-live
+// value out of all registers. When that value is subsequently used, we must
+// load it from a slot on the stack. We must also issue an instruction to
+// initialize that stack location with a copy of v.
+//
+// pre-regalloc:
+// (1) v = Op ...
+// (2) x = Op ...
+// (3) ... = Op v ...
+//
+// post-regalloc:
+// (1) v = Op ... : AX // computes v, store result in AX
+// s = StoreReg v // spill v to a stack slot
+// (2) x = Op ... : AX // some other op uses AX
+// c = LoadReg s : CX // restore v from stack slot
+// (3) ... = Op c ... // use the restored value
+//
+// Allocation occurs normally until we reach (3) and we realize we have
+// a use of v and it isn't in any register. At that point, we allocate
+// a spill (a StoreReg) for v. We can't determine the correct place for
+// the spill at this point, so we allocate the spill as blockless initially.
+// The restore is then generated to load v back into a register so it can
+// be used. Subsequent uses of v will use the restored value c instead.
+//
+// What remains is the question of where to schedule the spill.
+// During allocation, we keep track of the dominator of all restores of v.
+// The spill of v must dominate that block. The spill must also be issued at
+// a point where v is still in a register.
+//
+// To find the right place, start at b, the block which dominates all restores.
+// - If b is v.Block, then issue the spill right after v.
+// It is known to be in a register at that point, and dominates any restores.
+// - Otherwise, if v is in a register at the start of b,
+// put the spill of v at the start of b.
+// - Otherwise, set b = immediate dominator of b, and repeat.
+//
+// Phi values are special, as always. We define two kinds of phis, those
+// where the merge happens in a register (a "register" phi) and those where
+// the merge happens in a stack location (a "stack" phi).
+//
+// A register phi must have the phi and all of its inputs allocated to the
+// same register. Register phis are spilled similarly to regular ops.
+//
+// A stack phi must have the phi and all of its inputs allocated to the same
+// stack location. Stack phis start out life already spilled - each phi
+// input must be a store (using StoreReg) at the end of the corresponding
+// predecessor block.
+// b1: y = ... : AX b2: z = ... : BX
+// y2 = StoreReg y z2 = StoreReg z
+// goto b3 goto b3
+// b3: x = phi(y2, z2)
+// The stack allocator knows that StoreReg args of stack-allocated phis
+// must be allocated to the same stack slot as the phi that uses them.
+// x is now a spilled value and a restore must appear before its first use.
+
+// TODO
+
+// Use an affinity graph to mark two values which should use the
+// same register. This affinity graph will be used to prefer certain
+// registers for allocation. This affinity helps eliminate moves that
+// are required for phi implementations and helps generate allocations
+// for 2-register architectures.
+
+// Note: regalloc generates a not-quite-SSA output. If we have:
+//
+// b1: x = ... : AX
+// x2 = StoreReg x
+// ... AX gets reused for something else ...
+// if ... goto b3 else b4
+//
+// b3: x3 = LoadReg x2 : BX b4: x4 = LoadReg x2 : CX
+// ... use x3 ... ... use x4 ...
+//
+// b2: ... use x3 ...
+//
+// If b3 is the primary predecessor of b2, then we use x3 in b2 and
+// add a x4:CX->BX copy at the end of b4.
+// But the definition of x3 doesn't dominate b2. We should really
+// insert a dummy phi at the start of b2 (x5=phi(x3,x4):BX) to keep
+// SSA form. For now, we ignore this problem as remaining in strict
+// SSA form isn't needed after regalloc. We'll just leave the use
+// of x3 not dominated by the definition of x3, and the CX->BX copy
+// will have no use (so don't run deadcode after regalloc!).
+// TODO: maybe we should introduce these extra phis?
+
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "cmd/internal/objabi"
+ "cmd/internal/src"
+ "cmd/internal/sys"
+ "fmt"
+ "math/bits"
+ "unsafe"
+)
+
+const (
+ moveSpills = iota
+ logSpills
+ regDebug
+ stackDebug
+)
+
+// distance is a measure of how far into the future values are used.
+// distance is measured in units of instructions.
+const (
+ likelyDistance = 1
+ normalDistance = 10
+ unlikelyDistance = 100
+)
+
+// regalloc performs register allocation on f. It sets f.RegAlloc
+// to the resulting allocation.
+func regalloc(f *Func) {
+ var s regAllocState
+ s.init(f)
+ s.regalloc(f)
+}
+
+type register uint8
+
+const noRegister register = 255
+
+// A regMask encodes a set of machine registers.
+// TODO: regMask -> regSet?
+type regMask uint64
+
+func (m regMask) String() string {
+ s := ""
+ for r := register(0); m != 0; r++ {
+ if m>>r&1 == 0 {
+ continue
+ }
+ m &^= regMask(1) << r
+ if s != "" {
+ s += " "
+ }
+ s += fmt.Sprintf("r%d", r)
+ }
+ return s
+}
+
+func (s *regAllocState) RegMaskString(m regMask) string {
+ str := ""
+ for r := register(0); m != 0; r++ {
+ if m>>r&1 == 0 {
+ continue
+ }
+ m &^= regMask(1) << r
+ if str != "" {
+ str += " "
+ }
+ str += s.registers[r].String()
+ }
+ return str
+}
+
+// countRegs returns the number of set bits in the register mask.
+func countRegs(r regMask) int {
+ return bits.OnesCount64(uint64(r))
+}
+
+// pickReg picks an arbitrary register from the register mask.
+func pickReg(r regMask) register {
+ if r == 0 {
+ panic("can't pick a register from an empty set")
+ }
+ // pick the lowest one
+ return register(bits.TrailingZeros64(uint64(r)))
+}
+
+type use struct {
+ dist int32 // distance from start of the block to a use of a value
+ pos src.XPos // source position of the use
+ next *use // linked list of uses of a value in nondecreasing dist order
+}
+
+// A valState records the register allocation state for a (pre-regalloc) value.
+type valState struct {
+ regs regMask // the set of registers holding a Value (usually just one)
+ uses *use // list of uses in this block
+ spill *Value // spilled copy of the Value (if any)
+ restoreMin int32 // minimum of all restores' blocks' sdom.entry
+ restoreMax int32 // maximum of all restores' blocks' sdom.exit
+ needReg bool // cached value of !v.Type.IsMemory() && !v.Type.IsVoid() && !.v.Type.IsFlags()
+ rematerializeable bool // cached value of v.rematerializeable()
+}
+
+type regState struct {
+ v *Value // Original (preregalloc) Value stored in this register.
+ c *Value // A Value equal to v which is currently in a register. Might be v or a copy of it.
+ // If a register is unused, v==c==nil
+}
+
+type regAllocState struct {
+ f *Func
+
+ sdom SparseTree
+ registers []Register
+ numRegs register
+ SPReg register
+ SBReg register
+ GReg register
+ allocatable regMask
+
+ // for each block, its primary predecessor.
+ // A predecessor of b is primary if it is the closest
+ // predecessor that appears before b in the layout order.
+ // We record the index in the Preds list where the primary predecessor sits.
+ primary []int32
+
+ // live values at the end of each block. live[b.ID] is a list of value IDs
+ // which are live at the end of b, together with a count of how many instructions
+ // forward to the next use.
+ live [][]liveInfo
+ // desired register assignments at the end of each block.
+ // Note that this is a static map computed before allocation occurs. Dynamic
+ // register desires (from partially completed allocations) will trump
+ // this information.
+ desired []desiredState
+
+ // current state of each (preregalloc) Value
+ values []valState
+
+ // ID of SP, SB values
+ sp, sb ID
+
+ // For each Value, map from its value ID back to the
+ // preregalloc Value it was derived from.
+ orig []*Value
+
+ // current state of each register
+ regs []regState
+
+ // registers that contain values which can't be kicked out
+ nospill regMask
+
+ // mask of registers currently in use
+ used regMask
+
+ // mask of registers used in the current instruction
+ tmpused regMask
+
+ // current block we're working on
+ curBlock *Block
+
+ // cache of use records
+ freeUseRecords *use
+
+ // endRegs[blockid] is the register state at the end of each block.
+ // encoded as a set of endReg records.
+ endRegs [][]endReg
+
+ // startRegs[blockid] is the register state at the start of merge blocks.
+ // saved state does not include the state of phi ops in the block.
+ startRegs [][]startReg
+
+ // spillLive[blockid] is the set of live spills at the end of each block
+ spillLive [][]ID
+
+ // a set of copies we generated to move things around, and
+ // whether it is used in shuffle. Unused copies will be deleted.
+ copies map[*Value]bool
+
+ loopnest *loopnest
+
+ // choose a good order in which to visit blocks for allocation purposes.
+ visitOrder []*Block
+}
+
+type endReg struct {
+ r register
+ v *Value // pre-regalloc value held in this register (TODO: can we use ID here?)
+ c *Value // cached version of the value
+}
+
+type startReg struct {
+ r register
+ v *Value // pre-regalloc value needed in this register
+ c *Value // cached version of the value
+ pos src.XPos // source position of use of this register
+}
+
+// freeReg frees up register r. Any current user of r is kicked out.
+func (s *regAllocState) freeReg(r register) {
+ v := s.regs[r].v
+ if v == nil {
+ s.f.Fatalf("tried to free an already free register %d\n", r)
+ }
+
+ // Mark r as unused.
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("freeReg %s (dump %s/%s)\n", &s.registers[r], v, s.regs[r].c)
+ }
+ s.regs[r] = regState{}
+ s.values[v.ID].regs &^= regMask(1) << r
+ s.used &^= regMask(1) << r
+}
+
+// freeRegs frees up all registers listed in m.
+func (s *regAllocState) freeRegs(m regMask) {
+ for m&s.used != 0 {
+ s.freeReg(pickReg(m & s.used))
+ }
+}
+
+// setOrig records that c's original value is the same as
+// v's original value.
+func (s *regAllocState) setOrig(c *Value, v *Value) {
+ for int(c.ID) >= len(s.orig) {
+ s.orig = append(s.orig, nil)
+ }
+ if s.orig[c.ID] != nil {
+ s.f.Fatalf("orig value set twice %s %s", c, v)
+ }
+ s.orig[c.ID] = s.orig[v.ID]
+}
+
+// assignReg assigns register r to hold c, a copy of v.
+// r must be unused.
+func (s *regAllocState) assignReg(r register, v *Value, c *Value) {
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("assignReg %s %s/%s\n", &s.registers[r], v, c)
+ }
+ if s.regs[r].v != nil {
+ s.f.Fatalf("tried to assign register %d to %s/%s but it is already used by %s", r, v, c, s.regs[r].v)
+ }
+
+ // Update state.
+ s.regs[r] = regState{v, c}
+ s.values[v.ID].regs |= regMask(1) << r
+ s.used |= regMask(1) << r
+ s.f.setHome(c, &s.registers[r])
+}
+
+// allocReg chooses a register from the set of registers in mask.
+// If there is no unused register, a Value will be kicked out of
+// a register to make room.
+func (s *regAllocState) allocReg(mask regMask, v *Value) register {
+ if v.OnWasmStack {
+ return noRegister
+ }
+
+ mask &= s.allocatable
+ mask &^= s.nospill
+ if mask == 0 {
+ s.f.Fatalf("no register available for %s", v.LongString())
+ }
+
+ // Pick an unused register if one is available.
+ if mask&^s.used != 0 {
+ return pickReg(mask &^ s.used)
+ }
+
+ // Pick a value to spill. Spill the value with the
+ // farthest-in-the-future use.
+ // TODO: Prefer registers with already spilled Values?
+ // TODO: Modify preference using affinity graph.
+ // TODO: if a single value is in multiple registers, spill one of them
+ // before spilling a value in just a single register.
+
+ // Find a register to spill. We spill the register containing the value
+ // whose next use is as far in the future as possible.
+ // https://en.wikipedia.org/wiki/Page_replacement_algorithm#The_theoretically_optimal_page_replacement_algorithm
+ var r register
+ maxuse := int32(-1)
+ for t := register(0); t < s.numRegs; t++ {
+ if mask>>t&1 == 0 {
+ continue
+ }
+ v := s.regs[t].v
+ if n := s.values[v.ID].uses.dist; n > maxuse {
+ // v's next use is farther in the future than any value
+ // we've seen so far. A new best spill candidate.
+ r = t
+ maxuse = n
+ }
+ }
+ if maxuse == -1 {
+ s.f.Fatalf("couldn't find register to spill")
+ }
+
+ if s.f.Config.ctxt.Arch.Arch == sys.ArchWasm {
+ // TODO(neelance): In theory this should never happen, because all wasm registers are equal.
+ // So if there is still a free register, the allocation should have picked that one in the first place instead of
+ // trying to kick some other value out. In practice, this case does happen and it breaks the stack optimization.
+ s.freeReg(r)
+ return r
+ }
+
+ // Try to move it around before kicking out, if there is a free register.
+ // We generate a Copy and record it. It will be deleted if never used.
+ v2 := s.regs[r].v
+ m := s.compatRegs(v2.Type) &^ s.used &^ s.tmpused &^ (regMask(1) << r)
+ if m != 0 && !s.values[v2.ID].rematerializeable && countRegs(s.values[v2.ID].regs) == 1 {
+ r2 := pickReg(m)
+ c := s.curBlock.NewValue1(v2.Pos, OpCopy, v2.Type, s.regs[r].c)
+ s.copies[c] = false
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("copy %s to %s : %s\n", v2, c, &s.registers[r2])
+ }
+ s.setOrig(c, v2)
+ s.assignReg(r2, v2, c)
+ }
+ s.freeReg(r)
+ return r
+}
+
+// makeSpill returns a Value which represents the spilled value of v.
+// b is the block in which the spill is used.
+func (s *regAllocState) makeSpill(v *Value, b *Block) *Value {
+ vi := &s.values[v.ID]
+ if vi.spill != nil {
+ // Final block not known - keep track of subtree where restores reside.
+ vi.restoreMin = min32(vi.restoreMin, s.sdom[b.ID].entry)
+ vi.restoreMax = max32(vi.restoreMax, s.sdom[b.ID].exit)
+ return vi.spill
+ }
+ // Make a spill for v. We don't know where we want
+ // to put it yet, so we leave it blockless for now.
+ spill := s.f.newValueNoBlock(OpStoreReg, v.Type, v.Pos)
+ // We also don't know what the spill's arg will be.
+ // Leave it argless for now.
+ s.setOrig(spill, v)
+ vi.spill = spill
+ vi.restoreMin = s.sdom[b.ID].entry
+ vi.restoreMax = s.sdom[b.ID].exit
+ return spill
+}
+
+// allocValToReg allocates v to a register selected from regMask and
+// returns the register copy of v. Any previous user is kicked out and spilled
+// (if necessary). Load code is added at the current pc. If nospill is set the
+// allocated register is marked nospill so the assignment cannot be
+// undone until the caller allows it by clearing nospill. Returns a
+// *Value which is either v or a copy of v allocated to the chosen register.
+func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos src.XPos) *Value {
+ if s.f.Config.ctxt.Arch.Arch == sys.ArchWasm && v.rematerializeable() {
+ c := v.copyIntoWithXPos(s.curBlock, pos)
+ c.OnWasmStack = true
+ s.setOrig(c, v)
+ return c
+ }
+ if v.OnWasmStack {
+ return v
+ }
+
+ vi := &s.values[v.ID]
+ pos = pos.WithNotStmt()
+ // Check if v is already in a requested register.
+ if mask&vi.regs != 0 {
+ r := pickReg(mask & vi.regs)
+ if s.regs[r].v != v || s.regs[r].c == nil {
+ panic("bad register state")
+ }
+ if nospill {
+ s.nospill |= regMask(1) << r
+ }
+ return s.regs[r].c
+ }
+
+ var r register
+ // If nospill is set, the value is used immediately, so it can live on the WebAssembly stack.
+ onWasmStack := nospill && s.f.Config.ctxt.Arch.Arch == sys.ArchWasm
+ if !onWasmStack {
+ // Allocate a register.
+ r = s.allocReg(mask, v)
+ }
+
+ // Allocate v to the new register.
+ var c *Value
+ if vi.regs != 0 {
+ // Copy from a register that v is already in.
+ r2 := pickReg(vi.regs)
+ if s.regs[r2].v != v {
+ panic("bad register state")
+ }
+ c = s.curBlock.NewValue1(pos, OpCopy, v.Type, s.regs[r2].c)
+ } else if v.rematerializeable() {
+ // Rematerialize instead of loading from the spill location.
+ c = v.copyIntoWithXPos(s.curBlock, pos)
+ } else {
+ // Load v from its spill location.
+ spill := s.makeSpill(v, s.curBlock)
+ if s.f.pass.debug > logSpills {
+ s.f.Warnl(vi.spill.Pos, "load spill for %v from %v", v, spill)
+ }
+ c = s.curBlock.NewValue1(pos, OpLoadReg, v.Type, spill)
+ }
+
+ s.setOrig(c, v)
+
+ if onWasmStack {
+ c.OnWasmStack = true
+ return c
+ }
+
+ s.assignReg(r, v, c)
+ if c.Op == OpLoadReg && s.isGReg(r) {
+ s.f.Fatalf("allocValToReg.OpLoadReg targeting g: " + c.LongString())
+ }
+ if nospill {
+ s.nospill |= regMask(1) << r
+ }
+ return c
+}
+
+// isLeaf reports whether f performs any calls.
+func isLeaf(f *Func) bool {
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if opcodeTable[v.Op].call {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+func (s *regAllocState) init(f *Func) {
+ s.f = f
+ s.f.RegAlloc = s.f.Cache.locs[:0]
+ s.registers = f.Config.registers
+ if nr := len(s.registers); nr == 0 || nr > int(noRegister) || nr > int(unsafe.Sizeof(regMask(0))*8) {
+ s.f.Fatalf("bad number of registers: %d", nr)
+ } else {
+ s.numRegs = register(nr)
+ }
+ // Locate SP, SB, and g registers.
+ s.SPReg = noRegister
+ s.SBReg = noRegister
+ s.GReg = noRegister
+ for r := register(0); r < s.numRegs; r++ {
+ switch s.registers[r].String() {
+ case "SP":
+ s.SPReg = r
+ case "SB":
+ s.SBReg = r
+ case "g":
+ s.GReg = r
+ }
+ }
+ // Make sure we found all required registers.
+ switch noRegister {
+ case s.SPReg:
+ s.f.Fatalf("no SP register found")
+ case s.SBReg:
+ s.f.Fatalf("no SB register found")
+ case s.GReg:
+ if f.Config.hasGReg {
+ s.f.Fatalf("no g register found")
+ }
+ }
+
+ // Figure out which registers we're allowed to use.
+ s.allocatable = s.f.Config.gpRegMask | s.f.Config.fpRegMask | s.f.Config.specialRegMask
+ s.allocatable &^= 1 << s.SPReg
+ s.allocatable &^= 1 << s.SBReg
+ if s.f.Config.hasGReg {
+ s.allocatable &^= 1 << s.GReg
+ }
+ if objabi.Framepointer_enabled && s.f.Config.FPReg >= 0 {
+ s.allocatable &^= 1 << uint(s.f.Config.FPReg)
+ }
+ if s.f.Config.LinkReg != -1 {
+ if isLeaf(f) {
+ // Leaf functions don't save/restore the link register.
+ s.allocatable &^= 1 << uint(s.f.Config.LinkReg)
+ }
+ if s.f.Config.arch == "arm" && objabi.GOARM == 5 {
+ // On ARMv5 we insert softfloat calls at each FP instruction.
+ // This clobbers LR almost everywhere. Disable allocating LR
+ // on ARMv5.
+ s.allocatable &^= 1 << uint(s.f.Config.LinkReg)
+ }
+ }
+ if s.f.Config.ctxt.Flag_dynlink {
+ switch s.f.Config.arch {
+ case "amd64":
+ s.allocatable &^= 1 << 15 // R15
+ case "arm":
+ s.allocatable &^= 1 << 9 // R9
+ case "ppc64le": // R2 already reserved.
+ // nothing to do
+ case "arm64":
+ // nothing to do?
+ case "386":
+ // nothing to do.
+ // Note that for Flag_shared (position independent code)
+ // we do need to be careful, but that carefulness is hidden
+ // in the rewrite rules so we always have a free register
+ // available for global load/stores. See gen/386.rules (search for Flag_shared).
+ case "s390x":
+ s.allocatable &^= 1 << 11 // R11
+ default:
+ s.f.fe.Fatalf(src.NoXPos, "arch %s not implemented", s.f.Config.arch)
+ }
+ }
+
+ // Linear scan register allocation can be influenced by the order in which blocks appear.
+ // Decouple the register allocation order from the generated block order.
+ // This also creates an opportunity for experiments to find a better order.
+ s.visitOrder = layoutRegallocOrder(f)
+
+ // Compute block order. This array allows us to distinguish forward edges
+ // from backward edges and compute how far they go.
+ blockOrder := make([]int32, f.NumBlocks())
+ for i, b := range s.visitOrder {
+ blockOrder[b.ID] = int32(i)
+ }
+
+ s.regs = make([]regState, s.numRegs)
+ nv := f.NumValues()
+ if cap(s.f.Cache.regallocValues) >= nv {
+ s.f.Cache.regallocValues = s.f.Cache.regallocValues[:nv]
+ } else {
+ s.f.Cache.regallocValues = make([]valState, nv)
+ }
+ s.values = s.f.Cache.regallocValues
+ s.orig = make([]*Value, nv)
+ s.copies = make(map[*Value]bool)
+ for _, b := range s.visitOrder {
+ for _, v := range b.Values {
+ if !v.Type.IsMemory() && !v.Type.IsVoid() && !v.Type.IsFlags() && !v.Type.IsTuple() {
+ s.values[v.ID].needReg = true
+ s.values[v.ID].rematerializeable = v.rematerializeable()
+ s.orig[v.ID] = v
+ }
+ // Note: needReg is false for values returning Tuple types.
+ // Instead, we mark the corresponding Selects as needReg.
+ }
+ }
+ s.computeLive()
+
+ // Compute primary predecessors.
+ s.primary = make([]int32, f.NumBlocks())
+ for _, b := range s.visitOrder {
+ best := -1
+ for i, e := range b.Preds {
+ p := e.b
+ if blockOrder[p.ID] >= blockOrder[b.ID] {
+ continue // backward edge
+ }
+ if best == -1 || blockOrder[p.ID] > blockOrder[b.Preds[best].b.ID] {
+ best = i
+ }
+ }
+ s.primary[b.ID] = int32(best)
+ }
+
+ s.endRegs = make([][]endReg, f.NumBlocks())
+ s.startRegs = make([][]startReg, f.NumBlocks())
+ s.spillLive = make([][]ID, f.NumBlocks())
+ s.sdom = f.Sdom()
+
+ // wasm: Mark instructions that can be optimized to have their values only on the WebAssembly stack.
+ if f.Config.ctxt.Arch.Arch == sys.ArchWasm {
+ canLiveOnStack := f.newSparseSet(f.NumValues())
+ defer f.retSparseSet(canLiveOnStack)
+ for _, b := range f.Blocks {
+ // New block. Clear candidate set.
+ canLiveOnStack.clear()
+ for _, c := range b.ControlValues() {
+ if c.Uses == 1 && !opcodeTable[c.Op].generic {
+ canLiveOnStack.add(c.ID)
+ }
+ }
+ // Walking backwards.
+ for i := len(b.Values) - 1; i >= 0; i-- {
+ v := b.Values[i]
+ if canLiveOnStack.contains(v.ID) {
+ v.OnWasmStack = true
+ } else {
+ // Value can not live on stack. Values are not allowed to be reordered, so clear candidate set.
+ canLiveOnStack.clear()
+ }
+ for _, arg := range v.Args {
+ // Value can live on the stack if:
+ // - it is only used once
+ // - it is used in the same basic block
+ // - it is not a "mem" value
+ // - it is a WebAssembly op
+ if arg.Uses == 1 && arg.Block == v.Block && !arg.Type.IsMemory() && !opcodeTable[arg.Op].generic {
+ canLiveOnStack.add(arg.ID)
+ }
+ }
+ }
+ }
+ }
+}
+
+// Adds a use record for id at distance dist from the start of the block.
+// All calls to addUse must happen with nonincreasing dist.
+func (s *regAllocState) addUse(id ID, dist int32, pos src.XPos) {
+ r := s.freeUseRecords
+ if r != nil {
+ s.freeUseRecords = r.next
+ } else {
+ r = &use{}
+ }
+ r.dist = dist
+ r.pos = pos
+ r.next = s.values[id].uses
+ s.values[id].uses = r
+ if r.next != nil && dist > r.next.dist {
+ s.f.Fatalf("uses added in wrong order")
+ }
+}
+
+// advanceUses advances the uses of v's args from the state before v to the state after v.
+// Any values which have no more uses are deallocated from registers.
+func (s *regAllocState) advanceUses(v *Value) {
+ for _, a := range v.Args {
+ if !s.values[a.ID].needReg {
+ continue
+ }
+ ai := &s.values[a.ID]
+ r := ai.uses
+ ai.uses = r.next
+ if r.next == nil {
+ // Value is dead, free all registers that hold it.
+ s.freeRegs(ai.regs)
+ }
+ r.next = s.freeUseRecords
+ s.freeUseRecords = r
+ }
+}
+
+// liveAfterCurrentInstruction reports whether v is live after
+// the current instruction is completed. v must be used by the
+// current instruction.
+func (s *regAllocState) liveAfterCurrentInstruction(v *Value) bool {
+ u := s.values[v.ID].uses
+ d := u.dist
+ for u != nil && u.dist == d {
+ u = u.next
+ }
+ return u != nil && u.dist > d
+}
+
+// Sets the state of the registers to that encoded in regs.
+func (s *regAllocState) setState(regs []endReg) {
+ s.freeRegs(s.used)
+ for _, x := range regs {
+ s.assignReg(x.r, x.v, x.c)
+ }
+}
+
+// compatRegs returns the set of registers which can store a type t.
+func (s *regAllocState) compatRegs(t *types.Type) regMask {
+ var m regMask
+ if t.IsTuple() || t.IsFlags() {
+ return 0
+ }
+ if t.IsFloat() || t == types.TypeInt128 {
+ if t.Etype == types.TFLOAT32 && s.f.Config.fp32RegMask != 0 {
+ m = s.f.Config.fp32RegMask
+ } else if t.Etype == types.TFLOAT64 && s.f.Config.fp64RegMask != 0 {
+ m = s.f.Config.fp64RegMask
+ } else {
+ m = s.f.Config.fpRegMask
+ }
+ } else {
+ m = s.f.Config.gpRegMask
+ }
+ return m & s.allocatable
+}
+
+// regspec returns the regInfo for operation op.
+func (s *regAllocState) regspec(op Op) regInfo {
+ if op == OpConvert {
+ // OpConvert is a generic op, so it doesn't have a
+ // register set in the static table. It can use any
+ // allocatable integer register.
+ m := s.allocatable & s.f.Config.gpRegMask
+ return regInfo{inputs: []inputInfo{{regs: m}}, outputs: []outputInfo{{regs: m}}}
+ }
+ return opcodeTable[op].reg
+}
+
+func (s *regAllocState) isGReg(r register) bool {
+ return s.f.Config.hasGReg && s.GReg == r
+}
+
+func (s *regAllocState) regalloc(f *Func) {
+ regValLiveSet := f.newSparseSet(f.NumValues()) // set of values that may be live in register
+ defer f.retSparseSet(regValLiveSet)
+ var oldSched []*Value
+ var phis []*Value
+ var phiRegs []register
+ var args []*Value
+
+ // Data structure used for computing desired registers.
+ var desired desiredState
+
+ // Desired registers for inputs & outputs for each instruction in the block.
+ type dentry struct {
+ out [4]register // desired output registers
+ in [3][4]register // desired input registers (for inputs 0,1, and 2)
+ }
+ var dinfo []dentry
+
+ if f.Entry != f.Blocks[0] {
+ f.Fatalf("entry block must be first")
+ }
+
+ for _, b := range s.visitOrder {
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("Begin processing block %v\n", b)
+ }
+ s.curBlock = b
+
+ // Initialize regValLiveSet and uses fields for this block.
+ // Walk backwards through the block doing liveness analysis.
+ regValLiveSet.clear()
+ for _, e := range s.live[b.ID] {
+ s.addUse(e.ID, int32(len(b.Values))+e.dist, e.pos) // pseudo-uses from beyond end of block
+ regValLiveSet.add(e.ID)
+ }
+ for _, v := range b.ControlValues() {
+ if s.values[v.ID].needReg {
+ s.addUse(v.ID, int32(len(b.Values)), b.Pos) // pseudo-use by control values
+ regValLiveSet.add(v.ID)
+ }
+ }
+ for i := len(b.Values) - 1; i >= 0; i-- {
+ v := b.Values[i]
+ regValLiveSet.remove(v.ID)
+ if v.Op == OpPhi {
+ // Remove v from the live set, but don't add
+ // any inputs. This is the state the len(b.Preds)>1
+ // case below desires; it wants to process phis specially.
+ continue
+ }
+ if opcodeTable[v.Op].call {
+ // Function call clobbers all the registers but SP and SB.
+ regValLiveSet.clear()
+ if s.sp != 0 && s.values[s.sp].uses != nil {
+ regValLiveSet.add(s.sp)
+ }
+ if s.sb != 0 && s.values[s.sb].uses != nil {
+ regValLiveSet.add(s.sb)
+ }
+ }
+ for _, a := range v.Args {
+ if !s.values[a.ID].needReg {
+ continue
+ }
+ s.addUse(a.ID, int32(i), v.Pos)
+ regValLiveSet.add(a.ID)
+ }
+ }
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("use distances for %s\n", b)
+ for i := range s.values {
+ vi := &s.values[i]
+ u := vi.uses
+ if u == nil {
+ continue
+ }
+ fmt.Printf(" v%d:", i)
+ for u != nil {
+ fmt.Printf(" %d", u.dist)
+ u = u.next
+ }
+ fmt.Println()
+ }
+ }
+
+ // Make a copy of the block schedule so we can generate a new one in place.
+ // We make a separate copy for phis and regular values.
+ nphi := 0
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ break
+ }
+ nphi++
+ }
+ phis = append(phis[:0], b.Values[:nphi]...)
+ oldSched = append(oldSched[:0], b.Values[nphi:]...)
+ b.Values = b.Values[:0]
+
+ // Initialize start state of block.
+ if b == f.Entry {
+ // Regalloc state is empty to start.
+ if nphi > 0 {
+ f.Fatalf("phis in entry block")
+ }
+ } else if len(b.Preds) == 1 {
+ // Start regalloc state with the end state of the previous block.
+ s.setState(s.endRegs[b.Preds[0].b.ID])
+ if nphi > 0 {
+ f.Fatalf("phis in single-predecessor block")
+ }
+ // Drop any values which are no longer live.
+ // This may happen because at the end of p, a value may be
+ // live but only used by some other successor of p.
+ for r := register(0); r < s.numRegs; r++ {
+ v := s.regs[r].v
+ if v != nil && !regValLiveSet.contains(v.ID) {
+ s.freeReg(r)
+ }
+ }
+ } else {
+ // This is the complicated case. We have more than one predecessor,
+ // which means we may have Phi ops.
+
+ // Start with the final register state of the primary predecessor
+ idx := s.primary[b.ID]
+ if idx < 0 {
+ f.Fatalf("block with no primary predecessor %s", b)
+ }
+ p := b.Preds[idx].b
+ s.setState(s.endRegs[p.ID])
+
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("starting merge block %s with end state of %s:\n", b, p)
+ for _, x := range s.endRegs[p.ID] {
+ fmt.Printf(" %s: orig:%s cache:%s\n", &s.registers[x.r], x.v, x.c)
+ }
+ }
+
+ // Decide on registers for phi ops. Use the registers determined
+ // by the primary predecessor if we can.
+ // TODO: pick best of (already processed) predecessors?
+ // Majority vote? Deepest nesting level?
+ phiRegs = phiRegs[:0]
+ var phiUsed regMask
+
+ for _, v := range phis {
+ if !s.values[v.ID].needReg {
+ phiRegs = append(phiRegs, noRegister)
+ continue
+ }
+ a := v.Args[idx]
+ // Some instructions target not-allocatable registers.
+ // They're not suitable for further (phi-function) allocation.
+ m := s.values[a.ID].regs &^ phiUsed & s.allocatable
+ if m != 0 {
+ r := pickReg(m)
+ phiUsed |= regMask(1) << r
+ phiRegs = append(phiRegs, r)
+ } else {
+ phiRegs = append(phiRegs, noRegister)
+ }
+ }
+
+ // Second pass - deallocate all in-register phi inputs.
+ for i, v := range phis {
+ if !s.values[v.ID].needReg {
+ continue
+ }
+ a := v.Args[idx]
+ r := phiRegs[i]
+ if r == noRegister {
+ continue
+ }
+ if regValLiveSet.contains(a.ID) {
+ // Input value is still live (it is used by something other than Phi).
+ // Try to move it around before kicking out, if there is a free register.
+ // We generate a Copy in the predecessor block and record it. It will be
+ // deleted later if never used.
+ //
+ // Pick a free register. At this point some registers used in the predecessor
+ // block may have been deallocated. Those are the ones used for Phis. Exclude
+ // them (and they are not going to be helpful anyway).
+ m := s.compatRegs(a.Type) &^ s.used &^ phiUsed
+ if m != 0 && !s.values[a.ID].rematerializeable && countRegs(s.values[a.ID].regs) == 1 {
+ r2 := pickReg(m)
+ c := p.NewValue1(a.Pos, OpCopy, a.Type, s.regs[r].c)
+ s.copies[c] = false
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("copy %s to %s : %s\n", a, c, &s.registers[r2])
+ }
+ s.setOrig(c, a)
+ s.assignReg(r2, a, c)
+ s.endRegs[p.ID] = append(s.endRegs[p.ID], endReg{r2, a, c})
+ }
+ }
+ s.freeReg(r)
+ }
+
+ // Copy phi ops into new schedule.
+ b.Values = append(b.Values, phis...)
+
+ // Third pass - pick registers for phis whose input
+ // was not in a register in the primary predecessor.
+ for i, v := range phis {
+ if !s.values[v.ID].needReg {
+ continue
+ }
+ if phiRegs[i] != noRegister {
+ continue
+ }
+ m := s.compatRegs(v.Type) &^ phiUsed &^ s.used
+ // If one of the other inputs of v is in a register, and the register is available,
+ // select this register, which can save some unnecessary copies.
+ for i, pe := range b.Preds {
+ if int32(i) == idx {
+ continue
+ }
+ ri := noRegister
+ for _, er := range s.endRegs[pe.b.ID] {
+ if er.v == s.orig[v.Args[i].ID] {
+ ri = er.r
+ break
+ }
+ }
+ if ri != noRegister && m>>ri&1 != 0 {
+ m = regMask(1) << ri
+ break
+ }
+ }
+ if m != 0 {
+ r := pickReg(m)
+ phiRegs[i] = r
+ phiUsed |= regMask(1) << r
+ }
+ }
+
+ // Set registers for phis. Add phi spill code.
+ for i, v := range phis {
+ if !s.values[v.ID].needReg {
+ continue
+ }
+ r := phiRegs[i]
+ if r == noRegister {
+ // stack-based phi
+ // Spills will be inserted in all the predecessors below.
+ s.values[v.ID].spill = v // v starts life spilled
+ continue
+ }
+ // register-based phi
+ s.assignReg(r, v, v)
+ }
+
+ // Deallocate any values which are no longer live. Phis are excluded.
+ for r := register(0); r < s.numRegs; r++ {
+ if phiUsed>>r&1 != 0 {
+ continue
+ }
+ v := s.regs[r].v
+ if v != nil && !regValLiveSet.contains(v.ID) {
+ s.freeReg(r)
+ }
+ }
+
+ // Save the starting state for use by merge edges.
+ // We append to a stack allocated variable that we'll
+ // later copy into s.startRegs in one fell swoop, to save
+ // on allocations.
+ regList := make([]startReg, 0, 32)
+ for r := register(0); r < s.numRegs; r++ {
+ v := s.regs[r].v
+ if v == nil {
+ continue
+ }
+ if phiUsed>>r&1 != 0 {
+ // Skip registers that phis used, we'll handle those
+ // specially during merge edge processing.
+ continue
+ }
+ regList = append(regList, startReg{r, v, s.regs[r].c, s.values[v.ID].uses.pos})
+ }
+ s.startRegs[b.ID] = make([]startReg, len(regList))
+ copy(s.startRegs[b.ID], regList)
+
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("after phis\n")
+ for _, x := range s.startRegs[b.ID] {
+ fmt.Printf(" %s: v%d\n", &s.registers[x.r], x.v.ID)
+ }
+ }
+ }
+
+ // Allocate space to record the desired registers for each value.
+ if l := len(oldSched); cap(dinfo) < l {
+ dinfo = make([]dentry, l)
+ } else {
+ dinfo = dinfo[:l]
+ for i := range dinfo {
+ dinfo[i] = dentry{}
+ }
+ }
+
+ // Load static desired register info at the end of the block.
+ desired.copy(&s.desired[b.ID])
+
+ // Check actual assigned registers at the start of the next block(s).
+ // Dynamically assigned registers will trump the static
+ // desired registers computed during liveness analysis.
+ // Note that we do this phase after startRegs is set above, so that
+ // we get the right behavior for a block which branches to itself.
+ for _, e := range b.Succs {
+ succ := e.b
+ // TODO: prioritize likely successor?
+ for _, x := range s.startRegs[succ.ID] {
+ desired.add(x.v.ID, x.r)
+ }
+ // Process phi ops in succ.
+ pidx := e.i
+ for _, v := range succ.Values {
+ if v.Op != OpPhi {
+ break
+ }
+ if !s.values[v.ID].needReg {
+ continue
+ }
+ rp, ok := s.f.getHome(v.ID).(*Register)
+ if !ok {
+ // If v is not assigned a register, pick a register assigned to one of v's inputs.
+ // Hopefully v will get assigned that register later.
+ // If the inputs have allocated register information, add it to desired,
+ // which may reduce spill or copy operations when the register is available.
+ for _, a := range v.Args {
+ rp, ok = s.f.getHome(a.ID).(*Register)
+ if ok {
+ break
+ }
+ }
+ if !ok {
+ continue
+ }
+ }
+ desired.add(v.Args[pidx].ID, register(rp.num))
+ }
+ }
+ // Walk values backwards computing desired register info.
+ // See computeLive for more comments.
+ for i := len(oldSched) - 1; i >= 0; i-- {
+ v := oldSched[i]
+ prefs := desired.remove(v.ID)
+ regspec := s.regspec(v.Op)
+ desired.clobber(regspec.clobbers)
+ for _, j := range regspec.inputs {
+ if countRegs(j.regs) != 1 {
+ continue
+ }
+ desired.clobber(j.regs)
+ desired.add(v.Args[j.idx].ID, pickReg(j.regs))
+ }
+ if opcodeTable[v.Op].resultInArg0 {
+ if opcodeTable[v.Op].commutative {
+ desired.addList(v.Args[1].ID, prefs)
+ }
+ desired.addList(v.Args[0].ID, prefs)
+ }
+ // Save desired registers for this value.
+ dinfo[i].out = prefs
+ for j, a := range v.Args {
+ if j >= len(dinfo[i].in) {
+ break
+ }
+ dinfo[i].in[j] = desired.get(a.ID)
+ }
+ }
+
+ // Process all the non-phi values.
+ for idx, v := range oldSched {
+ if s.f.pass.debug > regDebug {
+ fmt.Printf(" processing %s\n", v.LongString())
+ }
+ regspec := s.regspec(v.Op)
+ if v.Op == OpPhi {
+ f.Fatalf("phi %s not at start of block", v)
+ }
+ if v.Op == OpSP {
+ s.assignReg(s.SPReg, v, v)
+ b.Values = append(b.Values, v)
+ s.advanceUses(v)
+ s.sp = v.ID
+ continue
+ }
+ if v.Op == OpSB {
+ s.assignReg(s.SBReg, v, v)
+ b.Values = append(b.Values, v)
+ s.advanceUses(v)
+ s.sb = v.ID
+ continue
+ }
+ if v.Op == OpSelect0 || v.Op == OpSelect1 {
+ if s.values[v.ID].needReg {
+ var i = 0
+ if v.Op == OpSelect1 {
+ i = 1
+ }
+ s.assignReg(register(s.f.getHome(v.Args[0].ID).(LocPair)[i].(*Register).num), v, v)
+ }
+ b.Values = append(b.Values, v)
+ s.advanceUses(v)
+ goto issueSpill
+ }
+ if v.Op == OpGetG && s.f.Config.hasGReg {
+ // use hardware g register
+ if s.regs[s.GReg].v != nil {
+ s.freeReg(s.GReg) // kick out the old value
+ }
+ s.assignReg(s.GReg, v, v)
+ b.Values = append(b.Values, v)
+ s.advanceUses(v)
+ goto issueSpill
+ }
+ if v.Op == OpArg {
+ // Args are "pre-spilled" values. We don't allocate
+ // any register here. We just set up the spill pointer to
+ // point at itself and any later user will restore it to use it.
+ s.values[v.ID].spill = v
+ b.Values = append(b.Values, v)
+ s.advanceUses(v)
+ continue
+ }
+ if v.Op == OpKeepAlive {
+ // Make sure the argument to v is still live here.
+ s.advanceUses(v)
+ a := v.Args[0]
+ vi := &s.values[a.ID]
+ if vi.regs == 0 && !vi.rematerializeable {
+ // Use the spill location.
+ // This forces later liveness analysis to make the
+ // value live at this point.
+ v.SetArg(0, s.makeSpill(a, b))
+ } else if _, ok := a.Aux.(GCNode); ok && vi.rematerializeable {
+ // Rematerializeable value with a gc.Node. This is the address of
+ // a stack object (e.g. an LEAQ). Keep the object live.
+ // Change it to VarLive, which is what plive expects for locals.
+ v.Op = OpVarLive
+ v.SetArgs1(v.Args[1])
+ v.Aux = a.Aux
+ } else {
+ // In-register and rematerializeable values are already live.
+ // These are typically rematerializeable constants like nil,
+ // or values of a variable that were modified since the last call.
+ v.Op = OpCopy
+ v.SetArgs1(v.Args[1])
+ }
+ b.Values = append(b.Values, v)
+ continue
+ }
+ if len(regspec.inputs) == 0 && len(regspec.outputs) == 0 {
+ // No register allocation required (or none specified yet)
+ s.freeRegs(regspec.clobbers)
+ b.Values = append(b.Values, v)
+ s.advanceUses(v)
+ continue
+ }
+
+ if s.values[v.ID].rematerializeable {
+ // Value is rematerializeable, don't issue it here.
+ // It will get issued just before each use (see
+ // allocValueToReg).
+ for _, a := range v.Args {
+ a.Uses--
+ }
+ s.advanceUses(v)
+ continue
+ }
+
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("value %s\n", v.LongString())
+ fmt.Printf(" out:")
+ for _, r := range dinfo[idx].out {
+ if r != noRegister {
+ fmt.Printf(" %s", &s.registers[r])
+ }
+ }
+ fmt.Println()
+ for i := 0; i < len(v.Args) && i < 3; i++ {
+ fmt.Printf(" in%d:", i)
+ for _, r := range dinfo[idx].in[i] {
+ if r != noRegister {
+ fmt.Printf(" %s", &s.registers[r])
+ }
+ }
+ fmt.Println()
+ }
+ }
+
+ // Move arguments to registers. Process in an ordering defined
+ // by the register specification (most constrained first).
+ args = append(args[:0], v.Args...)
+ for _, i := range regspec.inputs {
+ mask := i.regs
+ if mask&s.values[args[i.idx].ID].regs == 0 {
+ // Need a new register for the input.
+ mask &= s.allocatable
+ mask &^= s.nospill
+ // Used desired register if available.
+ if i.idx < 3 {
+ for _, r := range dinfo[idx].in[i.idx] {
+ if r != noRegister && (mask&^s.used)>>r&1 != 0 {
+ // Desired register is allowed and unused.
+ mask = regMask(1) << r
+ break
+ }
+ }
+ }
+ // Avoid registers we're saving for other values.
+ if mask&^desired.avoid != 0 {
+ mask &^= desired.avoid
+ }
+ }
+ args[i.idx] = s.allocValToReg(args[i.idx], mask, true, v.Pos)
+ }
+
+ // If the output clobbers the input register, make sure we have
+ // at least two copies of the input register so we don't
+ // have to reload the value from the spill location.
+ if opcodeTable[v.Op].resultInArg0 {
+ var m regMask
+ if !s.liveAfterCurrentInstruction(v.Args[0]) {
+ // arg0 is dead. We can clobber its register.
+ goto ok
+ }
+ if opcodeTable[v.Op].commutative && !s.liveAfterCurrentInstruction(v.Args[1]) {
+ args[0], args[1] = args[1], args[0]
+ goto ok
+ }
+ if s.values[v.Args[0].ID].rematerializeable {
+ // We can rematerialize the input, don't worry about clobbering it.
+ goto ok
+ }
+ if opcodeTable[v.Op].commutative && s.values[v.Args[1].ID].rematerializeable {
+ args[0], args[1] = args[1], args[0]
+ goto ok
+ }
+ if countRegs(s.values[v.Args[0].ID].regs) >= 2 {
+ // we have at least 2 copies of arg0. We can afford to clobber one.
+ goto ok
+ }
+ if opcodeTable[v.Op].commutative && countRegs(s.values[v.Args[1].ID].regs) >= 2 {
+ args[0], args[1] = args[1], args[0]
+ goto ok
+ }
+
+ // We can't overwrite arg0 (or arg1, if commutative). So we
+ // need to make a copy of an input so we have a register we can modify.
+
+ // Possible new registers to copy into.
+ m = s.compatRegs(v.Args[0].Type) &^ s.used
+ if m == 0 {
+ // No free registers. In this case we'll just clobber
+ // an input and future uses of that input must use a restore.
+ // TODO(khr): We should really do this like allocReg does it,
+ // spilling the value with the most distant next use.
+ goto ok
+ }
+
+ // Try to move an input to the desired output.
+ for _, r := range dinfo[idx].out {
+ if r != noRegister && m>>r&1 != 0 {
+ m = regMask(1) << r
+ args[0] = s.allocValToReg(v.Args[0], m, true, v.Pos)
+ // Note: we update args[0] so the instruction will
+ // use the register copy we just made.
+ goto ok
+ }
+ }
+ // Try to copy input to its desired location & use its old
+ // location as the result register.
+ for _, r := range dinfo[idx].in[0] {
+ if r != noRegister && m>>r&1 != 0 {
+ m = regMask(1) << r
+ c := s.allocValToReg(v.Args[0], m, true, v.Pos)
+ s.copies[c] = false
+ // Note: no update to args[0] so the instruction will
+ // use the original copy.
+ goto ok
+ }
+ }
+ if opcodeTable[v.Op].commutative {
+ for _, r := range dinfo[idx].in[1] {
+ if r != noRegister && m>>r&1 != 0 {
+ m = regMask(1) << r
+ c := s.allocValToReg(v.Args[1], m, true, v.Pos)
+ s.copies[c] = false
+ args[0], args[1] = args[1], args[0]
+ goto ok
+ }
+ }
+ }
+ // Avoid future fixed uses if we can.
+ if m&^desired.avoid != 0 {
+ m &^= desired.avoid
+ }
+ // Save input 0 to a new register so we can clobber it.
+ c := s.allocValToReg(v.Args[0], m, true, v.Pos)
+ s.copies[c] = false
+ }
+
+ ok:
+ // Now that all args are in regs, we're ready to issue the value itself.
+ // Before we pick a register for the output value, allow input registers
+ // to be deallocated. We do this here so that the output can use the
+ // same register as a dying input.
+ if !opcodeTable[v.Op].resultNotInArgs {
+ s.tmpused = s.nospill
+ s.nospill = 0
+ s.advanceUses(v) // frees any registers holding args that are no longer live
+ }
+
+ // Dump any registers which will be clobbered
+ s.freeRegs(regspec.clobbers)
+ s.tmpused |= regspec.clobbers
+
+ // Pick registers for outputs.
+ {
+ outRegs := [2]register{noRegister, noRegister}
+ var used regMask
+ for _, out := range regspec.outputs {
+ mask := out.regs & s.allocatable &^ used
+ if mask == 0 {
+ continue
+ }
+ if opcodeTable[v.Op].resultInArg0 && out.idx == 0 {
+ if !opcodeTable[v.Op].commutative {
+ // Output must use the same register as input 0.
+ r := register(s.f.getHome(args[0].ID).(*Register).num)
+ mask = regMask(1) << r
+ } else {
+ // Output must use the same register as input 0 or 1.
+ r0 := register(s.f.getHome(args[0].ID).(*Register).num)
+ r1 := register(s.f.getHome(args[1].ID).(*Register).num)
+ // Check r0 and r1 for desired output register.
+ found := false
+ for _, r := range dinfo[idx].out {
+ if (r == r0 || r == r1) && (mask&^s.used)>>r&1 != 0 {
+ mask = regMask(1) << r
+ found = true
+ if r == r1 {
+ args[0], args[1] = args[1], args[0]
+ }
+ break
+ }
+ }
+ if !found {
+ // Neither are desired, pick r0.
+ mask = regMask(1) << r0
+ }
+ }
+ }
+ for _, r := range dinfo[idx].out {
+ if r != noRegister && (mask&^s.used)>>r&1 != 0 {
+ // Desired register is allowed and unused.
+ mask = regMask(1) << r
+ break
+ }
+ }
+ // Avoid registers we're saving for other values.
+ if mask&^desired.avoid&^s.nospill != 0 {
+ mask &^= desired.avoid
+ }
+ r := s.allocReg(mask, v)
+ outRegs[out.idx] = r
+ used |= regMask(1) << r
+ s.tmpused |= regMask(1) << r
+ }
+ // Record register choices
+ if v.Type.IsTuple() {
+ var outLocs LocPair
+ if r := outRegs[0]; r != noRegister {
+ outLocs[0] = &s.registers[r]
+ }
+ if r := outRegs[1]; r != noRegister {
+ outLocs[1] = &s.registers[r]
+ }
+ s.f.setHome(v, outLocs)
+ // Note that subsequent SelectX instructions will do the assignReg calls.
+ } else {
+ if r := outRegs[0]; r != noRegister {
+ s.assignReg(r, v, v)
+ }
+ }
+ }
+
+ // deallocate dead args, if we have not done so
+ if opcodeTable[v.Op].resultNotInArgs {
+ s.nospill = 0
+ s.advanceUses(v) // frees any registers holding args that are no longer live
+ }
+ s.tmpused = 0
+
+ // Issue the Value itself.
+ for i, a := range args {
+ v.SetArg(i, a) // use register version of arguments
+ }
+ b.Values = append(b.Values, v)
+
+ issueSpill:
+ }
+
+ // Copy the control values - we need this so we can reduce the
+ // uses property of these values later.
+ controls := append(make([]*Value, 0, 2), b.ControlValues()...)
+
+ // Load control values into registers.
+ for i, v := range b.ControlValues() {
+ if !s.values[v.ID].needReg {
+ continue
+ }
+ if s.f.pass.debug > regDebug {
+ fmt.Printf(" processing control %s\n", v.LongString())
+ }
+ // We assume that a control input can be passed in any
+ // type-compatible register. If this turns out not to be true,
+ // we'll need to introduce a regspec for a block's control value.
+ b.ReplaceControl(i, s.allocValToReg(v, s.compatRegs(v.Type), false, b.Pos))
+ }
+
+ // Reduce the uses of the control values once registers have been loaded.
+ // This loop is equivalent to the advanceUses method.
+ for _, v := range controls {
+ vi := &s.values[v.ID]
+ if !vi.needReg {
+ continue
+ }
+ // Remove this use from the uses list.
+ u := vi.uses
+ vi.uses = u.next
+ if u.next == nil {
+ s.freeRegs(vi.regs) // value is dead
+ }
+ u.next = s.freeUseRecords
+ s.freeUseRecords = u
+ }
+
+ // If we are approaching a merge point and we are the primary
+ // predecessor of it, find live values that we use soon after
+ // the merge point and promote them to registers now.
+ if len(b.Succs) == 1 {
+ if s.f.Config.hasGReg && s.regs[s.GReg].v != nil {
+ s.freeReg(s.GReg) // Spill value in G register before any merge.
+ }
+ // For this to be worthwhile, the loop must have no calls in it.
+ top := b.Succs[0].b
+ loop := s.loopnest.b2l[top.ID]
+ if loop == nil || loop.header != top || loop.containsUnavoidableCall {
+ goto badloop
+ }
+
+ // TODO: sort by distance, pick the closest ones?
+ for _, live := range s.live[b.ID] {
+ if live.dist >= unlikelyDistance {
+ // Don't preload anything live after the loop.
+ continue
+ }
+ vid := live.ID
+ vi := &s.values[vid]
+ if vi.regs != 0 {
+ continue
+ }
+ if vi.rematerializeable {
+ continue
+ }
+ v := s.orig[vid]
+ m := s.compatRegs(v.Type) &^ s.used
+ // Used desired register if available.
+ outerloop:
+ for _, e := range desired.entries {
+ if e.ID != v.ID {
+ continue
+ }
+ for _, r := range e.regs {
+ if r != noRegister && m>>r&1 != 0 {
+ m = regMask(1) << r
+ break outerloop
+ }
+ }
+ }
+ if m&^desired.avoid != 0 {
+ m &^= desired.avoid
+ }
+ if m != 0 {
+ s.allocValToReg(v, m, false, b.Pos)
+ }
+ }
+ }
+ badloop:
+ ;
+
+ // Save end-of-block register state.
+ // First count how many, this cuts allocations in half.
+ k := 0
+ for r := register(0); r < s.numRegs; r++ {
+ v := s.regs[r].v
+ if v == nil {
+ continue
+ }
+ k++
+ }
+ regList := make([]endReg, 0, k)
+ for r := register(0); r < s.numRegs; r++ {
+ v := s.regs[r].v
+ if v == nil {
+ continue
+ }
+ regList = append(regList, endReg{r, v, s.regs[r].c})
+ }
+ s.endRegs[b.ID] = regList
+
+ if checkEnabled {
+ regValLiveSet.clear()
+ for _, x := range s.live[b.ID] {
+ regValLiveSet.add(x.ID)
+ }
+ for r := register(0); r < s.numRegs; r++ {
+ v := s.regs[r].v
+ if v == nil {
+ continue
+ }
+ if !regValLiveSet.contains(v.ID) {
+ s.f.Fatalf("val %s is in reg but not live at end of %s", v, b)
+ }
+ }
+ }
+
+ // If a value is live at the end of the block and
+ // isn't in a register, generate a use for the spill location.
+ // We need to remember this information so that
+ // the liveness analysis in stackalloc is correct.
+ for _, e := range s.live[b.ID] {
+ vi := &s.values[e.ID]
+ if vi.regs != 0 {
+ // in a register, we'll use that source for the merge.
+ continue
+ }
+ if vi.rematerializeable {
+ // we'll rematerialize during the merge.
+ continue
+ }
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("live-at-end spill for %s at %s\n", s.orig[e.ID], b)
+ }
+ spill := s.makeSpill(s.orig[e.ID], b)
+ s.spillLive[b.ID] = append(s.spillLive[b.ID], spill.ID)
+ }
+
+ // Clear any final uses.
+ // All that is left should be the pseudo-uses added for values which
+ // are live at the end of b.
+ for _, e := range s.live[b.ID] {
+ u := s.values[e.ID].uses
+ if u == nil {
+ f.Fatalf("live at end, no uses v%d", e.ID)
+ }
+ if u.next != nil {
+ f.Fatalf("live at end, too many uses v%d", e.ID)
+ }
+ s.values[e.ID].uses = nil
+ u.next = s.freeUseRecords
+ s.freeUseRecords = u
+ }
+ }
+
+ // Decide where the spills we generated will go.
+ s.placeSpills()
+
+ // Anything that didn't get a register gets a stack location here.
+ // (StoreReg, stack-based phis, inputs, ...)
+ stacklive := stackalloc(s.f, s.spillLive)
+
+ // Fix up all merge edges.
+ s.shuffle(stacklive)
+
+ // Erase any copies we never used.
+ // Also, an unused copy might be the only use of another copy,
+ // so continue erasing until we reach a fixed point.
+ for {
+ progress := false
+ for c, used := range s.copies {
+ if !used && c.Uses == 0 {
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("delete copied value %s\n", c.LongString())
+ }
+ c.RemoveArg(0)
+ f.freeValue(c)
+ delete(s.copies, c)
+ progress = true
+ }
+ }
+ if !progress {
+ break
+ }
+ }
+
+ for _, b := range s.visitOrder {
+ i := 0
+ for _, v := range b.Values {
+ if v.Op == OpInvalid {
+ continue
+ }
+ b.Values[i] = v
+ i++
+ }
+ b.Values = b.Values[:i]
+ }
+}
+
+func (s *regAllocState) placeSpills() {
+ f := s.f
+
+ // Precompute some useful info.
+ phiRegs := make([]regMask, f.NumBlocks())
+ for _, b := range s.visitOrder {
+ var m regMask
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ break
+ }
+ if r, ok := f.getHome(v.ID).(*Register); ok {
+ m |= regMask(1) << uint(r.num)
+ }
+ }
+ phiRegs[b.ID] = m
+ }
+
+ // Start maps block IDs to the list of spills
+ // that go at the start of the block (but after any phis).
+ start := map[ID][]*Value{}
+ // After maps value IDs to the list of spills
+ // that go immediately after that value ID.
+ after := map[ID][]*Value{}
+
+ for i := range s.values {
+ vi := s.values[i]
+ spill := vi.spill
+ if spill == nil {
+ continue
+ }
+ if spill.Block != nil {
+ // Some spills are already fully set up,
+ // like OpArgs and stack-based phis.
+ continue
+ }
+ v := s.orig[i]
+
+ // Walk down the dominator tree looking for a good place to
+ // put the spill of v. At the start "best" is the best place
+ // we have found so far.
+ // TODO: find a way to make this O(1) without arbitrary cutoffs.
+ best := v.Block
+ bestArg := v
+ var bestDepth int16
+ if l := s.loopnest.b2l[best.ID]; l != nil {
+ bestDepth = l.depth
+ }
+ b := best
+ const maxSpillSearch = 100
+ for i := 0; i < maxSpillSearch; i++ {
+ // Find the child of b in the dominator tree which
+ // dominates all restores.
+ p := b
+ b = nil
+ for c := s.sdom.Child(p); c != nil && i < maxSpillSearch; c, i = s.sdom.Sibling(c), i+1 {
+ if s.sdom[c.ID].entry <= vi.restoreMin && s.sdom[c.ID].exit >= vi.restoreMax {
+ // c also dominates all restores. Walk down into c.
+ b = c
+ break
+ }
+ }
+ if b == nil {
+ // Ran out of blocks which dominate all restores.
+ break
+ }
+
+ var depth int16
+ if l := s.loopnest.b2l[b.ID]; l != nil {
+ depth = l.depth
+ }
+ if depth > bestDepth {
+ // Don't push the spill into a deeper loop.
+ continue
+ }
+
+ // If v is in a register at the start of b, we can
+ // place the spill here (after the phis).
+ if len(b.Preds) == 1 {
+ for _, e := range s.endRegs[b.Preds[0].b.ID] {
+ if e.v == v {
+ // Found a better spot for the spill.
+ best = b
+ bestArg = e.c
+ bestDepth = depth
+ break
+ }
+ }
+ } else {
+ for _, e := range s.startRegs[b.ID] {
+ if e.v == v {
+ // Found a better spot for the spill.
+ best = b
+ bestArg = e.c
+ bestDepth = depth
+ break
+ }
+ }
+ }
+ }
+
+ // Put the spill in the best block we found.
+ spill.Block = best
+ spill.AddArg(bestArg)
+ if best == v.Block && v.Op != OpPhi {
+ // Place immediately after v.
+ after[v.ID] = append(after[v.ID], spill)
+ } else {
+ // Place at the start of best block.
+ start[best.ID] = append(start[best.ID], spill)
+ }
+ }
+
+ // Insert spill instructions into the block schedules.
+ var oldSched []*Value
+ for _, b := range s.visitOrder {
+ nphi := 0
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ break
+ }
+ nphi++
+ }
+ oldSched = append(oldSched[:0], b.Values[nphi:]...)
+ b.Values = b.Values[:nphi]
+ b.Values = append(b.Values, start[b.ID]...)
+ for _, v := range oldSched {
+ b.Values = append(b.Values, v)
+ b.Values = append(b.Values, after[v.ID]...)
+ }
+ }
+}
+
+// shuffle fixes up all the merge edges (those going into blocks of indegree > 1).
+func (s *regAllocState) shuffle(stacklive [][]ID) {
+ var e edgeState
+ e.s = s
+ e.cache = map[ID][]*Value{}
+ e.contents = map[Location]contentRecord{}
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("shuffle %s\n", s.f.Name)
+ fmt.Println(s.f.String())
+ }
+
+ for _, b := range s.visitOrder {
+ if len(b.Preds) <= 1 {
+ continue
+ }
+ e.b = b
+ for i, edge := range b.Preds {
+ p := edge.b
+ e.p = p
+ e.setup(i, s.endRegs[p.ID], s.startRegs[b.ID], stacklive[p.ID])
+ e.process()
+ }
+ }
+
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("post shuffle %s\n", s.f.Name)
+ fmt.Println(s.f.String())
+ }
+}
+
+type edgeState struct {
+ s *regAllocState
+ p, b *Block // edge goes from p->b.
+
+ // for each pre-regalloc value, a list of equivalent cached values
+ cache map[ID][]*Value
+ cachedVals []ID // (superset of) keys of the above map, for deterministic iteration
+
+ // map from location to the value it contains
+ contents map[Location]contentRecord
+
+ // desired destination locations
+ destinations []dstRecord
+ extra []dstRecord
+
+ usedRegs regMask // registers currently holding something
+ uniqueRegs regMask // registers holding the only copy of a value
+ finalRegs regMask // registers holding final target
+ rematerializeableRegs regMask // registers that hold rematerializeable values
+}
+
+type contentRecord struct {
+ vid ID // pre-regalloc value
+ c *Value // cached value
+ final bool // this is a satisfied destination
+ pos src.XPos // source position of use of the value
+}
+
+type dstRecord struct {
+ loc Location // register or stack slot
+ vid ID // pre-regalloc value it should contain
+ splice **Value // place to store reference to the generating instruction
+ pos src.XPos // source position of use of this location
+}
+
+// setup initializes the edge state for shuffling.
+func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive []ID) {
+ if e.s.f.pass.debug > regDebug {
+ fmt.Printf("edge %s->%s\n", e.p, e.b)
+ }
+
+ // Clear state.
+ for _, vid := range e.cachedVals {
+ delete(e.cache, vid)
+ }
+ e.cachedVals = e.cachedVals[:0]
+ for k := range e.contents {
+ delete(e.contents, k)
+ }
+ e.usedRegs = 0
+ e.uniqueRegs = 0
+ e.finalRegs = 0
+ e.rematerializeableRegs = 0
+
+ // Live registers can be sources.
+ for _, x := range srcReg {
+ e.set(&e.s.registers[x.r], x.v.ID, x.c, false, src.NoXPos) // don't care the position of the source
+ }
+ // So can all of the spill locations.
+ for _, spillID := range stacklive {
+ v := e.s.orig[spillID]
+ spill := e.s.values[v.ID].spill
+ if !e.s.sdom.IsAncestorEq(spill.Block, e.p) {
+ // Spills were placed that only dominate the uses found
+ // during the first regalloc pass. The edge fixup code
+ // can't use a spill location if the spill doesn't dominate
+ // the edge.
+ // We are guaranteed that if the spill doesn't dominate this edge,
+ // then the value is available in a register (because we called
+ // makeSpill for every value not in a register at the start
+ // of an edge).
+ continue
+ }
+ e.set(e.s.f.getHome(spillID), v.ID, spill, false, src.NoXPos) // don't care the position of the source
+ }
+
+ // Figure out all the destinations we need.
+ dsts := e.destinations[:0]
+ for _, x := range dstReg {
+ dsts = append(dsts, dstRecord{&e.s.registers[x.r], x.v.ID, nil, x.pos})
+ }
+ // Phis need their args to end up in a specific location.
+ for _, v := range e.b.Values {
+ if v.Op != OpPhi {
+ break
+ }
+ loc := e.s.f.getHome(v.ID)
+ if loc == nil {
+ continue
+ }
+ dsts = append(dsts, dstRecord{loc, v.Args[idx].ID, &v.Args[idx], v.Pos})
+ }
+ e.destinations = dsts
+
+ if e.s.f.pass.debug > regDebug {
+ for _, vid := range e.cachedVals {
+ a := e.cache[vid]
+ for _, c := range a {
+ fmt.Printf("src %s: v%d cache=%s\n", e.s.f.getHome(c.ID), vid, c)
+ }
+ }
+ for _, d := range e.destinations {
+ fmt.Printf("dst %s: v%d\n", d.loc, d.vid)
+ }
+ }
+}
+
+// process generates code to move all the values to the right destination locations.
+func (e *edgeState) process() {
+ dsts := e.destinations
+
+ // Process the destinations until they are all satisfied.
+ for len(dsts) > 0 {
+ i := 0
+ for _, d := range dsts {
+ if !e.processDest(d.loc, d.vid, d.splice, d.pos) {
+ // Failed - save for next iteration.
+ dsts[i] = d
+ i++
+ }
+ }
+ if i < len(dsts) {
+ // Made some progress. Go around again.
+ dsts = dsts[:i]
+
+ // Append any extras destinations we generated.
+ dsts = append(dsts, e.extra...)
+ e.extra = e.extra[:0]
+ continue
+ }
+
+ // We made no progress. That means that any
+ // remaining unsatisfied moves are in simple cycles.
+ // For example, A -> B -> C -> D -> A.
+ // A ----> B
+ // ^ |
+ // | |
+ // | v
+ // D <---- C
+
+ // To break the cycle, we pick an unused register, say R,
+ // and put a copy of B there.
+ // A ----> B
+ // ^ |
+ // | |
+ // | v
+ // D <---- C <---- R=copyofB
+ // When we resume the outer loop, the A->B move can now proceed,
+ // and eventually the whole cycle completes.
+
+ // Copy any cycle location to a temp register. This duplicates
+ // one of the cycle entries, allowing the just duplicated value
+ // to be overwritten and the cycle to proceed.
+ d := dsts[0]
+ loc := d.loc
+ vid := e.contents[loc].vid
+ c := e.contents[loc].c
+ r := e.findRegFor(c.Type)
+ if e.s.f.pass.debug > regDebug {
+ fmt.Printf("breaking cycle with v%d in %s:%s\n", vid, loc, c)
+ }
+ e.erase(r)
+ pos := d.pos.WithNotStmt()
+ if _, isReg := loc.(*Register); isReg {
+ c = e.p.NewValue1(pos, OpCopy, c.Type, c)
+ } else {
+ c = e.p.NewValue1(pos, OpLoadReg, c.Type, c)
+ }
+ e.set(r, vid, c, false, pos)
+ if c.Op == OpLoadReg && e.s.isGReg(register(r.(*Register).num)) {
+ e.s.f.Fatalf("process.OpLoadReg targeting g: " + c.LongString())
+ }
+ }
+}
+
+// processDest generates code to put value vid into location loc. Returns true
+// if progress was made.
+func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XPos) bool {
+ pos = pos.WithNotStmt()
+ occupant := e.contents[loc]
+ if occupant.vid == vid {
+ // Value is already in the correct place.
+ e.contents[loc] = contentRecord{vid, occupant.c, true, pos}
+ if splice != nil {
+ (*splice).Uses--
+ *splice = occupant.c
+ occupant.c.Uses++
+ }
+ // Note: if splice==nil then c will appear dead. This is
+ // non-SSA formed code, so be careful after this pass not to run
+ // deadcode elimination.
+ if _, ok := e.s.copies[occupant.c]; ok {
+ // The copy at occupant.c was used to avoid spill.
+ e.s.copies[occupant.c] = true
+ }
+ return true
+ }
+
+ // Check if we're allowed to clobber the destination location.
+ if len(e.cache[occupant.vid]) == 1 && !e.s.values[occupant.vid].rematerializeable {
+ // We can't overwrite the last copy
+ // of a value that needs to survive.
+ return false
+ }
+
+ // Copy from a source of v, register preferred.
+ v := e.s.orig[vid]
+ var c *Value
+ var src Location
+ if e.s.f.pass.debug > regDebug {
+ fmt.Printf("moving v%d to %s\n", vid, loc)
+ fmt.Printf("sources of v%d:", vid)
+ }
+ for _, w := range e.cache[vid] {
+ h := e.s.f.getHome(w.ID)
+ if e.s.f.pass.debug > regDebug {
+ fmt.Printf(" %s:%s", h, w)
+ }
+ _, isreg := h.(*Register)
+ if src == nil || isreg {
+ c = w
+ src = h
+ }
+ }
+ if e.s.f.pass.debug > regDebug {
+ if src != nil {
+ fmt.Printf(" [use %s]\n", src)
+ } else {
+ fmt.Printf(" [no source]\n")
+ }
+ }
+ _, dstReg := loc.(*Register)
+
+ // Pre-clobber destination. This avoids the
+ // following situation:
+ // - v is currently held in R0 and stacktmp0.
+ // - We want to copy stacktmp1 to stacktmp0.
+ // - We choose R0 as the temporary register.
+ // During the copy, both R0 and stacktmp0 are
+ // clobbered, losing both copies of v. Oops!
+ // Erasing the destination early means R0 will not
+ // be chosen as the temp register, as it will then
+ // be the last copy of v.
+ e.erase(loc)
+ var x *Value
+ if c == nil || e.s.values[vid].rematerializeable {
+ if !e.s.values[vid].rematerializeable {
+ e.s.f.Fatalf("can't find source for %s->%s: %s\n", e.p, e.b, v.LongString())
+ }
+ if dstReg {
+ x = v.copyInto(e.p)
+ } else {
+ // Rematerialize into stack slot. Need a free
+ // register to accomplish this.
+ r := e.findRegFor(v.Type)
+ e.erase(r)
+ x = v.copyIntoWithXPos(e.p, pos)
+ e.set(r, vid, x, false, pos)
+ // Make sure we spill with the size of the slot, not the
+ // size of x (which might be wider due to our dropping
+ // of narrowing conversions).
+ x = e.p.NewValue1(pos, OpStoreReg, loc.(LocalSlot).Type, x)
+ }
+ } else {
+ // Emit move from src to dst.
+ _, srcReg := src.(*Register)
+ if srcReg {
+ if dstReg {
+ x = e.p.NewValue1(pos, OpCopy, c.Type, c)
+ } else {
+ x = e.p.NewValue1(pos, OpStoreReg, loc.(LocalSlot).Type, c)
+ }
+ } else {
+ if dstReg {
+ x = e.p.NewValue1(pos, OpLoadReg, c.Type, c)
+ } else {
+ // mem->mem. Use temp register.
+ r := e.findRegFor(c.Type)
+ e.erase(r)
+ t := e.p.NewValue1(pos, OpLoadReg, c.Type, c)
+ e.set(r, vid, t, false, pos)
+ x = e.p.NewValue1(pos, OpStoreReg, loc.(LocalSlot).Type, t)
+ }
+ }
+ }
+ e.set(loc, vid, x, true, pos)
+ if x.Op == OpLoadReg && e.s.isGReg(register(loc.(*Register).num)) {
+ e.s.f.Fatalf("processDest.OpLoadReg targeting g: " + x.LongString())
+ }
+ if splice != nil {
+ (*splice).Uses--
+ *splice = x
+ x.Uses++
+ }
+ return true
+}
+
+// set changes the contents of location loc to hold the given value and its cached representative.
+func (e *edgeState) set(loc Location, vid ID, c *Value, final bool, pos src.XPos) {
+ e.s.f.setHome(c, loc)
+ e.contents[loc] = contentRecord{vid, c, final, pos}
+ a := e.cache[vid]
+ if len(a) == 0 {
+ e.cachedVals = append(e.cachedVals, vid)
+ }
+ a = append(a, c)
+ e.cache[vid] = a
+ if r, ok := loc.(*Register); ok {
+ if e.usedRegs&(regMask(1)<<uint(r.num)) != 0 {
+ e.s.f.Fatalf("%v is already set (v%d/%v)", r, vid, c)
+ }
+ e.usedRegs |= regMask(1) << uint(r.num)
+ if final {
+ e.finalRegs |= regMask(1) << uint(r.num)
+ }
+ if len(a) == 1 {
+ e.uniqueRegs |= regMask(1) << uint(r.num)
+ }
+ if len(a) == 2 {
+ if t, ok := e.s.f.getHome(a[0].ID).(*Register); ok {
+ e.uniqueRegs &^= regMask(1) << uint(t.num)
+ }
+ }
+ if e.s.values[vid].rematerializeable {
+ e.rematerializeableRegs |= regMask(1) << uint(r.num)
+ }
+ }
+ if e.s.f.pass.debug > regDebug {
+ fmt.Printf("%s\n", c.LongString())
+ fmt.Printf("v%d now available in %s:%s\n", vid, loc, c)
+ }
+}
+
+// erase removes any user of loc.
+func (e *edgeState) erase(loc Location) {
+ cr := e.contents[loc]
+ if cr.c == nil {
+ return
+ }
+ vid := cr.vid
+
+ if cr.final {
+ // Add a destination to move this value back into place.
+ // Make sure it gets added to the tail of the destination queue
+ // so we make progress on other moves first.
+ e.extra = append(e.extra, dstRecord{loc, cr.vid, nil, cr.pos})
+ }
+
+ // Remove c from the list of cached values.
+ a := e.cache[vid]
+ for i, c := range a {
+ if e.s.f.getHome(c.ID) == loc {
+ if e.s.f.pass.debug > regDebug {
+ fmt.Printf("v%d no longer available in %s:%s\n", vid, loc, c)
+ }
+ a[i], a = a[len(a)-1], a[:len(a)-1]
+ break
+ }
+ }
+ e.cache[vid] = a
+
+ // Update register masks.
+ if r, ok := loc.(*Register); ok {
+ e.usedRegs &^= regMask(1) << uint(r.num)
+ if cr.final {
+ e.finalRegs &^= regMask(1) << uint(r.num)
+ }
+ e.rematerializeableRegs &^= regMask(1) << uint(r.num)
+ }
+ if len(a) == 1 {
+ if r, ok := e.s.f.getHome(a[0].ID).(*Register); ok {
+ e.uniqueRegs |= regMask(1) << uint(r.num)
+ }
+ }
+}
+
+// findRegFor finds a register we can use to make a temp copy of type typ.
+func (e *edgeState) findRegFor(typ *types.Type) Location {
+ // Which registers are possibilities.
+ types := &e.s.f.Config.Types
+ m := e.s.compatRegs(typ)
+
+ // Pick a register. In priority order:
+ // 1) an unused register
+ // 2) a non-unique register not holding a final value
+ // 3) a non-unique register
+ // 4) a register holding a rematerializeable value
+ x := m &^ e.usedRegs
+ if x != 0 {
+ return &e.s.registers[pickReg(x)]
+ }
+ x = m &^ e.uniqueRegs &^ e.finalRegs
+ if x != 0 {
+ return &e.s.registers[pickReg(x)]
+ }
+ x = m &^ e.uniqueRegs
+ if x != 0 {
+ return &e.s.registers[pickReg(x)]
+ }
+ x = m & e.rematerializeableRegs
+ if x != 0 {
+ return &e.s.registers[pickReg(x)]
+ }
+
+ // No register is available.
+ // Pick a register to spill.
+ for _, vid := range e.cachedVals {
+ a := e.cache[vid]
+ for _, c := range a {
+ if r, ok := e.s.f.getHome(c.ID).(*Register); ok && m>>uint(r.num)&1 != 0 {
+ if !c.rematerializeable() {
+ x := e.p.NewValue1(c.Pos, OpStoreReg, c.Type, c)
+ // Allocate a temp location to spill a register to.
+ // The type of the slot is immaterial - it will not be live across
+ // any safepoint. Just use a type big enough to hold any register.
+ t := LocalSlot{N: e.s.f.fe.Auto(c.Pos, types.Int64), Type: types.Int64}
+ // TODO: reuse these slots. They'll need to be erased first.
+ e.set(t, vid, x, false, c.Pos)
+ if e.s.f.pass.debug > regDebug {
+ fmt.Printf(" SPILL %s->%s %s\n", r, t, x.LongString())
+ }
+ }
+ // r will now be overwritten by the caller. At some point
+ // later, the newly saved value will be moved back to its
+ // final destination in processDest.
+ return r
+ }
+ }
+ }
+
+ fmt.Printf("m:%d unique:%d final:%d rematerializable:%d\n", m, e.uniqueRegs, e.finalRegs, e.rematerializeableRegs)
+ for _, vid := range e.cachedVals {
+ a := e.cache[vid]
+ for _, c := range a {
+ fmt.Printf("v%d: %s %s\n", vid, c, e.s.f.getHome(c.ID))
+ }
+ }
+ e.s.f.Fatalf("can't find empty register on edge %s->%s", e.p, e.b)
+ return nil
+}
+
+// rematerializeable reports whether the register allocator should recompute
+// a value instead of spilling/restoring it.
+func (v *Value) rematerializeable() bool {
+ if !opcodeTable[v.Op].rematerializeable {
+ return false
+ }
+ for _, a := range v.Args {
+ // SP and SB (generated by OpSP and OpSB) are always available.
+ if a.Op != OpSP && a.Op != OpSB {
+ return false
+ }
+ }
+ return true
+}
+
+type liveInfo struct {
+ ID ID // ID of value
+ dist int32 // # of instructions before next use
+ pos src.XPos // source position of next use
+}
+
+// computeLive computes a map from block ID to a list of value IDs live at the end
+// of that block. Together with the value ID is a count of how many instructions
+// to the next use of that value. The resulting map is stored in s.live.
+// computeLive also computes the desired register information at the end of each block.
+// This desired register information is stored in s.desired.
+// TODO: this could be quadratic if lots of variables are live across lots of
+// basic blocks. Figure out a way to make this function (or, more precisely, the user
+// of this function) require only linear size & time.
+func (s *regAllocState) computeLive() {
+ f := s.f
+ s.live = make([][]liveInfo, f.NumBlocks())
+ s.desired = make([]desiredState, f.NumBlocks())
+ var phis []*Value
+
+ live := f.newSparseMap(f.NumValues())
+ defer f.retSparseMap(live)
+ t := f.newSparseMap(f.NumValues())
+ defer f.retSparseMap(t)
+
+ // Keep track of which value we want in each register.
+ var desired desiredState
+
+ // Instead of iterating over f.Blocks, iterate over their postordering.
+ // Liveness information flows backward, so starting at the end
+ // increases the probability that we will stabilize quickly.
+ // TODO: Do a better job yet. Here's one possibility:
+ // Calculate the dominator tree and locate all strongly connected components.
+ // If a value is live in one block of an SCC, it is live in all.
+ // Walk the dominator tree from end to beginning, just once, treating SCC
+ // components as single blocks, duplicated calculated liveness information
+ // out to all of them.
+ po := f.postorder()
+ s.loopnest = f.loopnest()
+ s.loopnest.calculateDepths()
+ for {
+ changed := false
+
+ for _, b := range po {
+ // Start with known live values at the end of the block.
+ // Add len(b.Values) to adjust from end-of-block distance
+ // to beginning-of-block distance.
+ live.clear()
+ for _, e := range s.live[b.ID] {
+ live.set(e.ID, e.dist+int32(len(b.Values)), e.pos)
+ }
+
+ // Mark control values as live
+ for _, c := range b.ControlValues() {
+ if s.values[c.ID].needReg {
+ live.set(c.ID, int32(len(b.Values)), b.Pos)
+ }
+ }
+
+ // Propagate backwards to the start of the block
+ // Assumes Values have been scheduled.
+ phis = phis[:0]
+ for i := len(b.Values) - 1; i >= 0; i-- {
+ v := b.Values[i]
+ live.remove(v.ID)
+ if v.Op == OpPhi {
+ // save phi ops for later
+ phis = append(phis, v)
+ continue
+ }
+ if opcodeTable[v.Op].call {
+ c := live.contents()
+ for i := range c {
+ c[i].val += unlikelyDistance
+ }
+ }
+ for _, a := range v.Args {
+ if s.values[a.ID].needReg {
+ live.set(a.ID, int32(i), v.Pos)
+ }
+ }
+ }
+ // Propagate desired registers backwards.
+ desired.copy(&s.desired[b.ID])
+ for i := len(b.Values) - 1; i >= 0; i-- {
+ v := b.Values[i]
+ prefs := desired.remove(v.ID)
+ if v.Op == OpPhi {
+ // TODO: if v is a phi, save desired register for phi inputs.
+ // For now, we just drop it and don't propagate
+ // desired registers back though phi nodes.
+ continue
+ }
+ regspec := s.regspec(v.Op)
+ // Cancel desired registers if they get clobbered.
+ desired.clobber(regspec.clobbers)
+ // Update desired registers if there are any fixed register inputs.
+ for _, j := range regspec.inputs {
+ if countRegs(j.regs) != 1 {
+ continue
+ }
+ desired.clobber(j.regs)
+ desired.add(v.Args[j.idx].ID, pickReg(j.regs))
+ }
+ // Set desired register of input 0 if this is a 2-operand instruction.
+ if opcodeTable[v.Op].resultInArg0 {
+ if opcodeTable[v.Op].commutative {
+ desired.addList(v.Args[1].ID, prefs)
+ }
+ desired.addList(v.Args[0].ID, prefs)
+ }
+ }
+
+ // For each predecessor of b, expand its list of live-at-end values.
+ // invariant: live contains the values live at the start of b (excluding phi inputs)
+ for i, e := range b.Preds {
+ p := e.b
+ // Compute additional distance for the edge.
+ // Note: delta must be at least 1 to distinguish the control
+ // value use from the first user in a successor block.
+ delta := int32(normalDistance)
+ if len(p.Succs) == 2 {
+ if p.Succs[0].b == b && p.Likely == BranchLikely ||
+ p.Succs[1].b == b && p.Likely == BranchUnlikely {
+ delta = likelyDistance
+ }
+ if p.Succs[0].b == b && p.Likely == BranchUnlikely ||
+ p.Succs[1].b == b && p.Likely == BranchLikely {
+ delta = unlikelyDistance
+ }
+ }
+
+ // Update any desired registers at the end of p.
+ s.desired[p.ID].merge(&desired)
+
+ // Start t off with the previously known live values at the end of p.
+ t.clear()
+ for _, e := range s.live[p.ID] {
+ t.set(e.ID, e.dist, e.pos)
+ }
+ update := false
+
+ // Add new live values from scanning this block.
+ for _, e := range live.contents() {
+ d := e.val + delta
+ if !t.contains(e.key) || d < t.get(e.key) {
+ update = true
+ t.set(e.key, d, e.aux)
+ }
+ }
+ // Also add the correct arg from the saved phi values.
+ // All phis are at distance delta (we consider them
+ // simultaneously happening at the start of the block).
+ for _, v := range phis {
+ id := v.Args[i].ID
+ if s.values[id].needReg && (!t.contains(id) || delta < t.get(id)) {
+ update = true
+ t.set(id, delta, v.Pos)
+ }
+ }
+
+ if !update {
+ continue
+ }
+ // The live set has changed, update it.
+ l := s.live[p.ID][:0]
+ if cap(l) < t.size() {
+ l = make([]liveInfo, 0, t.size())
+ }
+ for _, e := range t.contents() {
+ l = append(l, liveInfo{e.key, e.val, e.aux})
+ }
+ s.live[p.ID] = l
+ changed = true
+ }
+ }
+
+ if !changed {
+ break
+ }
+ }
+ if f.pass.debug > regDebug {
+ fmt.Println("live values at end of each block")
+ for _, b := range f.Blocks {
+ fmt.Printf(" %s:", b)
+ for _, x := range s.live[b.ID] {
+ fmt.Printf(" v%d(%d)", x.ID, x.dist)
+ for _, e := range s.desired[b.ID].entries {
+ if e.ID != x.ID {
+ continue
+ }
+ fmt.Printf("[")
+ first := true
+ for _, r := range e.regs {
+ if r == noRegister {
+ continue
+ }
+ if !first {
+ fmt.Printf(",")
+ }
+ fmt.Print(&s.registers[r])
+ first = false
+ }
+ fmt.Printf("]")
+ }
+ }
+ if avoid := s.desired[b.ID].avoid; avoid != 0 {
+ fmt.Printf(" avoid=%v", s.RegMaskString(avoid))
+ }
+ fmt.Println()
+ }
+ }
+}
+
+// A desiredState represents desired register assignments.
+type desiredState struct {
+ // Desired assignments will be small, so we just use a list
+ // of valueID+registers entries.
+ entries []desiredStateEntry
+ // Registers that other values want to be in. This value will
+ // contain at least the union of the regs fields of entries, but
+ // may contain additional entries for values that were once in
+ // this data structure but are no longer.
+ avoid regMask
+}
+type desiredStateEntry struct {
+ // (pre-regalloc) value
+ ID ID
+ // Registers it would like to be in, in priority order.
+ // Unused slots are filled with noRegister.
+ regs [4]register
+}
+
+func (d *desiredState) clear() {
+ d.entries = d.entries[:0]
+ d.avoid = 0
+}
+
+// get returns a list of desired registers for value vid.
+func (d *desiredState) get(vid ID) [4]register {
+ for _, e := range d.entries {
+ if e.ID == vid {
+ return e.regs
+ }
+ }
+ return [4]register{noRegister, noRegister, noRegister, noRegister}
+}
+
+// add records that we'd like value vid to be in register r.
+func (d *desiredState) add(vid ID, r register) {
+ d.avoid |= regMask(1) << r
+ for i := range d.entries {
+ e := &d.entries[i]
+ if e.ID != vid {
+ continue
+ }
+ if e.regs[0] == r {
+ // Already known and highest priority
+ return
+ }
+ for j := 1; j < len(e.regs); j++ {
+ if e.regs[j] == r {
+ // Move from lower priority to top priority
+ copy(e.regs[1:], e.regs[:j])
+ e.regs[0] = r
+ return
+ }
+ }
+ copy(e.regs[1:], e.regs[:])
+ e.regs[0] = r
+ return
+ }
+ d.entries = append(d.entries, desiredStateEntry{vid, [4]register{r, noRegister, noRegister, noRegister}})
+}
+
+func (d *desiredState) addList(vid ID, regs [4]register) {
+ // regs is in priority order, so iterate in reverse order.
+ for i := len(regs) - 1; i >= 0; i-- {
+ r := regs[i]
+ if r != noRegister {
+ d.add(vid, r)
+ }
+ }
+}
+
+// clobber erases any desired registers in the set m.
+func (d *desiredState) clobber(m regMask) {
+ for i := 0; i < len(d.entries); {
+ e := &d.entries[i]
+ j := 0
+ for _, r := range e.regs {
+ if r != noRegister && m>>r&1 == 0 {
+ e.regs[j] = r
+ j++
+ }
+ }
+ if j == 0 {
+ // No more desired registers for this value.
+ d.entries[i] = d.entries[len(d.entries)-1]
+ d.entries = d.entries[:len(d.entries)-1]
+ continue
+ }
+ for ; j < len(e.regs); j++ {
+ e.regs[j] = noRegister
+ }
+ i++
+ }
+ d.avoid &^= m
+}
+
+// copy copies a desired state from another desiredState x.
+func (d *desiredState) copy(x *desiredState) {
+ d.entries = append(d.entries[:0], x.entries...)
+ d.avoid = x.avoid
+}
+
+// remove removes the desired registers for vid and returns them.
+func (d *desiredState) remove(vid ID) [4]register {
+ for i := range d.entries {
+ if d.entries[i].ID == vid {
+ regs := d.entries[i].regs
+ d.entries[i] = d.entries[len(d.entries)-1]
+ d.entries = d.entries[:len(d.entries)-1]
+ return regs
+ }
+ }
+ return [4]register{noRegister, noRegister, noRegister, noRegister}
+}
+
+// merge merges another desired state x into d.
+func (d *desiredState) merge(x *desiredState) {
+ d.avoid |= x.avoid
+ // There should only be a few desired registers, so
+ // linear insert is ok.
+ for _, e := range x.entries {
+ d.addList(e.ID, e.regs)
+ }
+}
+
+func min32(x, y int32) int32 {
+ if x < y {
+ return x
+ }
+ return y
+}
+func max32(x, y int32) int32 {
+ if x > y {
+ return x
+ }
+ return y
+}
diff --git a/src/cmd/compile/internal/ssa/regalloc_test.go b/src/cmd/compile/internal/ssa/regalloc_test.go
new file mode 100644
index 0000000..d990cac
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/regalloc_test.go
@@ -0,0 +1,230 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "testing"
+)
+
+func TestLiveControlOps(t *testing.T) {
+ c := testConfig(t)
+ f := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("x", OpAMD64MOVLconst, c.config.Types.Int8, 1, nil),
+ Valu("y", OpAMD64MOVLconst, c.config.Types.Int8, 2, nil),
+ Valu("a", OpAMD64TESTB, types.TypeFlags, 0, nil, "x", "y"),
+ Valu("b", OpAMD64TESTB, types.TypeFlags, 0, nil, "y", "x"),
+ Eq("a", "if", "exit"),
+ ),
+ Bloc("if",
+ Eq("b", "plain", "exit"),
+ ),
+ Bloc("plain",
+ Goto("exit"),
+ ),
+ Bloc("exit",
+ Exit("mem"),
+ ),
+ )
+ flagalloc(f.f)
+ regalloc(f.f)
+ checkFunc(f.f)
+}
+
+// Test to make sure G register is never reloaded from spill (spill of G is okay)
+// See #25504
+func TestNoGetgLoadReg(t *testing.T) {
+ /*
+ Original:
+ func fff3(i int) *g {
+ gee := getg()
+ if i == 0 {
+ fff()
+ }
+ return gee // here
+ }
+ */
+ c := testConfigARM64(t)
+ f := c.Fun("b1",
+ Bloc("b1",
+ Valu("v1", OpInitMem, types.TypeMem, 0, nil),
+ Valu("v6", OpArg, c.config.Types.Int64, 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64)),
+ Valu("v8", OpGetG, c.config.Types.Int64.PtrTo(), 0, nil, "v1"),
+ Valu("v11", OpARM64CMPconst, types.TypeFlags, 0, nil, "v6"),
+ Eq("v11", "b2", "b4"),
+ ),
+ Bloc("b4",
+ Goto("b3"),
+ ),
+ Bloc("b3",
+ Valu("v14", OpPhi, types.TypeMem, 0, nil, "v1", "v12"),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("v16", OpARM64MOVDstore, types.TypeMem, 0, nil, "v8", "sb", "v14"),
+ Exit("v16"),
+ ),
+ Bloc("b2",
+ Valu("v12", OpARM64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "v1"),
+ Goto("b3"),
+ ),
+ )
+ regalloc(f.f)
+ checkFunc(f.f)
+ // Double-check that we never restore to the G register. Regalloc should catch it, but check again anyway.
+ r := f.f.RegAlloc
+ for _, b := range f.blocks {
+ for _, v := range b.Values {
+ if v.Op == OpLoadReg && r[v.ID].String() == "g" {
+ t.Errorf("Saw OpLoadReg targeting g register: %s", v.LongString())
+ }
+ }
+ }
+}
+
+// Test to make sure we don't push spills into loops.
+// See issue #19595.
+func TestSpillWithLoop(t *testing.T) {
+ c := testConfig(t)
+ f := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("ptr", OpArg, c.config.Types.Int64.PtrTo(), 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64)),
+ Valu("cond", OpArg, c.config.Types.Bool, 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Bool)),
+ Valu("ld", OpAMD64MOVQload, c.config.Types.Int64, 0, nil, "ptr", "mem"), // this value needs a spill
+ Goto("loop"),
+ ),
+ Bloc("loop",
+ Valu("memphi", OpPhi, types.TypeMem, 0, nil, "mem", "call"),
+ Valu("call", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "memphi"),
+ Valu("test", OpAMD64CMPBconst, types.TypeFlags, 0, nil, "cond"),
+ Eq("test", "next", "exit"),
+ ),
+ Bloc("next",
+ Goto("loop"),
+ ),
+ Bloc("exit",
+ Valu("store", OpAMD64MOVQstore, types.TypeMem, 0, nil, "ptr", "ld", "call"),
+ Exit("store"),
+ ),
+ )
+ regalloc(f.f)
+ checkFunc(f.f)
+ for _, v := range f.blocks["loop"].Values {
+ if v.Op == OpStoreReg {
+ t.Errorf("spill inside loop %s", v.LongString())
+ }
+ }
+}
+
+func TestSpillMove1(t *testing.T) {
+ c := testConfig(t)
+ f := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("x", OpArg, c.config.Types.Int64, 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64)),
+ Valu("p", OpArg, c.config.Types.Int64.PtrTo(), 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64.PtrTo())),
+ Valu("a", OpAMD64TESTQ, types.TypeFlags, 0, nil, "x", "x"),
+ Goto("loop1"),
+ ),
+ Bloc("loop1",
+ Valu("y", OpAMD64MULQ, c.config.Types.Int64, 0, nil, "x", "x"),
+ Eq("a", "loop2", "exit1"),
+ ),
+ Bloc("loop2",
+ Eq("a", "loop1", "exit2"),
+ ),
+ Bloc("exit1",
+ // store before call, y is available in a register
+ Valu("mem2", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem"),
+ Valu("mem3", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem2"),
+ Exit("mem3"),
+ ),
+ Bloc("exit2",
+ // store after call, y must be loaded from a spill location
+ Valu("mem4", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
+ Valu("mem5", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem4"),
+ Exit("mem5"),
+ ),
+ )
+ flagalloc(f.f)
+ regalloc(f.f)
+ checkFunc(f.f)
+ // Spill should be moved to exit2.
+ if numSpills(f.blocks["loop1"]) != 0 {
+ t.Errorf("spill present from loop1")
+ }
+ if numSpills(f.blocks["loop2"]) != 0 {
+ t.Errorf("spill present in loop2")
+ }
+ if numSpills(f.blocks["exit1"]) != 0 {
+ t.Errorf("spill present in exit1")
+ }
+ if numSpills(f.blocks["exit2"]) != 1 {
+ t.Errorf("spill missing in exit2")
+ }
+
+}
+
+func TestSpillMove2(t *testing.T) {
+ c := testConfig(t)
+ f := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("x", OpArg, c.config.Types.Int64, 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64)),
+ Valu("p", OpArg, c.config.Types.Int64.PtrTo(), 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64.PtrTo())),
+ Valu("a", OpAMD64TESTQ, types.TypeFlags, 0, nil, "x", "x"),
+ Goto("loop1"),
+ ),
+ Bloc("loop1",
+ Valu("y", OpAMD64MULQ, c.config.Types.Int64, 0, nil, "x", "x"),
+ Eq("a", "loop2", "exit1"),
+ ),
+ Bloc("loop2",
+ Eq("a", "loop1", "exit2"),
+ ),
+ Bloc("exit1",
+ // store after call, y must be loaded from a spill location
+ Valu("mem2", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
+ Valu("mem3", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem2"),
+ Exit("mem3"),
+ ),
+ Bloc("exit2",
+ // store after call, y must be loaded from a spill location
+ Valu("mem4", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
+ Valu("mem5", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem4"),
+ Exit("mem5"),
+ ),
+ )
+ flagalloc(f.f)
+ regalloc(f.f)
+ checkFunc(f.f)
+ // There should be a spill in loop1, and nowhere else.
+ // TODO: resurrect moving spills out of loops? We could put spills at the start of both exit1 and exit2.
+ if numSpills(f.blocks["loop1"]) != 1 {
+ t.Errorf("spill missing from loop1")
+ }
+ if numSpills(f.blocks["loop2"]) != 0 {
+ t.Errorf("spill present in loop2")
+ }
+ if numSpills(f.blocks["exit1"]) != 0 {
+ t.Errorf("spill present in exit1")
+ }
+ if numSpills(f.blocks["exit2"]) != 0 {
+ t.Errorf("spill present in exit2")
+ }
+
+}
+
+func numSpills(b *Block) int {
+ n := 0
+ for _, v := range b.Values {
+ if v.Op == OpStoreReg {
+ n++
+ }
+ }
+ return n
+}
diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go
new file mode 100644
index 0000000..9e5ef68
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewrite.go
@@ -0,0 +1,1892 @@
+// 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 (
+ "cmd/compile/internal/logopt"
+ "cmd/compile/internal/types"
+ "cmd/internal/obj"
+ "cmd/internal/obj/s390x"
+ "cmd/internal/objabi"
+ "cmd/internal/src"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "math"
+ "math/bits"
+ "os"
+ "path/filepath"
+)
+
+type deadValueChoice bool
+
+const (
+ leaveDeadValues deadValueChoice = false
+ removeDeadValues = true
+)
+
+// deadcode indicates that rewrite should try to remove any values that become dead.
+func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValueChoice) {
+ // repeat rewrites until we find no more rewrites
+ pendingLines := f.cachedLineStarts // Holds statement boundaries that need to be moved to a new value/block
+ pendingLines.clear()
+ debug := f.pass.debug
+ if debug > 1 {
+ fmt.Printf("%s: rewriting for %s\n", f.pass.name, f.Name)
+ }
+ for {
+ change := false
+ for _, b := range f.Blocks {
+ var b0 *Block
+ if debug > 1 {
+ b0 = new(Block)
+ *b0 = *b
+ b0.Succs = append([]Edge{}, b.Succs...) // make a new copy, not aliasing
+ }
+ for i, c := range b.ControlValues() {
+ for c.Op == OpCopy {
+ c = c.Args[0]
+ b.ReplaceControl(i, c)
+ }
+ }
+ if rb(b) {
+ change = true
+ if debug > 1 {
+ fmt.Printf("rewriting %s -> %s\n", b0.LongString(), b.LongString())
+ }
+ }
+ for j, v := range b.Values {
+ var v0 *Value
+ if debug > 1 {
+ v0 = new(Value)
+ *v0 = *v
+ v0.Args = append([]*Value{}, v.Args...) // make a new copy, not aliasing
+ }
+ if v.Uses == 0 && v.removeable() {
+ if v.Op != OpInvalid && deadcode == removeDeadValues {
+ // Reset any values that are now unused, so that we decrement
+ // the use count of all of its arguments.
+ // Not quite a deadcode pass, because it does not handle cycles.
+ // But it should help Uses==1 rules to fire.
+ v.reset(OpInvalid)
+ change = true
+ }
+ // No point rewriting values which aren't used.
+ continue
+ }
+
+ vchange := phielimValue(v)
+ if vchange && debug > 1 {
+ fmt.Printf("rewriting %s -> %s\n", v0.LongString(), v.LongString())
+ }
+
+ // Eliminate copy inputs.
+ // If any copy input becomes unused, mark it
+ // as invalid and discard its argument. Repeat
+ // recursively on the discarded argument.
+ // This phase helps remove phantom "dead copy" uses
+ // of a value so that a x.Uses==1 rule condition
+ // fires reliably.
+ for i, a := range v.Args {
+ if a.Op != OpCopy {
+ continue
+ }
+ aa := copySource(a)
+ v.SetArg(i, aa)
+ // If a, a copy, has a line boundary indicator, attempt to find a new value
+ // to hold it. The first candidate is the value that will replace a (aa),
+ // if it shares the same block and line and is eligible.
+ // The second option is v, which has a as an input. Because aa is earlier in
+ // the data flow, it is the better choice.
+ if a.Pos.IsStmt() == src.PosIsStmt {
+ if aa.Block == a.Block && aa.Pos.Line() == a.Pos.Line() && aa.Pos.IsStmt() != src.PosNotStmt {
+ aa.Pos = aa.Pos.WithIsStmt()
+ } else if v.Block == a.Block && v.Pos.Line() == a.Pos.Line() && v.Pos.IsStmt() != src.PosNotStmt {
+ v.Pos = v.Pos.WithIsStmt()
+ } else {
+ // Record the lost line and look for a new home after all rewrites are complete.
+ // TODO: it's possible (in FOR loops, in particular) for statement boundaries for the same
+ // line to appear in more than one block, but only one block is stored, so if both end
+ // up here, then one will be lost.
+ pendingLines.set(a.Pos, int32(a.Block.ID))
+ }
+ a.Pos = a.Pos.WithNotStmt()
+ }
+ vchange = true
+ for a.Uses == 0 {
+ b := a.Args[0]
+ a.reset(OpInvalid)
+ a = b
+ }
+ }
+ if vchange && debug > 1 {
+ fmt.Printf("rewriting %s -> %s\n", v0.LongString(), v.LongString())
+ }
+
+ // apply rewrite function
+ if rv(v) {
+ vchange = true
+ // If value changed to a poor choice for a statement boundary, move the boundary
+ if v.Pos.IsStmt() == src.PosIsStmt {
+ if k := nextGoodStatementIndex(v, j, b); k != j {
+ v.Pos = v.Pos.WithNotStmt()
+ b.Values[k].Pos = b.Values[k].Pos.WithIsStmt()
+ }
+ }
+ }
+
+ change = change || vchange
+ if vchange && debug > 1 {
+ fmt.Printf("rewriting %s -> %s\n", v0.LongString(), v.LongString())
+ }
+ }
+ }
+ if !change {
+ break
+ }
+ }
+ // remove clobbered values
+ for _, b := range f.Blocks {
+ j := 0
+ for i, v := range b.Values {
+ vl := v.Pos
+ if v.Op == OpInvalid {
+ if v.Pos.IsStmt() == src.PosIsStmt {
+ pendingLines.set(vl, int32(b.ID))
+ }
+ f.freeValue(v)
+ continue
+ }
+ if v.Pos.IsStmt() != src.PosNotStmt && pendingLines.get(vl) == int32(b.ID) {
+ pendingLines.remove(vl)
+ v.Pos = v.Pos.WithIsStmt()
+ }
+ if i != j {
+ b.Values[j] = v
+ }
+ j++
+ }
+ if pendingLines.get(b.Pos) == int32(b.ID) {
+ b.Pos = b.Pos.WithIsStmt()
+ pendingLines.remove(b.Pos)
+ }
+ b.truncateValues(j)
+ }
+}
+
+// Common functions called from rewriting rules
+
+func is64BitFloat(t *types.Type) bool {
+ return t.Size() == 8 && t.IsFloat()
+}
+
+func is32BitFloat(t *types.Type) bool {
+ return t.Size() == 4 && t.IsFloat()
+}
+
+func is64BitInt(t *types.Type) bool {
+ return t.Size() == 8 && t.IsInteger()
+}
+
+func is32BitInt(t *types.Type) bool {
+ return t.Size() == 4 && t.IsInteger()
+}
+
+func is16BitInt(t *types.Type) bool {
+ return t.Size() == 2 && t.IsInteger()
+}
+
+func is8BitInt(t *types.Type) bool {
+ return t.Size() == 1 && t.IsInteger()
+}
+
+func isPtr(t *types.Type) bool {
+ return t.IsPtrShaped()
+}
+
+func isSigned(t *types.Type) bool {
+ return t.IsSigned()
+}
+
+// mergeSym merges two symbolic offsets. There is no real merging of
+// offsets, we just pick the non-nil one.
+func mergeSym(x, y Sym) Sym {
+ if x == nil {
+ return y
+ }
+ if y == nil {
+ return x
+ }
+ panic(fmt.Sprintf("mergeSym with two non-nil syms %v %v", x, y))
+}
+
+func canMergeSym(x, y Sym) bool {
+ return x == nil || y == nil
+}
+
+// canMergeLoadClobber reports whether the load can be merged into target without
+// invalidating the schedule.
+// It also checks that the other non-load argument x is something we
+// are ok with clobbering.
+func canMergeLoadClobber(target, load, x *Value) bool {
+ // The register containing x is going to get clobbered.
+ // Don't merge if we still need the value of x.
+ // We don't have liveness information here, but we can
+ // approximate x dying with:
+ // 1) target is x's only use.
+ // 2) target is not in a deeper loop than x.
+ if x.Uses != 1 {
+ return false
+ }
+ loopnest := x.Block.Func.loopnest()
+ loopnest.calculateDepths()
+ if loopnest.depth(target.Block.ID) > loopnest.depth(x.Block.ID) {
+ return false
+ }
+ return canMergeLoad(target, load)
+}
+
+// canMergeLoad reports whether the load can be merged into target without
+// invalidating the schedule.
+func canMergeLoad(target, load *Value) bool {
+ if target.Block.ID != load.Block.ID {
+ // If the load is in a different block do not merge it.
+ return false
+ }
+
+ // We can't merge the load into the target if the load
+ // has more than one use.
+ if load.Uses != 1 {
+ return false
+ }
+
+ mem := load.MemoryArg()
+
+ // We need the load's memory arg to still be alive at target. That
+ // can't be the case if one of target's args depends on a memory
+ // state that is a successor of load's memory arg.
+ //
+ // For example, it would be invalid to merge load into target in
+ // the following situation because newmem has killed oldmem
+ // before target is reached:
+ // load = read ... oldmem
+ // newmem = write ... oldmem
+ // arg0 = read ... newmem
+ // target = add arg0 load
+ //
+ // If the argument comes from a different block then we can exclude
+ // it immediately because it must dominate load (which is in the
+ // same block as target).
+ var args []*Value
+ for _, a := range target.Args {
+ if a != load && a.Block.ID == target.Block.ID {
+ args = append(args, a)
+ }
+ }
+
+ // memPreds contains memory states known to be predecessors of load's
+ // memory state. It is lazily initialized.
+ var memPreds map[*Value]bool
+ for i := 0; len(args) > 0; i++ {
+ const limit = 100
+ if i >= limit {
+ // Give up if we have done a lot of iterations.
+ return false
+ }
+ v := args[len(args)-1]
+ args = args[:len(args)-1]
+ if target.Block.ID != v.Block.ID {
+ // Since target and load are in the same block
+ // we can stop searching when we leave the block.
+ continue
+ }
+ if v.Op == OpPhi {
+ // A Phi implies we have reached the top of the block.
+ // The memory phi, if it exists, is always
+ // the first logical store in the block.
+ continue
+ }
+ if v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() {
+ // We could handle this situation however it is likely
+ // to be very rare.
+ return false
+ }
+ if v.Op.SymEffect()&SymAddr != 0 {
+ // This case prevents an operation that calculates the
+ // address of a local variable from being forced to schedule
+ // before its corresponding VarDef.
+ // See issue 28445.
+ // v1 = LOAD ...
+ // v2 = VARDEF
+ // v3 = LEAQ
+ // v4 = CMPQ v1 v3
+ // We don't want to combine the CMPQ with the load, because
+ // that would force the CMPQ to schedule before the VARDEF, which
+ // in turn requires the LEAQ to schedule before the VARDEF.
+ return false
+ }
+ if v.Type.IsMemory() {
+ if memPreds == nil {
+ // Initialise a map containing memory states
+ // known to be predecessors of load's memory
+ // state.
+ memPreds = make(map[*Value]bool)
+ m := mem
+ const limit = 50
+ for i := 0; i < limit; i++ {
+ if m.Op == OpPhi {
+ // The memory phi, if it exists, is always
+ // the first logical store in the block.
+ break
+ }
+ if m.Block.ID != target.Block.ID {
+ break
+ }
+ if !m.Type.IsMemory() {
+ break
+ }
+ memPreds[m] = true
+ if len(m.Args) == 0 {
+ break
+ }
+ m = m.MemoryArg()
+ }
+ }
+
+ // We can merge if v is a predecessor of mem.
+ //
+ // For example, we can merge load into target in the
+ // following scenario:
+ // x = read ... v
+ // mem = write ... v
+ // load = read ... mem
+ // target = add x load
+ if memPreds[v] {
+ continue
+ }
+ return false
+ }
+ if len(v.Args) > 0 && v.Args[len(v.Args)-1] == mem {
+ // If v takes mem as an input then we know mem
+ // is valid at this point.
+ continue
+ }
+ for _, a := range v.Args {
+ if target.Block.ID == a.Block.ID {
+ args = append(args, a)
+ }
+ }
+ }
+
+ return true
+}
+
+// isSameCall reports whether sym is the same as the given named symbol
+func isSameCall(sym interface{}, name string) bool {
+ fn := sym.(*AuxCall).Fn
+ return fn != nil && fn.String() == name
+}
+
+// nlz returns the number of leading zeros.
+func nlz64(x int64) int { return bits.LeadingZeros64(uint64(x)) }
+func nlz32(x int32) int { return bits.LeadingZeros32(uint32(x)) }
+func nlz16(x int16) int { return bits.LeadingZeros16(uint16(x)) }
+func nlz8(x int8) int { return bits.LeadingZeros8(uint8(x)) }
+
+// ntzX returns the number of trailing zeros.
+func ntz64(x int64) int { return bits.TrailingZeros64(uint64(x)) }
+func ntz32(x int32) int { return bits.TrailingZeros32(uint32(x)) }
+func ntz16(x int16) int { return bits.TrailingZeros16(uint16(x)) }
+func ntz8(x int8) int { return bits.TrailingZeros8(uint8(x)) }
+
+func oneBit(x int64) bool { return x&(x-1) == 0 && x != 0 }
+func oneBit8(x int8) bool { return x&(x-1) == 0 && x != 0 }
+func oneBit16(x int16) bool { return x&(x-1) == 0 && x != 0 }
+func oneBit32(x int32) bool { return x&(x-1) == 0 && x != 0 }
+func oneBit64(x int64) bool { return x&(x-1) == 0 && x != 0 }
+
+// nto returns the number of trailing ones.
+func nto(x int64) int64 {
+ return int64(ntz64(^x))
+}
+
+// logX returns logarithm of n base 2.
+// n must be a positive power of 2 (isPowerOfTwoX returns true).
+func log8(n int8) int64 {
+ return int64(bits.Len8(uint8(n))) - 1
+}
+func log16(n int16) int64 {
+ return int64(bits.Len16(uint16(n))) - 1
+}
+func log32(n int32) int64 {
+ return int64(bits.Len32(uint32(n))) - 1
+}
+func log64(n int64) int64 {
+ return int64(bits.Len64(uint64(n))) - 1
+}
+
+// log2uint32 returns logarithm in base 2 of uint32(n), with log2(0) = -1.
+// Rounds down.
+func log2uint32(n int64) int64 {
+ return int64(bits.Len32(uint32(n))) - 1
+}
+
+// isPowerOfTwo functions report whether n is a power of 2.
+func isPowerOfTwo8(n int8) bool {
+ return n > 0 && n&(n-1) == 0
+}
+func isPowerOfTwo16(n int16) bool {
+ return n > 0 && n&(n-1) == 0
+}
+func isPowerOfTwo32(n int32) bool {
+ return n > 0 && n&(n-1) == 0
+}
+func isPowerOfTwo64(n int64) bool {
+ return n > 0 && n&(n-1) == 0
+}
+
+// isUint64PowerOfTwo reports whether uint64(n) is a power of 2.
+func isUint64PowerOfTwo(in int64) bool {
+ n := uint64(in)
+ return n > 0 && n&(n-1) == 0
+}
+
+// isUint32PowerOfTwo reports whether uint32(n) is a power of 2.
+func isUint32PowerOfTwo(in int64) bool {
+ n := uint64(uint32(in))
+ 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))
+}
+
+// is16Bit reports whether n can be represented as a signed 16 bit integer.
+func is16Bit(n int64) bool {
+ return n == int64(int16(n))
+}
+
+// is8Bit reports whether n can be represented as a signed 8 bit integer.
+func is8Bit(n int64) bool {
+ return n == int64(int8(n))
+}
+
+// isU8Bit reports whether n can be represented as an unsigned 8 bit integer.
+func isU8Bit(n int64) bool {
+ return n == int64(uint8(n))
+}
+
+// isU12Bit reports whether n can be represented as an unsigned 12 bit integer.
+func isU12Bit(n int64) bool {
+ return 0 <= n && n < (1<<12)
+}
+
+// isU16Bit reports whether n can be represented as an unsigned 16 bit integer.
+func isU16Bit(n int64) bool {
+ return n == int64(uint16(n))
+}
+
+// isU32Bit reports whether n can be represented as an unsigned 32 bit integer.
+func isU32Bit(n int64) bool {
+ return n == int64(uint32(n))
+}
+
+// is20Bit reports whether n can be represented as a signed 20 bit integer.
+func is20Bit(n int64) bool {
+ return -(1<<19) <= n && n < (1<<19)
+}
+
+// b2i translates a boolean value to 0 or 1 for assigning to auxInt.
+func b2i(b bool) int64 {
+ if b {
+ return 1
+ }
+ return 0
+}
+
+// b2i32 translates a boolean value to 0 or 1.
+func b2i32(b bool) int32 {
+ if b {
+ return 1
+ }
+ return 0
+}
+
+// shiftIsBounded reports whether (left/right) shift Value v is known to be bounded.
+// A shift is bounded if it is shifting by less than the width of the shifted value.
+func shiftIsBounded(v *Value) bool {
+ return v.AuxInt != 0
+}
+
+// truncate64Fto32F converts a float64 value to a float32 preserving the bit pattern
+// of the mantissa. It will panic if the truncation results in lost information.
+func truncate64Fto32F(f float64) float32 {
+ if !isExactFloat32(f) {
+ panic("truncate64Fto32F: truncation is not exact")
+ }
+ if !math.IsNaN(f) {
+ return float32(f)
+ }
+ // NaN bit patterns aren't necessarily preserved across conversion
+ // instructions so we need to do the conversion manually.
+ b := math.Float64bits(f)
+ m := b & ((1 << 52) - 1) // mantissa (a.k.a. significand)
+ // | sign | exponent | mantissa |
+ r := uint32(((b >> 32) & (1 << 31)) | 0x7f800000 | (m >> (52 - 23)))
+ return math.Float32frombits(r)
+}
+
+// extend32Fto64F converts a float32 value to a float64 value preserving the bit
+// pattern of the mantissa.
+func extend32Fto64F(f float32) float64 {
+ if !math.IsNaN(float64(f)) {
+ return float64(f)
+ }
+ // NaN bit patterns aren't necessarily preserved across conversion
+ // instructions so we need to do the conversion manually.
+ b := uint64(math.Float32bits(f))
+ // | sign | exponent | mantissa |
+ r := ((b << 32) & (1 << 63)) | (0x7ff << 52) | ((b & 0x7fffff) << (52 - 23))
+ return math.Float64frombits(r)
+}
+
+// DivisionNeedsFixUp reports whether the division needs fix-up code.
+func DivisionNeedsFixUp(v *Value) bool {
+ return v.AuxInt == 0
+}
+
+// auxFrom64F encodes a float64 value so it can be stored in an AuxInt.
+func auxFrom64F(f float64) int64 {
+ if f != f {
+ panic("can't encode a NaN in AuxInt field")
+ }
+ return int64(math.Float64bits(f))
+}
+
+// auxFrom32F encodes a float32 value so it can be stored in an AuxInt.
+func auxFrom32F(f float32) int64 {
+ if f != f {
+ panic("can't encode a NaN in AuxInt field")
+ }
+ return int64(math.Float64bits(extend32Fto64F(f)))
+}
+
+// auxTo32F decodes a float32 from the AuxInt value provided.
+func auxTo32F(i int64) float32 {
+ return truncate64Fto32F(math.Float64frombits(uint64(i)))
+}
+
+// auxTo64F decodes a float64 from the AuxInt value provided.
+func auxTo64F(i int64) float64 {
+ return math.Float64frombits(uint64(i))
+}
+
+func auxIntToBool(i int64) bool {
+ if i == 0 {
+ return false
+ }
+ return true
+}
+func auxIntToInt8(i int64) int8 {
+ return int8(i)
+}
+func auxIntToInt16(i int64) int16 {
+ return int16(i)
+}
+func auxIntToInt32(i int64) int32 {
+ return int32(i)
+}
+func auxIntToInt64(i int64) int64 {
+ return i
+}
+func auxIntToUint8(i int64) uint8 {
+ return uint8(i)
+}
+func auxIntToFloat32(i int64) float32 {
+ return float32(math.Float64frombits(uint64(i)))
+}
+func auxIntToFloat64(i int64) float64 {
+ return math.Float64frombits(uint64(i))
+}
+func auxIntToValAndOff(i int64) ValAndOff {
+ return ValAndOff(i)
+}
+func auxIntToArm64BitField(i int64) arm64BitField {
+ return arm64BitField(i)
+}
+func auxIntToInt128(x int64) int128 {
+ if x != 0 {
+ panic("nonzero int128 not allowed")
+ }
+ return 0
+}
+func auxIntToFlagConstant(x int64) flagConstant {
+ return flagConstant(x)
+}
+
+func auxIntToOp(cc int64) Op {
+ return Op(cc)
+}
+
+func boolToAuxInt(b bool) int64 {
+ if b {
+ return 1
+ }
+ return 0
+}
+func int8ToAuxInt(i int8) int64 {
+ return int64(i)
+}
+func int16ToAuxInt(i int16) int64 {
+ return int64(i)
+}
+func int32ToAuxInt(i int32) int64 {
+ return int64(i)
+}
+func int64ToAuxInt(i int64) int64 {
+ return int64(i)
+}
+func uint8ToAuxInt(i uint8) int64 {
+ return int64(int8(i))
+}
+func float32ToAuxInt(f float32) int64 {
+ return int64(math.Float64bits(float64(f)))
+}
+func float64ToAuxInt(f float64) int64 {
+ return int64(math.Float64bits(f))
+}
+func valAndOffToAuxInt(v ValAndOff) int64 {
+ return int64(v)
+}
+func arm64BitFieldToAuxInt(v arm64BitField) int64 {
+ return int64(v)
+}
+func int128ToAuxInt(x int128) int64 {
+ if x != 0 {
+ panic("nonzero int128 not allowed")
+ }
+ return 0
+}
+func flagConstantToAuxInt(x flagConstant) int64 {
+ return int64(x)
+}
+
+func opToAuxInt(o Op) int64 {
+ return int64(o)
+}
+
+func auxToString(i interface{}) string {
+ return i.(string)
+}
+func auxToSym(i interface{}) Sym {
+ // TODO: kind of a hack - allows nil interface through
+ s, _ := i.(Sym)
+ return s
+}
+func auxToType(i interface{}) *types.Type {
+ return i.(*types.Type)
+}
+func auxToCall(i interface{}) *AuxCall {
+ return i.(*AuxCall)
+}
+func auxToS390xCCMask(i interface{}) s390x.CCMask {
+ return i.(s390x.CCMask)
+}
+func auxToS390xRotateParams(i interface{}) s390x.RotateParams {
+ return i.(s390x.RotateParams)
+}
+
+func stringToAux(s string) interface{} {
+ return s
+}
+func symToAux(s Sym) interface{} {
+ return s
+}
+func callToAux(s *AuxCall) interface{} {
+ return s
+}
+func typeToAux(t *types.Type) interface{} {
+ return t
+}
+func s390xCCMaskToAux(c s390x.CCMask) interface{} {
+ return c
+}
+func s390xRotateParamsToAux(r s390x.RotateParams) interface{} {
+ return r
+}
+
+// uaddOvf reports whether unsigned a+b would overflow.
+func uaddOvf(a, b int64) bool {
+ return uint64(a)+uint64(b) < uint64(a)
+}
+
+// de-virtualize an InterCall
+// 'sym' is the symbol for the itab
+func devirt(v *Value, aux interface{}, sym Sym, offset int64) *AuxCall {
+ f := v.Block.Func
+ n, ok := sym.(*obj.LSym)
+ if !ok {
+ return nil
+ }
+ lsym := f.fe.DerefItab(n, offset)
+ if f.pass.debug > 0 {
+ if lsym != nil {
+ f.Warnl(v.Pos, "de-virtualizing call")
+ } else {
+ f.Warnl(v.Pos, "couldn't de-virtualize call")
+ }
+ }
+ if lsym == nil {
+ return nil
+ }
+ va := aux.(*AuxCall)
+ return StaticAuxCall(lsym, va.args, va.results)
+}
+
+// de-virtualize an InterLECall
+// 'sym' is the symbol for the itab
+func devirtLESym(v *Value, aux interface{}, sym Sym, offset int64) *obj.LSym {
+ n, ok := sym.(*obj.LSym)
+ if !ok {
+ return nil
+ }
+
+ f := v.Block.Func
+ lsym := f.fe.DerefItab(n, offset)
+ if f.pass.debug > 0 {
+ if lsym != nil {
+ f.Warnl(v.Pos, "de-virtualizing call")
+ } else {
+ f.Warnl(v.Pos, "couldn't de-virtualize call")
+ }
+ }
+ if lsym == nil {
+ return nil
+ }
+ return lsym
+}
+
+func devirtLECall(v *Value, sym *obj.LSym) *Value {
+ v.Op = OpStaticLECall
+ v.Aux.(*AuxCall).Fn = sym
+ v.RemoveArg(0)
+ return v
+}
+
+// isSamePtr reports whether p1 and p2 point to the same address.
+func isSamePtr(p1, p2 *Value) bool {
+ if p1 == p2 {
+ return true
+ }
+ if p1.Op != p2.Op {
+ return false
+ }
+ switch p1.Op {
+ case OpOffPtr:
+ return p1.AuxInt == p2.AuxInt && isSamePtr(p1.Args[0], p2.Args[0])
+ case OpAddr, OpLocalAddr:
+ // OpAddr's 0th arg is either OpSP or OpSB, which means that it is uniquely identified by its Op.
+ // Checking for value equality only works after [z]cse has run.
+ return p1.Aux == p2.Aux && p1.Args[0].Op == p2.Args[0].Op
+ case OpAddPtr:
+ return p1.Args[1] == p2.Args[1] && isSamePtr(p1.Args[0], p2.Args[0])
+ }
+ return false
+}
+
+func isStackPtr(v *Value) bool {
+ for v.Op == OpOffPtr || v.Op == OpAddPtr {
+ v = v.Args[0]
+ }
+ return v.Op == OpSP || v.Op == OpLocalAddr
+}
+
+// disjoint reports whether the memory region specified by [p1:p1+n1)
+// does not overlap with [p2:p2+n2).
+// A return value of false does not imply the regions overlap.
+func disjoint(p1 *Value, n1 int64, p2 *Value, n2 int64) bool {
+ if n1 == 0 || n2 == 0 {
+ return true
+ }
+ if p1 == p2 {
+ return false
+ }
+ baseAndOffset := func(ptr *Value) (base *Value, offset int64) {
+ base, offset = ptr, 0
+ for base.Op == OpOffPtr {
+ offset += base.AuxInt
+ base = base.Args[0]
+ }
+ return base, offset
+ }
+ p1, off1 := baseAndOffset(p1)
+ p2, off2 := baseAndOffset(p2)
+ if isSamePtr(p1, p2) {
+ return !overlap(off1, n1, off2, n2)
+ }
+ // p1 and p2 are not the same, so if they are both OpAddrs then
+ // they point to different variables.
+ // If one pointer is on the stack and the other is an argument
+ // then they can't overlap.
+ switch p1.Op {
+ case OpAddr, OpLocalAddr:
+ if p2.Op == OpAddr || p2.Op == OpLocalAddr || p2.Op == OpSP {
+ return true
+ }
+ return p2.Op == OpArg && p1.Args[0].Op == OpSP
+ case OpArg:
+ if p2.Op == OpSP || p2.Op == OpLocalAddr {
+ return true
+ }
+ case OpSP:
+ return p2.Op == OpAddr || p2.Op == OpLocalAddr || p2.Op == OpArg || p2.Op == OpSP
+ }
+ return false
+}
+
+// moveSize returns the number of bytes an aligned MOV instruction moves
+func moveSize(align int64, c *Config) int64 {
+ switch {
+ case align%8 == 0 && c.PtrSize == 8:
+ return 8
+ case align%4 == 0:
+ return 4
+ case align%2 == 0:
+ return 2
+ }
+ return 1
+}
+
+// mergePoint finds a block among a's blocks which dominates b and is itself
+// dominated by all of a's blocks. Returns nil if it can't find one.
+// Might return nil even if one does exist.
+func mergePoint(b *Block, a ...*Value) *Block {
+ // Walk backward from b looking for one of the a's blocks.
+
+ // Max distance
+ d := 100
+
+ for d > 0 {
+ for _, x := range a {
+ if b == x.Block {
+ goto found
+ }
+ }
+ if len(b.Preds) > 1 {
+ // Don't know which way to go back. Abort.
+ return nil
+ }
+ b = b.Preds[0].b
+ d--
+ }
+ return nil // too far away
+found:
+ // At this point, r is the first value in a that we find by walking backwards.
+ // if we return anything, r will be it.
+ r := b
+
+ // Keep going, counting the other a's that we find. They must all dominate r.
+ na := 0
+ for d > 0 {
+ for _, x := range a {
+ if b == x.Block {
+ na++
+ }
+ }
+ if na == len(a) {
+ // Found all of a in a backwards walk. We can return r.
+ return r
+ }
+ if len(b.Preds) > 1 {
+ return nil
+ }
+ b = b.Preds[0].b
+ d--
+
+ }
+ return nil // too far away
+}
+
+// clobber invalidates values. Returns true.
+// clobber is used by rewrite rules to:
+// A) make sure the values are really dead and never used again.
+// B) decrement use counts of the values' args.
+func clobber(vv ...*Value) bool {
+ for _, v := range vv {
+ v.reset(OpInvalid)
+ // Note: leave v.Block intact. The Block field is used after clobber.
+ }
+ return true
+}
+
+// clobberIfDead resets v when use count is 1. Returns true.
+// clobberIfDead is used by rewrite rules to decrement
+// use counts of v's args when v is dead and never used.
+func clobberIfDead(v *Value) bool {
+ if v.Uses == 1 {
+ v.reset(OpInvalid)
+ }
+ // Note: leave v.Block intact. The Block field is used after clobberIfDead.
+ return true
+}
+
+// noteRule is an easy way to track if a rule is matched when writing
+// new ones. Make the rule of interest also conditional on
+// noteRule("note to self: rule of interest matched")
+// and that message will print when the rule matches.
+func noteRule(s string) bool {
+ fmt.Println(s)
+ return true
+}
+
+// countRule increments Func.ruleMatches[key].
+// If Func.ruleMatches is non-nil at the end
+// of compilation, it will be printed to stdout.
+// This is intended to make it easier to find which functions
+// which contain lots of rules matches when developing new rules.
+func countRule(v *Value, key string) bool {
+ f := v.Block.Func
+ if f.ruleMatches == nil {
+ f.ruleMatches = make(map[string]int)
+ }
+ f.ruleMatches[key]++
+ return true
+}
+
+// warnRule generates compiler debug output with string s when
+// v is not in autogenerated code, cond is true and the rule has fired.
+func warnRule(cond bool, v *Value, s string) bool {
+ if pos := v.Pos; pos.Line() > 1 && cond {
+ v.Block.Func.Warnl(pos, s)
+ }
+ return true
+}
+
+// for a pseudo-op like (LessThan x), extract x
+func flagArg(v *Value) *Value {
+ if len(v.Args) != 1 || !v.Args[0].Type.IsFlags() {
+ return nil
+ }
+ return v.Args[0]
+}
+
+// arm64Negate finds the complement to an ARM64 condition code,
+// for example !Equal -> NotEqual or !LessThan -> GreaterEqual
+//
+// For floating point, it's more subtle because NaN is unordered. We do
+// !LessThanF -> NotLessThanF, the latter takes care of NaNs.
+func arm64Negate(op Op) Op {
+ switch op {
+ case OpARM64LessThan:
+ return OpARM64GreaterEqual
+ case OpARM64LessThanU:
+ return OpARM64GreaterEqualU
+ case OpARM64GreaterThan:
+ return OpARM64LessEqual
+ case OpARM64GreaterThanU:
+ return OpARM64LessEqualU
+ case OpARM64LessEqual:
+ return OpARM64GreaterThan
+ case OpARM64LessEqualU:
+ return OpARM64GreaterThanU
+ case OpARM64GreaterEqual:
+ return OpARM64LessThan
+ case OpARM64GreaterEqualU:
+ return OpARM64LessThanU
+ case OpARM64Equal:
+ return OpARM64NotEqual
+ case OpARM64NotEqual:
+ return OpARM64Equal
+ case OpARM64LessThanF:
+ return OpARM64NotLessThanF
+ case OpARM64NotLessThanF:
+ return OpARM64LessThanF
+ case OpARM64LessEqualF:
+ return OpARM64NotLessEqualF
+ case OpARM64NotLessEqualF:
+ return OpARM64LessEqualF
+ case OpARM64GreaterThanF:
+ return OpARM64NotGreaterThanF
+ case OpARM64NotGreaterThanF:
+ return OpARM64GreaterThanF
+ case OpARM64GreaterEqualF:
+ return OpARM64NotGreaterEqualF
+ case OpARM64NotGreaterEqualF:
+ return OpARM64GreaterEqualF
+ default:
+ panic("unreachable")
+ }
+}
+
+// arm64Invert evaluates (InvertFlags op), which
+// is the same as altering the condition codes such
+// that the same result would be produced if the arguments
+// to the flag-generating instruction were reversed, e.g.
+// (InvertFlags (CMP x y)) -> (CMP y x)
+func arm64Invert(op Op) Op {
+ switch op {
+ case OpARM64LessThan:
+ return OpARM64GreaterThan
+ case OpARM64LessThanU:
+ return OpARM64GreaterThanU
+ case OpARM64GreaterThan:
+ return OpARM64LessThan
+ case OpARM64GreaterThanU:
+ return OpARM64LessThanU
+ case OpARM64LessEqual:
+ return OpARM64GreaterEqual
+ case OpARM64LessEqualU:
+ return OpARM64GreaterEqualU
+ case OpARM64GreaterEqual:
+ return OpARM64LessEqual
+ case OpARM64GreaterEqualU:
+ return OpARM64LessEqualU
+ case OpARM64Equal, OpARM64NotEqual:
+ return op
+ case OpARM64LessThanF:
+ return OpARM64GreaterThanF
+ case OpARM64GreaterThanF:
+ return OpARM64LessThanF
+ case OpARM64LessEqualF:
+ return OpARM64GreaterEqualF
+ case OpARM64GreaterEqualF:
+ return OpARM64LessEqualF
+ case OpARM64NotLessThanF:
+ return OpARM64NotGreaterThanF
+ case OpARM64NotGreaterThanF:
+ return OpARM64NotLessThanF
+ case OpARM64NotLessEqualF:
+ return OpARM64NotGreaterEqualF
+ case OpARM64NotGreaterEqualF:
+ return OpARM64NotLessEqualF
+ default:
+ panic("unreachable")
+ }
+}
+
+// evaluate an ARM64 op against a flags value
+// that is potentially constant; return 1 for true,
+// -1 for false, and 0 for not constant.
+func ccARM64Eval(op Op, flags *Value) int {
+ fop := flags.Op
+ if fop == OpARM64InvertFlags {
+ return -ccARM64Eval(op, flags.Args[0])
+ }
+ if fop != OpARM64FlagConstant {
+ return 0
+ }
+ fc := flagConstant(flags.AuxInt)
+ b2i := func(b bool) int {
+ if b {
+ return 1
+ }
+ return -1
+ }
+ switch op {
+ case OpARM64Equal:
+ return b2i(fc.eq())
+ case OpARM64NotEqual:
+ return b2i(fc.ne())
+ case OpARM64LessThan:
+ return b2i(fc.lt())
+ case OpARM64LessThanU:
+ return b2i(fc.ult())
+ case OpARM64GreaterThan:
+ return b2i(fc.gt())
+ case OpARM64GreaterThanU:
+ return b2i(fc.ugt())
+ case OpARM64LessEqual:
+ return b2i(fc.le())
+ case OpARM64LessEqualU:
+ return b2i(fc.ule())
+ case OpARM64GreaterEqual:
+ return b2i(fc.ge())
+ case OpARM64GreaterEqualU:
+ return b2i(fc.uge())
+ }
+ return 0
+}
+
+// logRule logs the use of the rule s. This will only be enabled if
+// rewrite rules were generated with the -log option, see gen/rulegen.go.
+func logRule(s string) {
+ if ruleFile == nil {
+ // Open a log file to write log to. We open in append
+ // mode because all.bash runs the compiler lots of times,
+ // and we want the concatenation of all of those logs.
+ // This means, of course, that users need to rm the old log
+ // to get fresh data.
+ // TODO: all.bash runs compilers in parallel. Need to synchronize logging somehow?
+ w, err := os.OpenFile(filepath.Join(os.Getenv("GOROOT"), "src", "rulelog"),
+ os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
+ if err != nil {
+ panic(err)
+ }
+ ruleFile = w
+ }
+ _, err := fmt.Fprintln(ruleFile, s)
+ if err != nil {
+ panic(err)
+ }
+}
+
+var ruleFile io.Writer
+
+func min(x, y int64) int64 {
+ if x < y {
+ return x
+ }
+ return y
+}
+
+func isConstZero(v *Value) bool {
+ switch v.Op {
+ case OpConstNil:
+ return true
+ case OpConst64, OpConst32, OpConst16, OpConst8, OpConstBool, OpConst32F, OpConst64F:
+ return v.AuxInt == 0
+ }
+ return false
+}
+
+// reciprocalExact64 reports whether 1/c is exactly representable.
+func reciprocalExact64(c float64) bool {
+ b := math.Float64bits(c)
+ man := b & (1<<52 - 1)
+ if man != 0 {
+ return false // not a power of 2, denormal, or NaN
+ }
+ exp := b >> 52 & (1<<11 - 1)
+ // exponent bias is 0x3ff. So taking the reciprocal of a number
+ // changes the exponent to 0x7fe-exp.
+ switch exp {
+ case 0:
+ return false // ±0
+ case 0x7ff:
+ return false // ±inf
+ case 0x7fe:
+ return false // exponent is not representable
+ default:
+ return true
+ }
+}
+
+// reciprocalExact32 reports whether 1/c is exactly representable.
+func reciprocalExact32(c float32) bool {
+ b := math.Float32bits(c)
+ man := b & (1<<23 - 1)
+ if man != 0 {
+ return false // not a power of 2, denormal, or NaN
+ }
+ exp := b >> 23 & (1<<8 - 1)
+ // exponent bias is 0x7f. So taking the reciprocal of a number
+ // changes the exponent to 0xfe-exp.
+ switch exp {
+ case 0:
+ return false // ±0
+ case 0xff:
+ return false // ±inf
+ case 0xfe:
+ return false // exponent is not representable
+ default:
+ return true
+ }
+}
+
+// check if an immediate can be directly encoded into an ARM's instruction
+func isARMImmRot(v uint32) bool {
+ for i := 0; i < 16; i++ {
+ if v&^0xff == 0 {
+ return true
+ }
+ v = v<<2 | v>>30
+ }
+
+ return false
+}
+
+// overlap reports whether the ranges given by the given offset and
+// size pairs overlap.
+func overlap(offset1, size1, offset2, size2 int64) bool {
+ if offset1 >= offset2 && offset2+size2 > offset1 {
+ return true
+ }
+ if offset2 >= offset1 && offset1+size1 > offset2 {
+ return true
+ }
+ return false
+}
+
+func areAdjacentOffsets(off1, off2, size int64) bool {
+ return off1+size == off2 || off1 == off2+size
+}
+
+// check if value zeroes out upper 32-bit of 64-bit register.
+// depth limits recursion depth. In AMD64.rules 3 is used as limit,
+// because it catches same amount of cases as 4.
+func zeroUpper32Bits(x *Value, depth int) bool {
+ switch x.Op {
+ case OpAMD64MOVLconst, OpAMD64MOVLload, OpAMD64MOVLQZX, OpAMD64MOVLloadidx1,
+ OpAMD64MOVWload, OpAMD64MOVWloadidx1, OpAMD64MOVBload, OpAMD64MOVBloadidx1,
+ OpAMD64MOVLloadidx4, OpAMD64ADDLload, OpAMD64SUBLload, OpAMD64ANDLload,
+ OpAMD64ORLload, OpAMD64XORLload, OpAMD64CVTTSD2SL,
+ OpAMD64ADDL, OpAMD64ADDLconst, OpAMD64SUBL, OpAMD64SUBLconst,
+ OpAMD64ANDL, OpAMD64ANDLconst, OpAMD64ORL, OpAMD64ORLconst,
+ OpAMD64XORL, OpAMD64XORLconst, OpAMD64NEGL, OpAMD64NOTL,
+ OpAMD64SHRL, OpAMD64SHRLconst, OpAMD64SARL, OpAMD64SARLconst,
+ OpAMD64SHLL, OpAMD64SHLLconst:
+ return true
+ case OpArg:
+ return x.Type.Width == 4
+ case OpPhi, OpSelect0, OpSelect1:
+ // Phis can use each-other as an arguments, instead of tracking visited values,
+ // just limit recursion depth.
+ if depth <= 0 {
+ return false
+ }
+ for i := range x.Args {
+ if !zeroUpper32Bits(x.Args[i], depth-1) {
+ return false
+ }
+ }
+ return true
+
+ }
+ return false
+}
+
+// zeroUpper48Bits is similar to zeroUpper32Bits, but for upper 48 bits
+func zeroUpper48Bits(x *Value, depth int) bool {
+ switch x.Op {
+ case OpAMD64MOVWQZX, OpAMD64MOVWload, OpAMD64MOVWloadidx1, OpAMD64MOVWloadidx2:
+ return true
+ case OpArg:
+ return x.Type.Width == 2
+ case OpPhi, OpSelect0, OpSelect1:
+ // Phis can use each-other as an arguments, instead of tracking visited values,
+ // just limit recursion depth.
+ if depth <= 0 {
+ return false
+ }
+ for i := range x.Args {
+ if !zeroUpper48Bits(x.Args[i], depth-1) {
+ return false
+ }
+ }
+ return true
+
+ }
+ return false
+}
+
+// zeroUpper56Bits is similar to zeroUpper32Bits, but for upper 56 bits
+func zeroUpper56Bits(x *Value, depth int) bool {
+ switch x.Op {
+ case OpAMD64MOVBQZX, OpAMD64MOVBload, OpAMD64MOVBloadidx1:
+ return true
+ case OpArg:
+ return x.Type.Width == 1
+ case OpPhi, OpSelect0, OpSelect1:
+ // Phis can use each-other as an arguments, instead of tracking visited values,
+ // just limit recursion depth.
+ if depth <= 0 {
+ return false
+ }
+ for i := range x.Args {
+ if !zeroUpper56Bits(x.Args[i], depth-1) {
+ return false
+ }
+ }
+ return true
+
+ }
+ return false
+}
+
+// isInlinableMemmove reports whether the given arch performs a Move of the given size
+// faster than memmove. It will only return true if replacing the memmove with a Move is
+// safe, either because Move is small or because the arguments are disjoint.
+// This is used as a check for replacing memmove with Move ops.
+func isInlinableMemmove(dst, src *Value, sz int64, c *Config) bool {
+ // It is always safe to convert memmove into Move when its arguments are disjoint.
+ // Move ops may or may not be faster for large sizes depending on how the platform
+ // lowers them, so we only perform this optimization on platforms that we know to
+ // have fast Move ops.
+ switch c.arch {
+ case "amd64":
+ return sz <= 16 || (sz < 1024 && disjoint(dst, sz, src, sz))
+ case "386", "arm64":
+ return sz <= 8
+ case "s390x", "ppc64", "ppc64le":
+ return sz <= 8 || disjoint(dst, sz, src, sz)
+ case "arm", "mips", "mips64", "mipsle", "mips64le":
+ return sz <= 4
+ }
+ return false
+}
+
+// logLargeCopy logs the occurrence of a large copy.
+// The best place to do this is in the rewrite rules where the size of the move is easy to find.
+// "Large" is arbitrarily chosen to be 128 bytes; this may change.
+func logLargeCopy(v *Value, s int64) bool {
+ if s < 128 {
+ return true
+ }
+ if logopt.Enabled() {
+ logopt.LogOpt(v.Pos, "copy", "lower", v.Block.Func.Name, fmt.Sprintf("%d bytes", s))
+ }
+ return true
+}
+
+// hasSmallRotate reports whether the architecture has rotate instructions
+// for sizes < 32-bit. This is used to decide whether to promote some rotations.
+func hasSmallRotate(c *Config) bool {
+ switch c.arch {
+ case "amd64", "386":
+ return true
+ default:
+ return false
+ }
+}
+
+func newPPC64ShiftAuxInt(sh, mb, me, sz int64) int32 {
+ if sh < 0 || sh >= sz {
+ panic("PPC64 shift arg sh out of range")
+ }
+ if mb < 0 || mb >= sz {
+ panic("PPC64 shift arg mb out of range")
+ }
+ if me < 0 || me >= sz {
+ panic("PPC64 shift arg me out of range")
+ }
+ return int32(sh<<16 | mb<<8 | me)
+}
+
+func GetPPC64Shiftsh(auxint int64) int64 {
+ return int64(int8(auxint >> 16))
+}
+
+func GetPPC64Shiftmb(auxint int64) int64 {
+ return int64(int8(auxint >> 8))
+}
+
+func GetPPC64Shiftme(auxint int64) int64 {
+ return int64(int8(auxint))
+}
+
+// Test if this value can encoded as a mask for a rlwinm like
+// operation. Masks can also extend from the msb and wrap to
+// the lsb too. That is, the valid masks are 32 bit strings
+// of the form: 0..01..10..0 or 1..10..01..1 or 1...1
+func isPPC64WordRotateMask(v64 int64) bool {
+ // Isolate rightmost 1 (if none 0) and add.
+ v := uint32(v64)
+ vp := (v & -v) + v
+ // Likewise, for the wrapping case.
+ vn := ^v
+ vpn := (vn & -vn) + vn
+ return (v&vp == 0 || vn&vpn == 0) && v != 0
+}
+
+// Compress mask and and shift into single value of the form
+// me | mb<<8 | rotate<<16 | nbits<<24 where me and mb can
+// be used to regenerate the input mask.
+func encodePPC64RotateMask(rotate, mask, nbits int64) int64 {
+ var mb, me, mbn, men int
+
+ // Determine boundaries and then decode them
+ if mask == 0 || ^mask == 0 || rotate >= nbits {
+ panic("Invalid PPC64 rotate mask")
+ } else if nbits == 32 {
+ mb = bits.LeadingZeros32(uint32(mask))
+ me = 32 - bits.TrailingZeros32(uint32(mask))
+ mbn = bits.LeadingZeros32(^uint32(mask))
+ men = 32 - bits.TrailingZeros32(^uint32(mask))
+ } else {
+ mb = bits.LeadingZeros64(uint64(mask))
+ me = 64 - bits.TrailingZeros64(uint64(mask))
+ mbn = bits.LeadingZeros64(^uint64(mask))
+ men = 64 - bits.TrailingZeros64(^uint64(mask))
+ }
+ // Check for a wrapping mask (e.g bits at 0 and 63)
+ if mb == 0 && me == int(nbits) {
+ // swap the inverted values
+ mb, me = men, mbn
+ }
+
+ return int64(me) | int64(mb<<8) | int64(rotate<<16) | int64(nbits<<24)
+}
+
+// The inverse operation of encodePPC64RotateMask. The values returned as
+// mb and me satisfy the POWER ISA definition of MASK(x,y) where MASK(mb,me) = mask.
+func DecodePPC64RotateMask(sauxint int64) (rotate, mb, me int64, mask uint64) {
+ auxint := uint64(sauxint)
+ rotate = int64((auxint >> 16) & 0xFF)
+ mb = int64((auxint >> 8) & 0xFF)
+ me = int64((auxint >> 0) & 0xFF)
+ nbits := int64((auxint >> 24) & 0xFF)
+ mask = ((1 << uint(nbits-mb)) - 1) ^ ((1 << uint(nbits-me)) - 1)
+ if mb > me {
+ mask = ^mask
+ }
+ if nbits == 32 {
+ mask = uint64(uint32(mask))
+ }
+
+ // Fixup ME to match ISA definition. The second argument to MASK(..,me)
+ // is inclusive.
+ me = (me - 1) & (nbits - 1)
+ return
+}
+
+// This verifies that the mask is a set of
+// consecutive bits including the least
+// significant bit.
+func isPPC64ValidShiftMask(v int64) bool {
+ if (v != 0) && ((v+1)&v) == 0 {
+ return true
+ }
+ return false
+}
+
+func getPPC64ShiftMaskLength(v int64) int64 {
+ return int64(bits.Len64(uint64(v)))
+}
+
+// Decompose a shift right into an equivalent rotate/mask,
+// and return mask & m.
+func mergePPC64RShiftMask(m, s, nbits int64) int64 {
+ smask := uint64((1<<uint(nbits))-1) >> uint(s)
+ return m & int64(smask)
+}
+
+// Combine (ANDconst [m] (SRWconst [s])) into (RLWINM [y]) or return 0
+func mergePPC64AndSrwi(m, s int64) int64 {
+ mask := mergePPC64RShiftMask(m, s, 32)
+ if !isPPC64WordRotateMask(mask) {
+ return 0
+ }
+ return encodePPC64RotateMask((32-s)&31, mask, 32)
+}
+
+// Test if a shift right feeding into a CLRLSLDI can be merged into RLWINM.
+// Return the encoded RLWINM constant, or 0 if they cannot be merged.
+func mergePPC64ClrlsldiSrw(sld, srw int64) int64 {
+ mask_1 := uint64(0xFFFFFFFF >> uint(srw))
+ // for CLRLSLDI, it's more convient to think of it as a mask left bits then rotate left.
+ mask_2 := uint64(0xFFFFFFFFFFFFFFFF) >> uint(GetPPC64Shiftmb(int64(sld)))
+
+ // Rewrite mask to apply after the final left shift.
+ mask_3 := (mask_1 & mask_2) << uint(GetPPC64Shiftsh(sld))
+
+ r_1 := 32 - srw
+ r_2 := GetPPC64Shiftsh(sld)
+ r_3 := (r_1 + r_2) & 31 // This can wrap.
+
+ if uint64(uint32(mask_3)) != mask_3 || mask_3 == 0 {
+ return 0
+ }
+ return encodePPC64RotateMask(int64(r_3), int64(mask_3), 32)
+}
+
+// Test if a RLWINM feeding into a CLRLSLDI can be merged into RLWINM. Return
+// the encoded RLWINM constant, or 0 if they cannot be merged.
+func mergePPC64ClrlsldiRlwinm(sld int32, rlw int64) int64 {
+ r_1, _, _, mask_1 := DecodePPC64RotateMask(rlw)
+ // for CLRLSLDI, it's more convient to think of it as a mask left bits then rotate left.
+ mask_2 := uint64(0xFFFFFFFFFFFFFFFF) >> uint(GetPPC64Shiftmb(int64(sld)))
+
+ // combine the masks, and adjust for the final left shift.
+ mask_3 := (mask_1 & mask_2) << uint(GetPPC64Shiftsh(int64(sld)))
+ r_2 := GetPPC64Shiftsh(int64(sld))
+ r_3 := (r_1 + r_2) & 31 // This can wrap.
+
+ // Verify the result is still a valid bitmask of <= 32 bits.
+ if !isPPC64WordRotateMask(int64(mask_3)) || uint64(uint32(mask_3)) != mask_3 {
+ return 0
+ }
+ return encodePPC64RotateMask(r_3, int64(mask_3), 32)
+}
+
+// Compute the encoded RLWINM constant from combining (SLDconst [sld] (SRWconst [srw] x)),
+// or return 0 if they cannot be combined.
+func mergePPC64SldiSrw(sld, srw int64) int64 {
+ if sld > srw || srw >= 32 {
+ return 0
+ }
+ mask_r := uint32(0xFFFFFFFF) >> uint(srw)
+ mask_l := uint32(0xFFFFFFFF) >> uint(sld)
+ mask := (mask_r & mask_l) << uint(sld)
+ return encodePPC64RotateMask((32-srw+sld)&31, int64(mask), 32)
+}
+
+// Convenience function to rotate a 32 bit constant value by another constant.
+func rotateLeft32(v, rotate int64) int64 {
+ return int64(bits.RotateLeft32(uint32(v), int(rotate)))
+}
+
+// encodes the lsb and width for arm(64) bitfield ops into the expected auxInt format.
+func armBFAuxInt(lsb, width int64) arm64BitField {
+ if lsb < 0 || lsb > 63 {
+ panic("ARM(64) bit field lsb constant out of range")
+ }
+ if width < 1 || width > 64 {
+ panic("ARM(64) bit field width constant out of range")
+ }
+ return arm64BitField(width | lsb<<8)
+}
+
+// returns the lsb part of the auxInt field of arm64 bitfield ops.
+func (bfc arm64BitField) getARM64BFlsb() int64 {
+ return int64(uint64(bfc) >> 8)
+}
+
+// returns the width part of the auxInt field of arm64 bitfield ops.
+func (bfc arm64BitField) getARM64BFwidth() int64 {
+ return int64(bfc) & 0xff
+}
+
+// checks if mask >> rshift applied at lsb is a valid arm64 bitfield op mask.
+func isARM64BFMask(lsb, mask, rshift int64) bool {
+ shiftedMask := int64(uint64(mask) >> uint64(rshift))
+ return shiftedMask != 0 && isPowerOfTwo64(shiftedMask+1) && nto(shiftedMask)+lsb < 64
+}
+
+// returns the bitfield width of mask >> rshift for arm64 bitfield ops
+func arm64BFWidth(mask, rshift int64) int64 {
+ shiftedMask := int64(uint64(mask) >> uint64(rshift))
+ if shiftedMask == 0 {
+ panic("ARM64 BF mask is zero")
+ }
+ return nto(shiftedMask)
+}
+
+// sizeof returns the size of t in bytes.
+// It will panic if t is not a *types.Type.
+func sizeof(t interface{}) int64 {
+ return t.(*types.Type).Size()
+}
+
+// registerizable reports whether t is a primitive type that fits in
+// a register. It assumes float64 values will always fit into registers
+// even if that isn't strictly true.
+func registerizable(b *Block, typ *types.Type) bool {
+ if typ.IsPtrShaped() || typ.IsFloat() {
+ return true
+ }
+ if typ.IsInteger() {
+ return typ.Size() <= b.Func.Config.RegSize
+ }
+ return false
+}
+
+// needRaceCleanup reports whether this call to racefuncenter/exit isn't needed.
+func needRaceCleanup(sym *AuxCall, v *Value) bool {
+ f := v.Block.Func
+ if !f.Config.Race {
+ return false
+ }
+ if !isSameCall(sym, "runtime.racefuncenter") && !isSameCall(sym, "runtime.racefuncenterfp") && !isSameCall(sym, "runtime.racefuncexit") {
+ return false
+ }
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ switch v.Op {
+ case OpStaticCall:
+ // Check for racefuncenter/racefuncenterfp will encounter racefuncexit and vice versa.
+ // Allow calls to panic*
+ s := v.Aux.(*AuxCall).Fn.String()
+ switch s {
+ case "runtime.racefuncenter", "runtime.racefuncenterfp", "runtime.racefuncexit",
+ "runtime.panicdivide", "runtime.panicwrap",
+ "runtime.panicshift":
+ continue
+ }
+ // If we encountered any call, we need to keep racefunc*,
+ // for accurate stacktraces.
+ return false
+ case OpPanicBounds, OpPanicExtend:
+ // Note: these are panic generators that are ok (like the static calls above).
+ case OpClosureCall, OpInterCall:
+ // We must keep the race functions if there are any other call types.
+ return false
+ }
+ }
+ }
+ if isSameCall(sym, "runtime.racefuncenter") {
+ // If we're removing racefuncenter, remove its argument as well.
+ if v.Args[0].Op != OpStore {
+ return false
+ }
+ mem := v.Args[0].Args[2]
+ v.Args[0].reset(OpCopy)
+ v.Args[0].AddArg(mem)
+ }
+ return true
+}
+
+// symIsRO reports whether sym is a read-only global.
+func symIsRO(sym interface{}) bool {
+ lsym := sym.(*obj.LSym)
+ return lsym.Type == objabi.SRODATA && len(lsym.R) == 0
+}
+
+// symIsROZero reports whether sym is a read-only global whose data contains all zeros.
+func symIsROZero(sym Sym) bool {
+ lsym := sym.(*obj.LSym)
+ if lsym.Type != objabi.SRODATA || len(lsym.R) != 0 {
+ return false
+ }
+ for _, b := range lsym.P {
+ if b != 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// read8 reads one byte from the read-only global sym at offset off.
+func read8(sym interface{}, off int64) uint8 {
+ lsym := sym.(*obj.LSym)
+ if off >= int64(len(lsym.P)) || off < 0 {
+ // Invalid index into the global sym.
+ // This can happen in dead code, so we don't want to panic.
+ // Just return any value, it will eventually get ignored.
+ // See issue 29215.
+ return 0
+ }
+ return lsym.P[off]
+}
+
+// read16 reads two bytes from the read-only global sym at offset off.
+func read16(sym interface{}, off int64, byteorder binary.ByteOrder) uint16 {
+ lsym := sym.(*obj.LSym)
+ // lsym.P is written lazily.
+ // Bytes requested after the end of lsym.P are 0.
+ var src []byte
+ if 0 <= off && off < int64(len(lsym.P)) {
+ src = lsym.P[off:]
+ }
+ buf := make([]byte, 2)
+ copy(buf, src)
+ return byteorder.Uint16(buf)
+}
+
+// read32 reads four bytes from the read-only global sym at offset off.
+func read32(sym interface{}, off int64, byteorder binary.ByteOrder) uint32 {
+ lsym := sym.(*obj.LSym)
+ var src []byte
+ if 0 <= off && off < int64(len(lsym.P)) {
+ src = lsym.P[off:]
+ }
+ buf := make([]byte, 4)
+ copy(buf, src)
+ return byteorder.Uint32(buf)
+}
+
+// read64 reads eight bytes from the read-only global sym at offset off.
+func read64(sym interface{}, off int64, byteorder binary.ByteOrder) uint64 {
+ lsym := sym.(*obj.LSym)
+ var src []byte
+ if 0 <= off && off < int64(len(lsym.P)) {
+ src = lsym.P[off:]
+ }
+ buf := make([]byte, 8)
+ copy(buf, src)
+ return byteorder.Uint64(buf)
+}
+
+// sequentialAddresses reports true if it can prove that x + n == y
+func sequentialAddresses(x, y *Value, n int64) bool {
+ if x.Op == Op386ADDL && y.Op == Op386LEAL1 && y.AuxInt == n && y.Aux == nil &&
+ (x.Args[0] == y.Args[0] && x.Args[1] == y.Args[1] ||
+ x.Args[0] == y.Args[1] && x.Args[1] == y.Args[0]) {
+ return true
+ }
+ if x.Op == Op386LEAL1 && y.Op == Op386LEAL1 && y.AuxInt == x.AuxInt+n && x.Aux == y.Aux &&
+ (x.Args[0] == y.Args[0] && x.Args[1] == y.Args[1] ||
+ x.Args[0] == y.Args[1] && x.Args[1] == y.Args[0]) {
+ return true
+ }
+ if x.Op == OpAMD64ADDQ && y.Op == OpAMD64LEAQ1 && y.AuxInt == n && y.Aux == nil &&
+ (x.Args[0] == y.Args[0] && x.Args[1] == y.Args[1] ||
+ x.Args[0] == y.Args[1] && x.Args[1] == y.Args[0]) {
+ return true
+ }
+ if x.Op == OpAMD64LEAQ1 && y.Op == OpAMD64LEAQ1 && y.AuxInt == x.AuxInt+n && x.Aux == y.Aux &&
+ (x.Args[0] == y.Args[0] && x.Args[1] == y.Args[1] ||
+ x.Args[0] == y.Args[1] && x.Args[1] == y.Args[0]) {
+ return true
+ }
+ return false
+}
+
+// flagConstant represents the result of a compile-time comparison.
+// The sense of these flags does not necessarily represent the hardware's notion
+// of a flags register - these are just a compile-time construct.
+// We happen to match the semantics to those of arm/arm64.
+// Note that these semantics differ from x86: the carry flag has the opposite
+// sense on a subtraction!
+// On amd64, C=1 represents a borrow, e.g. SBB on amd64 does x - y - C.
+// On arm64, C=0 represents a borrow, e.g. SBC on arm64 does x - y - ^C.
+// (because it does x + ^y + C).
+// See https://en.wikipedia.org/wiki/Carry_flag#Vs._borrow_flag
+type flagConstant uint8
+
+// N reports whether the result of an operation is negative (high bit set).
+func (fc flagConstant) N() bool {
+ return fc&1 != 0
+}
+
+// Z reports whether the result of an operation is 0.
+func (fc flagConstant) Z() bool {
+ return fc&2 != 0
+}
+
+// C reports whether an unsigned add overflowed (carry), or an
+// unsigned subtract did not underflow (borrow).
+func (fc flagConstant) C() bool {
+ return fc&4 != 0
+}
+
+// V reports whether a signed operation overflowed or underflowed.
+func (fc flagConstant) V() bool {
+ return fc&8 != 0
+}
+
+func (fc flagConstant) eq() bool {
+ return fc.Z()
+}
+func (fc flagConstant) ne() bool {
+ return !fc.Z()
+}
+func (fc flagConstant) lt() bool {
+ return fc.N() != fc.V()
+}
+func (fc flagConstant) le() bool {
+ return fc.Z() || fc.lt()
+}
+func (fc flagConstant) gt() bool {
+ return !fc.Z() && fc.ge()
+}
+func (fc flagConstant) ge() bool {
+ return fc.N() == fc.V()
+}
+func (fc flagConstant) ult() bool {
+ return !fc.C()
+}
+func (fc flagConstant) ule() bool {
+ return fc.Z() || fc.ult()
+}
+func (fc flagConstant) ugt() bool {
+ return !fc.Z() && fc.uge()
+}
+func (fc flagConstant) uge() bool {
+ return fc.C()
+}
+
+func (fc flagConstant) ltNoov() bool {
+ return fc.lt() && !fc.V()
+}
+func (fc flagConstant) leNoov() bool {
+ return fc.le() && !fc.V()
+}
+func (fc flagConstant) gtNoov() bool {
+ return fc.gt() && !fc.V()
+}
+func (fc flagConstant) geNoov() bool {
+ return fc.ge() && !fc.V()
+}
+
+func (fc flagConstant) String() string {
+ return fmt.Sprintf("N=%v,Z=%v,C=%v,V=%v", fc.N(), fc.Z(), fc.C(), fc.V())
+}
+
+type flagConstantBuilder struct {
+ N bool
+ Z bool
+ C bool
+ V bool
+}
+
+func (fcs flagConstantBuilder) encode() flagConstant {
+ var fc flagConstant
+ if fcs.N {
+ fc |= 1
+ }
+ if fcs.Z {
+ fc |= 2
+ }
+ if fcs.C {
+ fc |= 4
+ }
+ if fcs.V {
+ fc |= 8
+ }
+ return fc
+}
+
+// Note: addFlags(x,y) != subFlags(x,-y) in some situations:
+// - the results of the C flag are different
+// - the results of the V flag when y==minint are different
+
+// addFlags64 returns the flags that would be set from computing x+y.
+func addFlags64(x, y int64) flagConstant {
+ var fcb flagConstantBuilder
+ fcb.Z = x+y == 0
+ fcb.N = x+y < 0
+ fcb.C = uint64(x+y) < uint64(x)
+ fcb.V = x >= 0 && y >= 0 && x+y < 0 || x < 0 && y < 0 && x+y >= 0
+ return fcb.encode()
+}
+
+// subFlags64 returns the flags that would be set from computing x-y.
+func subFlags64(x, y int64) flagConstant {
+ var fcb flagConstantBuilder
+ fcb.Z = x-y == 0
+ fcb.N = x-y < 0
+ fcb.C = uint64(y) <= uint64(x) // This code follows the arm carry flag model.
+ fcb.V = x >= 0 && y < 0 && x-y < 0 || x < 0 && y >= 0 && x-y >= 0
+ return fcb.encode()
+}
+
+// addFlags32 returns the flags that would be set from computing x+y.
+func addFlags32(x, y int32) flagConstant {
+ var fcb flagConstantBuilder
+ fcb.Z = x+y == 0
+ fcb.N = x+y < 0
+ fcb.C = uint32(x+y) < uint32(x)
+ fcb.V = x >= 0 && y >= 0 && x+y < 0 || x < 0 && y < 0 && x+y >= 0
+ return fcb.encode()
+}
+
+// subFlags32 returns the flags that would be set from computing x-y.
+func subFlags32(x, y int32) flagConstant {
+ var fcb flagConstantBuilder
+ fcb.Z = x-y == 0
+ fcb.N = x-y < 0
+ fcb.C = uint32(y) <= uint32(x) // This code follows the arm carry flag model.
+ fcb.V = x >= 0 && y < 0 && x-y < 0 || x < 0 && y >= 0 && x-y >= 0
+ return fcb.encode()
+}
+
+// logicFlags64 returns flags set to the sign/zeroness of x.
+// C and V are set to false.
+func logicFlags64(x int64) flagConstant {
+ var fcb flagConstantBuilder
+ fcb.Z = x == 0
+ fcb.N = x < 0
+ return fcb.encode()
+}
+
+// logicFlags32 returns flags set to the sign/zeroness of x.
+// C and V are set to false.
+func logicFlags32(x int32) flagConstant {
+ var fcb flagConstantBuilder
+ fcb.Z = x == 0
+ fcb.N = x < 0
+ return fcb.encode()
+}
diff --git a/src/cmd/compile/internal/ssa/rewrite386.go b/src/cmd/compile/internal/ssa/rewrite386.go
new file mode 100644
index 0000000..2acdccd
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewrite386.go
@@ -0,0 +1,12575 @@
+// Code generated from gen/386.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "math"
+import "cmd/compile/internal/types"
+
+func rewriteValue386(v *Value) bool {
+ switch v.Op {
+ case Op386ADCL:
+ return rewriteValue386_Op386ADCL(v)
+ case Op386ADDL:
+ return rewriteValue386_Op386ADDL(v)
+ case Op386ADDLcarry:
+ return rewriteValue386_Op386ADDLcarry(v)
+ case Op386ADDLconst:
+ return rewriteValue386_Op386ADDLconst(v)
+ case Op386ADDLconstmodify:
+ return rewriteValue386_Op386ADDLconstmodify(v)
+ case Op386ADDLload:
+ return rewriteValue386_Op386ADDLload(v)
+ case Op386ADDLmodify:
+ return rewriteValue386_Op386ADDLmodify(v)
+ case Op386ADDSD:
+ return rewriteValue386_Op386ADDSD(v)
+ case Op386ADDSDload:
+ return rewriteValue386_Op386ADDSDload(v)
+ case Op386ADDSS:
+ return rewriteValue386_Op386ADDSS(v)
+ case Op386ADDSSload:
+ return rewriteValue386_Op386ADDSSload(v)
+ case Op386ANDL:
+ return rewriteValue386_Op386ANDL(v)
+ case Op386ANDLconst:
+ return rewriteValue386_Op386ANDLconst(v)
+ case Op386ANDLconstmodify:
+ return rewriteValue386_Op386ANDLconstmodify(v)
+ case Op386ANDLload:
+ return rewriteValue386_Op386ANDLload(v)
+ case Op386ANDLmodify:
+ return rewriteValue386_Op386ANDLmodify(v)
+ case Op386CMPB:
+ return rewriteValue386_Op386CMPB(v)
+ case Op386CMPBconst:
+ return rewriteValue386_Op386CMPBconst(v)
+ case Op386CMPBload:
+ return rewriteValue386_Op386CMPBload(v)
+ case Op386CMPL:
+ return rewriteValue386_Op386CMPL(v)
+ case Op386CMPLconst:
+ return rewriteValue386_Op386CMPLconst(v)
+ case Op386CMPLload:
+ return rewriteValue386_Op386CMPLload(v)
+ case Op386CMPW:
+ return rewriteValue386_Op386CMPW(v)
+ case Op386CMPWconst:
+ return rewriteValue386_Op386CMPWconst(v)
+ case Op386CMPWload:
+ return rewriteValue386_Op386CMPWload(v)
+ case Op386DIVSD:
+ return rewriteValue386_Op386DIVSD(v)
+ case Op386DIVSDload:
+ return rewriteValue386_Op386DIVSDload(v)
+ case Op386DIVSS:
+ return rewriteValue386_Op386DIVSS(v)
+ case Op386DIVSSload:
+ return rewriteValue386_Op386DIVSSload(v)
+ case Op386LEAL:
+ return rewriteValue386_Op386LEAL(v)
+ case Op386LEAL1:
+ return rewriteValue386_Op386LEAL1(v)
+ case Op386LEAL2:
+ return rewriteValue386_Op386LEAL2(v)
+ case Op386LEAL4:
+ return rewriteValue386_Op386LEAL4(v)
+ case Op386LEAL8:
+ return rewriteValue386_Op386LEAL8(v)
+ case Op386MOVBLSX:
+ return rewriteValue386_Op386MOVBLSX(v)
+ case Op386MOVBLSXload:
+ return rewriteValue386_Op386MOVBLSXload(v)
+ case Op386MOVBLZX:
+ return rewriteValue386_Op386MOVBLZX(v)
+ case Op386MOVBload:
+ return rewriteValue386_Op386MOVBload(v)
+ case Op386MOVBstore:
+ return rewriteValue386_Op386MOVBstore(v)
+ case Op386MOVBstoreconst:
+ return rewriteValue386_Op386MOVBstoreconst(v)
+ case Op386MOVLload:
+ return rewriteValue386_Op386MOVLload(v)
+ case Op386MOVLstore:
+ return rewriteValue386_Op386MOVLstore(v)
+ case Op386MOVLstoreconst:
+ return rewriteValue386_Op386MOVLstoreconst(v)
+ case Op386MOVSDconst:
+ return rewriteValue386_Op386MOVSDconst(v)
+ case Op386MOVSDload:
+ return rewriteValue386_Op386MOVSDload(v)
+ case Op386MOVSDstore:
+ return rewriteValue386_Op386MOVSDstore(v)
+ case Op386MOVSSconst:
+ return rewriteValue386_Op386MOVSSconst(v)
+ case Op386MOVSSload:
+ return rewriteValue386_Op386MOVSSload(v)
+ case Op386MOVSSstore:
+ return rewriteValue386_Op386MOVSSstore(v)
+ case Op386MOVWLSX:
+ return rewriteValue386_Op386MOVWLSX(v)
+ case Op386MOVWLSXload:
+ return rewriteValue386_Op386MOVWLSXload(v)
+ case Op386MOVWLZX:
+ return rewriteValue386_Op386MOVWLZX(v)
+ case Op386MOVWload:
+ return rewriteValue386_Op386MOVWload(v)
+ case Op386MOVWstore:
+ return rewriteValue386_Op386MOVWstore(v)
+ case Op386MOVWstoreconst:
+ return rewriteValue386_Op386MOVWstoreconst(v)
+ case Op386MULL:
+ return rewriteValue386_Op386MULL(v)
+ case Op386MULLconst:
+ return rewriteValue386_Op386MULLconst(v)
+ case Op386MULLload:
+ return rewriteValue386_Op386MULLload(v)
+ case Op386MULSD:
+ return rewriteValue386_Op386MULSD(v)
+ case Op386MULSDload:
+ return rewriteValue386_Op386MULSDload(v)
+ case Op386MULSS:
+ return rewriteValue386_Op386MULSS(v)
+ case Op386MULSSload:
+ return rewriteValue386_Op386MULSSload(v)
+ case Op386NEGL:
+ return rewriteValue386_Op386NEGL(v)
+ case Op386NOTL:
+ return rewriteValue386_Op386NOTL(v)
+ case Op386ORL:
+ return rewriteValue386_Op386ORL(v)
+ case Op386ORLconst:
+ return rewriteValue386_Op386ORLconst(v)
+ case Op386ORLconstmodify:
+ return rewriteValue386_Op386ORLconstmodify(v)
+ case Op386ORLload:
+ return rewriteValue386_Op386ORLload(v)
+ case Op386ORLmodify:
+ return rewriteValue386_Op386ORLmodify(v)
+ case Op386ROLBconst:
+ return rewriteValue386_Op386ROLBconst(v)
+ case Op386ROLLconst:
+ return rewriteValue386_Op386ROLLconst(v)
+ case Op386ROLWconst:
+ return rewriteValue386_Op386ROLWconst(v)
+ case Op386SARB:
+ return rewriteValue386_Op386SARB(v)
+ case Op386SARBconst:
+ return rewriteValue386_Op386SARBconst(v)
+ case Op386SARL:
+ return rewriteValue386_Op386SARL(v)
+ case Op386SARLconst:
+ return rewriteValue386_Op386SARLconst(v)
+ case Op386SARW:
+ return rewriteValue386_Op386SARW(v)
+ case Op386SARWconst:
+ return rewriteValue386_Op386SARWconst(v)
+ case Op386SBBL:
+ return rewriteValue386_Op386SBBL(v)
+ case Op386SBBLcarrymask:
+ return rewriteValue386_Op386SBBLcarrymask(v)
+ case Op386SETA:
+ return rewriteValue386_Op386SETA(v)
+ case Op386SETAE:
+ return rewriteValue386_Op386SETAE(v)
+ case Op386SETB:
+ return rewriteValue386_Op386SETB(v)
+ case Op386SETBE:
+ return rewriteValue386_Op386SETBE(v)
+ case Op386SETEQ:
+ return rewriteValue386_Op386SETEQ(v)
+ case Op386SETG:
+ return rewriteValue386_Op386SETG(v)
+ case Op386SETGE:
+ return rewriteValue386_Op386SETGE(v)
+ case Op386SETL:
+ return rewriteValue386_Op386SETL(v)
+ case Op386SETLE:
+ return rewriteValue386_Op386SETLE(v)
+ case Op386SETNE:
+ return rewriteValue386_Op386SETNE(v)
+ case Op386SHLL:
+ return rewriteValue386_Op386SHLL(v)
+ case Op386SHLLconst:
+ return rewriteValue386_Op386SHLLconst(v)
+ case Op386SHRB:
+ return rewriteValue386_Op386SHRB(v)
+ case Op386SHRBconst:
+ return rewriteValue386_Op386SHRBconst(v)
+ case Op386SHRL:
+ return rewriteValue386_Op386SHRL(v)
+ case Op386SHRLconst:
+ return rewriteValue386_Op386SHRLconst(v)
+ case Op386SHRW:
+ return rewriteValue386_Op386SHRW(v)
+ case Op386SHRWconst:
+ return rewriteValue386_Op386SHRWconst(v)
+ case Op386SUBL:
+ return rewriteValue386_Op386SUBL(v)
+ case Op386SUBLcarry:
+ return rewriteValue386_Op386SUBLcarry(v)
+ case Op386SUBLconst:
+ return rewriteValue386_Op386SUBLconst(v)
+ case Op386SUBLload:
+ return rewriteValue386_Op386SUBLload(v)
+ case Op386SUBLmodify:
+ return rewriteValue386_Op386SUBLmodify(v)
+ case Op386SUBSD:
+ return rewriteValue386_Op386SUBSD(v)
+ case Op386SUBSDload:
+ return rewriteValue386_Op386SUBSDload(v)
+ case Op386SUBSS:
+ return rewriteValue386_Op386SUBSS(v)
+ case Op386SUBSSload:
+ return rewriteValue386_Op386SUBSSload(v)
+ case Op386XORL:
+ return rewriteValue386_Op386XORL(v)
+ case Op386XORLconst:
+ return rewriteValue386_Op386XORLconst(v)
+ case Op386XORLconstmodify:
+ return rewriteValue386_Op386XORLconstmodify(v)
+ case Op386XORLload:
+ return rewriteValue386_Op386XORLload(v)
+ case Op386XORLmodify:
+ return rewriteValue386_Op386XORLmodify(v)
+ case OpAdd16:
+ v.Op = Op386ADDL
+ return true
+ case OpAdd32:
+ v.Op = Op386ADDL
+ return true
+ case OpAdd32F:
+ v.Op = Op386ADDSS
+ return true
+ case OpAdd32carry:
+ v.Op = Op386ADDLcarry
+ return true
+ case OpAdd32withcarry:
+ v.Op = Op386ADCL
+ return true
+ case OpAdd64F:
+ v.Op = Op386ADDSD
+ return true
+ case OpAdd8:
+ v.Op = Op386ADDL
+ return true
+ case OpAddPtr:
+ v.Op = Op386ADDL
+ return true
+ case OpAddr:
+ return rewriteValue386_OpAddr(v)
+ case OpAnd16:
+ v.Op = Op386ANDL
+ return true
+ case OpAnd32:
+ v.Op = Op386ANDL
+ return true
+ case OpAnd8:
+ v.Op = Op386ANDL
+ return true
+ case OpAndB:
+ v.Op = Op386ANDL
+ return true
+ case OpAvg32u:
+ v.Op = Op386AVGLU
+ return true
+ case OpBswap32:
+ v.Op = Op386BSWAPL
+ return true
+ case OpClosureCall:
+ v.Op = Op386CALLclosure
+ return true
+ case OpCom16:
+ v.Op = Op386NOTL
+ return true
+ case OpCom32:
+ v.Op = Op386NOTL
+ return true
+ case OpCom8:
+ v.Op = Op386NOTL
+ return true
+ case OpConst16:
+ return rewriteValue386_OpConst16(v)
+ case OpConst32:
+ v.Op = Op386MOVLconst
+ return true
+ case OpConst32F:
+ v.Op = Op386MOVSSconst
+ return true
+ case OpConst64F:
+ v.Op = Op386MOVSDconst
+ return true
+ case OpConst8:
+ return rewriteValue386_OpConst8(v)
+ case OpConstBool:
+ return rewriteValue386_OpConstBool(v)
+ case OpConstNil:
+ return rewriteValue386_OpConstNil(v)
+ case OpCtz16:
+ return rewriteValue386_OpCtz16(v)
+ case OpCtz16NonZero:
+ v.Op = Op386BSFL
+ return true
+ case OpCvt32Fto32:
+ v.Op = Op386CVTTSS2SL
+ return true
+ case OpCvt32Fto64F:
+ v.Op = Op386CVTSS2SD
+ return true
+ case OpCvt32to32F:
+ v.Op = Op386CVTSL2SS
+ return true
+ case OpCvt32to64F:
+ v.Op = Op386CVTSL2SD
+ return true
+ case OpCvt64Fto32:
+ v.Op = Op386CVTTSD2SL
+ return true
+ case OpCvt64Fto32F:
+ v.Op = Op386CVTSD2SS
+ return true
+ case OpCvtBoolToUint8:
+ v.Op = OpCopy
+ return true
+ case OpDiv16:
+ v.Op = Op386DIVW
+ return true
+ case OpDiv16u:
+ v.Op = Op386DIVWU
+ return true
+ case OpDiv32:
+ v.Op = Op386DIVL
+ return true
+ case OpDiv32F:
+ v.Op = Op386DIVSS
+ return true
+ case OpDiv32u:
+ v.Op = Op386DIVLU
+ return true
+ case OpDiv64F:
+ v.Op = Op386DIVSD
+ return true
+ case OpDiv8:
+ return rewriteValue386_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValue386_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValue386_OpEq16(v)
+ case OpEq32:
+ return rewriteValue386_OpEq32(v)
+ case OpEq32F:
+ return rewriteValue386_OpEq32F(v)
+ case OpEq64F:
+ return rewriteValue386_OpEq64F(v)
+ case OpEq8:
+ return rewriteValue386_OpEq8(v)
+ case OpEqB:
+ return rewriteValue386_OpEqB(v)
+ case OpEqPtr:
+ return rewriteValue386_OpEqPtr(v)
+ case OpGetCallerPC:
+ v.Op = Op386LoweredGetCallerPC
+ return true
+ case OpGetCallerSP:
+ v.Op = Op386LoweredGetCallerSP
+ return true
+ case OpGetClosurePtr:
+ v.Op = Op386LoweredGetClosurePtr
+ return true
+ case OpGetG:
+ v.Op = Op386LoweredGetG
+ return true
+ case OpHmul32:
+ v.Op = Op386HMULL
+ return true
+ case OpHmul32u:
+ v.Op = Op386HMULLU
+ return true
+ case OpInterCall:
+ v.Op = Op386CALLinter
+ return true
+ case OpIsInBounds:
+ return rewriteValue386_OpIsInBounds(v)
+ case OpIsNonNil:
+ return rewriteValue386_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ return rewriteValue386_OpIsSliceInBounds(v)
+ case OpLeq16:
+ return rewriteValue386_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValue386_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValue386_OpLeq32(v)
+ case OpLeq32F:
+ return rewriteValue386_OpLeq32F(v)
+ case OpLeq32U:
+ return rewriteValue386_OpLeq32U(v)
+ case OpLeq64F:
+ return rewriteValue386_OpLeq64F(v)
+ case OpLeq8:
+ return rewriteValue386_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValue386_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValue386_OpLess16(v)
+ case OpLess16U:
+ return rewriteValue386_OpLess16U(v)
+ case OpLess32:
+ return rewriteValue386_OpLess32(v)
+ case OpLess32F:
+ return rewriteValue386_OpLess32F(v)
+ case OpLess32U:
+ return rewriteValue386_OpLess32U(v)
+ case OpLess64F:
+ return rewriteValue386_OpLess64F(v)
+ case OpLess8:
+ return rewriteValue386_OpLess8(v)
+ case OpLess8U:
+ return rewriteValue386_OpLess8U(v)
+ case OpLoad:
+ return rewriteValue386_OpLoad(v)
+ case OpLocalAddr:
+ return rewriteValue386_OpLocalAddr(v)
+ case OpLsh16x16:
+ return rewriteValue386_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValue386_OpLsh16x32(v)
+ case OpLsh16x64:
+ return rewriteValue386_OpLsh16x64(v)
+ case OpLsh16x8:
+ return rewriteValue386_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValue386_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValue386_OpLsh32x32(v)
+ case OpLsh32x64:
+ return rewriteValue386_OpLsh32x64(v)
+ case OpLsh32x8:
+ return rewriteValue386_OpLsh32x8(v)
+ case OpLsh8x16:
+ return rewriteValue386_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValue386_OpLsh8x32(v)
+ case OpLsh8x64:
+ return rewriteValue386_OpLsh8x64(v)
+ case OpLsh8x8:
+ return rewriteValue386_OpLsh8x8(v)
+ case OpMod16:
+ v.Op = Op386MODW
+ return true
+ case OpMod16u:
+ v.Op = Op386MODWU
+ return true
+ case OpMod32:
+ v.Op = Op386MODL
+ return true
+ case OpMod32u:
+ v.Op = Op386MODLU
+ return true
+ case OpMod8:
+ return rewriteValue386_OpMod8(v)
+ case OpMod8u:
+ return rewriteValue386_OpMod8u(v)
+ case OpMove:
+ return rewriteValue386_OpMove(v)
+ case OpMul16:
+ v.Op = Op386MULL
+ return true
+ case OpMul32:
+ v.Op = Op386MULL
+ return true
+ case OpMul32F:
+ v.Op = Op386MULSS
+ return true
+ case OpMul32uhilo:
+ v.Op = Op386MULLQU
+ return true
+ case OpMul64F:
+ v.Op = Op386MULSD
+ return true
+ case OpMul8:
+ v.Op = Op386MULL
+ return true
+ case OpNeg16:
+ v.Op = Op386NEGL
+ return true
+ case OpNeg32:
+ v.Op = Op386NEGL
+ return true
+ case OpNeg32F:
+ return rewriteValue386_OpNeg32F(v)
+ case OpNeg64F:
+ return rewriteValue386_OpNeg64F(v)
+ case OpNeg8:
+ v.Op = Op386NEGL
+ return true
+ case OpNeq16:
+ return rewriteValue386_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValue386_OpNeq32(v)
+ case OpNeq32F:
+ return rewriteValue386_OpNeq32F(v)
+ case OpNeq64F:
+ return rewriteValue386_OpNeq64F(v)
+ case OpNeq8:
+ return rewriteValue386_OpNeq8(v)
+ case OpNeqB:
+ return rewriteValue386_OpNeqB(v)
+ case OpNeqPtr:
+ return rewriteValue386_OpNeqPtr(v)
+ case OpNilCheck:
+ v.Op = Op386LoweredNilCheck
+ return true
+ case OpNot:
+ return rewriteValue386_OpNot(v)
+ case OpOffPtr:
+ return rewriteValue386_OpOffPtr(v)
+ case OpOr16:
+ v.Op = Op386ORL
+ return true
+ case OpOr32:
+ v.Op = Op386ORL
+ return true
+ case OpOr8:
+ v.Op = Op386ORL
+ return true
+ case OpOrB:
+ v.Op = Op386ORL
+ return true
+ case OpPanicBounds:
+ return rewriteValue386_OpPanicBounds(v)
+ case OpPanicExtend:
+ return rewriteValue386_OpPanicExtend(v)
+ case OpRotateLeft16:
+ return rewriteValue386_OpRotateLeft16(v)
+ case OpRotateLeft32:
+ return rewriteValue386_OpRotateLeft32(v)
+ case OpRotateLeft8:
+ return rewriteValue386_OpRotateLeft8(v)
+ case OpRound32F:
+ v.Op = OpCopy
+ return true
+ case OpRound64F:
+ v.Op = OpCopy
+ return true
+ case OpRsh16Ux16:
+ return rewriteValue386_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValue386_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValue386_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValue386_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValue386_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValue386_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValue386_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValue386_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValue386_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValue386_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValue386_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValue386_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValue386_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValue386_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValue386_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValue386_OpRsh32x8(v)
+ case OpRsh8Ux16:
+ return rewriteValue386_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValue386_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValue386_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValue386_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValue386_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValue386_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValue386_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValue386_OpRsh8x8(v)
+ case OpSelect0:
+ return rewriteValue386_OpSelect0(v)
+ case OpSelect1:
+ return rewriteValue386_OpSelect1(v)
+ case OpSignExt16to32:
+ v.Op = Op386MOVWLSX
+ return true
+ case OpSignExt8to16:
+ v.Op = Op386MOVBLSX
+ return true
+ case OpSignExt8to32:
+ v.Op = Op386MOVBLSX
+ return true
+ case OpSignmask:
+ return rewriteValue386_OpSignmask(v)
+ case OpSlicemask:
+ return rewriteValue386_OpSlicemask(v)
+ case OpSqrt:
+ v.Op = Op386SQRTSD
+ return true
+ case OpStaticCall:
+ v.Op = Op386CALLstatic
+ return true
+ case OpStore:
+ return rewriteValue386_OpStore(v)
+ case OpSub16:
+ v.Op = Op386SUBL
+ return true
+ case OpSub32:
+ v.Op = Op386SUBL
+ return true
+ case OpSub32F:
+ v.Op = Op386SUBSS
+ return true
+ case OpSub32carry:
+ v.Op = Op386SUBLcarry
+ return true
+ case OpSub32withcarry:
+ v.Op = Op386SBBL
+ return true
+ case OpSub64F:
+ v.Op = Op386SUBSD
+ return true
+ case OpSub8:
+ v.Op = Op386SUBL
+ return true
+ case OpSubPtr:
+ v.Op = Op386SUBL
+ return true
+ case OpTrunc16to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to8:
+ v.Op = OpCopy
+ return true
+ case OpWB:
+ v.Op = Op386LoweredWB
+ return true
+ case OpXor16:
+ v.Op = Op386XORL
+ return true
+ case OpXor32:
+ v.Op = Op386XORL
+ return true
+ case OpXor8:
+ v.Op = Op386XORL
+ return true
+ case OpZero:
+ return rewriteValue386_OpZero(v)
+ case OpZeroExt16to32:
+ v.Op = Op386MOVWLZX
+ return true
+ case OpZeroExt8to16:
+ v.Op = Op386MOVBLZX
+ return true
+ case OpZeroExt8to32:
+ v.Op = Op386MOVBLZX
+ return true
+ case OpZeromask:
+ return rewriteValue386_OpZeromask(v)
+ }
+ return false
+}
+func rewriteValue386_Op386ADCL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADCL x (MOVLconst [c]) f)
+ // result: (ADCLconst [c] x f)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ f := v_2
+ v.reset(Op386ADCLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, f)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValue386_Op386ADDL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDL x (MOVLconst [c]))
+ // result: (ADDLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386ADDLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDL (SHLLconst [c] x) (SHRLconst [d] x))
+ // cond: d == 32-c
+ // result: (ROLLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386SHLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != Op386SHRLconst {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 32-c) {
+ continue
+ }
+ v.reset(Op386ROLLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDL <t> (SHLLconst x [c]) (SHRWconst x [d]))
+ // cond: c < 16 && d == int16(16-c) && t.Size() == 2
+ // result: (ROLWconst x [int16(c)])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386SHLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != Op386SHRWconst {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ if x != v_1.Args[0] || !(c < 16 && d == int16(16-c) && t.Size() == 2) {
+ continue
+ }
+ v.reset(Op386ROLWconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDL <t> (SHLLconst x [c]) (SHRBconst x [d]))
+ // cond: c < 8 && d == int8(8-c) && t.Size() == 1
+ // result: (ROLBconst x [int8(c)])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386SHLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != Op386SHRBconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(c < 8 && d == int8(8-c) && t.Size() == 1) {
+ continue
+ }
+ v.reset(Op386ROLBconst)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (SHLLconst [3] y))
+ // result: (LEAL8 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386SHLLconst || auxIntToInt32(v_1.AuxInt) != 3 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(Op386LEAL8)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (SHLLconst [2] y))
+ // result: (LEAL4 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386SHLLconst || auxIntToInt32(v_1.AuxInt) != 2 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(Op386LEAL4)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (SHLLconst [1] y))
+ // result: (LEAL2 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386SHLLconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(Op386LEAL2)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (ADDL y y))
+ // result: (LEAL2 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386ADDL {
+ continue
+ }
+ y := v_1.Args[1]
+ if y != v_1.Args[0] {
+ continue
+ }
+ v.reset(Op386LEAL2)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (ADDL x y))
+ // result: (LEAL2 y x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386ADDL {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(Op386LEAL2)
+ v.AddArg2(y, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ADDL (ADDLconst [c] x) y)
+ // result: (LEAL1 [c] x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386ADDLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(Op386LEAL1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (LEAL [c] {s} y))
+ // cond: x.Op != OpSB && y.Op != OpSB
+ // result: (LEAL1 [c] {s} x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386LEAL {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ s := auxToSym(v_1.Aux)
+ y := v_1.Args[0]
+ if !(x.Op != OpSB && y.Op != OpSB) {
+ continue
+ }
+ v.reset(Op386LEAL1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ADDLload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVLload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(Op386ADDLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (NEGL y))
+ // result: (SUBL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386NEGL {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(Op386SUBL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValue386_Op386ADDLcarry(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDLcarry x (MOVLconst [c]))
+ // result: (ADDLconstcarry [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386ADDLconstcarry)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValue386_Op386ADDLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDLconst [c] (ADDL x y))
+ // result: (LEAL1 [c] x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386ADDL {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(Op386LEAL1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDLconst [c] (LEAL [d] {s} x))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL [c+d] {s} x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(Op386LEAL)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDLconst [c] x:(SP))
+ // result: (LEAL [c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpSP {
+ break
+ }
+ v.reset(Op386LEAL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDLconst [c] (LEAL1 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL1 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386LEAL1 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(Op386LEAL1)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDLconst [c] (LEAL2 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL2 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386LEAL2 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(Op386LEAL2)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDLconst [c] (LEAL4 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL4 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386LEAL4 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(Op386LEAL4)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDLconst [c] (LEAL8 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL8 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386LEAL8 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(Op386LEAL8)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDLconst [c] x)
+ // cond: c==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ADDLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [c+d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ return true
+ }
+ // match: (ADDLconst [c] (ADDLconst [d] x))
+ // result: (ADDLconst [c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(Op386ADDLconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ADDLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ADDLconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem)
+ // cond: valoff1.canAdd32(off2)
+ // result: (ADDLconstmodify [valoff1.addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(valoff1.canAdd32(off2)) {
+ break
+ }
+ v.reset(Op386ADDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(valoff1.addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (ADDLconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: valoff1.canAdd32(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ADDLconstmodify [valoff1.addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(valoff1.canAdd32(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ADDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(valoff1.addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ADDLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ADDLload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ADDLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386ADDLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDLload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ADDLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ADDLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ADDLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ADDLmodify [off1] {sym} (ADDLconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ADDLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386ADDLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (ADDLmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ADDLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ADDLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ADDSD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDSD x l:(MOVSDload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ADDSDload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVSDload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(Op386ADDSDload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValue386_Op386ADDSDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ADDSDload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ADDSDload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386ADDSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDSDload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ADDSDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ADDSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ADDSS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDSS x l:(MOVSSload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ADDSSload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVSSload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(Op386ADDSSload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValue386_Op386ADDSSload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ADDSSload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ADDSSload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386ADDSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDSSload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ADDSSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ADDSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ANDL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ANDL x (MOVLconst [c]))
+ // result: (ANDLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386ANDLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ANDL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ANDLload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVLload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(Op386ANDLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (ANDL x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ANDLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ANDLconst [c] (ANDLconst [d] x))
+ // result: (ANDLconst [c & d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386ANDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(Op386ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDLconst [c] _)
+ // cond: c==0
+ // result: (MOVLconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if !(c == 0) {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (ANDLconst [c] x)
+ // cond: c==-1
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c == -1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [c&d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(c & d)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ANDLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ANDLconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem)
+ // cond: valoff1.canAdd32(off2)
+ // result: (ANDLconstmodify [valoff1.addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(valoff1.canAdd32(off2)) {
+ break
+ }
+ v.reset(Op386ANDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(valoff1.addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (ANDLconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: valoff1.canAdd32(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ANDLconstmodify [valoff1.addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(valoff1.canAdd32(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ANDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(valoff1.addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ANDLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ANDLload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ANDLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386ANDLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ANDLload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ANDLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ANDLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ANDLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ANDLmodify [off1] {sym} (ADDLconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ANDLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386ANDLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (ANDLmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ANDLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ANDLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPB x (MOVLconst [c]))
+ // result: (CMPBconst x [int8(c)])
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386CMPBconst)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPB (MOVLconst [c]) x)
+ // result: (InvertFlags (CMPBconst x [int8(c)]))
+ for {
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(v.Pos, Op386CMPBconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPB x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPB y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(v.Pos, Op386CMPB, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPB l:(MOVBload {sym} [off] ptr mem) x)
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (CMPBload {sym} [off] ptr x mem)
+ for {
+ l := v_0
+ if l.Op != Op386MOVBload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ x := v_1
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(Op386CMPBload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (CMPB x l:(MOVBload {sym} [off] ptr mem))
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (InvertFlags (CMPBload {sym} [off] ptr x mem))
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVBload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(l.Pos, Op386CMPBload, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, x, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPBconst (MOVLconst [x]) [y])
+ // cond: int8(x)==y
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt8(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int8(x) == y) {
+ break
+ }
+ v.reset(Op386FlagEQ)
+ return true
+ }
+ // match: (CMPBconst (MOVLconst [x]) [y])
+ // cond: int8(x)<y && uint8(x)<uint8(y)
+ // result: (FlagLT_ULT)
+ for {
+ y := auxIntToInt8(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int8(x) < y && uint8(x) < uint8(y)) {
+ break
+ }
+ v.reset(Op386FlagLT_ULT)
+ return true
+ }
+ // match: (CMPBconst (MOVLconst [x]) [y])
+ // cond: int8(x)<y && uint8(x)>uint8(y)
+ // result: (FlagLT_UGT)
+ for {
+ y := auxIntToInt8(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int8(x) < y && uint8(x) > uint8(y)) {
+ break
+ }
+ v.reset(Op386FlagLT_UGT)
+ return true
+ }
+ // match: (CMPBconst (MOVLconst [x]) [y])
+ // cond: int8(x)>y && uint8(x)<uint8(y)
+ // result: (FlagGT_ULT)
+ for {
+ y := auxIntToInt8(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int8(x) > y && uint8(x) < uint8(y)) {
+ break
+ }
+ v.reset(Op386FlagGT_ULT)
+ return true
+ }
+ // match: (CMPBconst (MOVLconst [x]) [y])
+ // cond: int8(x)>y && uint8(x)>uint8(y)
+ // result: (FlagGT_UGT)
+ for {
+ y := auxIntToInt8(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int8(x) > y && uint8(x) > uint8(y)) {
+ break
+ }
+ v.reset(Op386FlagGT_UGT)
+ return true
+ }
+ // match: (CMPBconst (ANDLconst _ [m]) [n])
+ // cond: 0 <= int8(m) && int8(m) < n
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt8(v.AuxInt)
+ if v_0.Op != Op386ANDLconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= int8(m) && int8(m) < n) {
+ break
+ }
+ v.reset(Op386FlagLT_ULT)
+ return true
+ }
+ // match: (CMPBconst l:(ANDL x y) [0])
+ // cond: l.Uses==1
+ // result: (TESTB x y)
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ l := v_0
+ if l.Op != Op386ANDL {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v.reset(Op386TESTB)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPBconst l:(ANDLconst [c] x) [0])
+ // cond: l.Uses==1
+ // result: (TESTBconst [int8(c)] x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ l := v_0
+ if l.Op != Op386ANDLconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v.reset(Op386TESTBconst)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPBconst x [0])
+ // result: (TESTB x x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.reset(Op386TESTB)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPBconst l:(MOVBload {sym} [off] ptr mem) [c])
+ // cond: l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l)
+ // result: @l.Block (CMPBconstload {sym} [makeValAndOff32(int32(c),int32(off))] ptr mem)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ l := v_0
+ if l.Op != Op386MOVBload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l)) {
+ break
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, Op386CMPBconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), int32(off)))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPBload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPBload {sym} [off] ptr (MOVLconst [c]) mem)
+ // cond: validValAndOff(int64(int8(c)),int64(off))
+ // result: (CMPBconstload {sym} [makeValAndOff32(int32(int8(c)),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ if !(validValAndOff(int64(int8(c)), int64(off))) {
+ break
+ }
+ v.reset(Op386CMPBconstload)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(int8(c)), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPL x (MOVLconst [c]))
+ // result: (CMPLconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386CMPLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPL (MOVLconst [c]) x)
+ // result: (InvertFlags (CMPLconst x [c]))
+ for {
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPL x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPL y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPL l:(MOVLload {sym} [off] ptr mem) x)
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (CMPLload {sym} [off] ptr x mem)
+ for {
+ l := v_0
+ if l.Op != Op386MOVLload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ x := v_1
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(Op386CMPLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (CMPL x l:(MOVLload {sym} [off] ptr mem))
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (InvertFlags (CMPLload {sym} [off] ptr x mem))
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVLload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(l.Pos, Op386CMPLload, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, x, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPLconst (MOVLconst [x]) [y])
+ // cond: x==y
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x == y) {
+ break
+ }
+ v.reset(Op386FlagEQ)
+ return true
+ }
+ // match: (CMPLconst (MOVLconst [x]) [y])
+ // cond: x<y && uint32(x)<uint32(y)
+ // result: (FlagLT_ULT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x < y && uint32(x) < uint32(y)) {
+ break
+ }
+ v.reset(Op386FlagLT_ULT)
+ return true
+ }
+ // match: (CMPLconst (MOVLconst [x]) [y])
+ // cond: x<y && uint32(x)>uint32(y)
+ // result: (FlagLT_UGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x < y && uint32(x) > uint32(y)) {
+ break
+ }
+ v.reset(Op386FlagLT_UGT)
+ return true
+ }
+ // match: (CMPLconst (MOVLconst [x]) [y])
+ // cond: x>y && uint32(x)<uint32(y)
+ // result: (FlagGT_ULT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x > y && uint32(x) < uint32(y)) {
+ break
+ }
+ v.reset(Op386FlagGT_ULT)
+ return true
+ }
+ // match: (CMPLconst (MOVLconst [x]) [y])
+ // cond: x>y && uint32(x)>uint32(y)
+ // result: (FlagGT_UGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x > y && uint32(x) > uint32(y)) {
+ break
+ }
+ v.reset(Op386FlagGT_UGT)
+ return true
+ }
+ // match: (CMPLconst (SHRLconst _ [c]) [n])
+ // cond: 0 <= n && 0 < c && c <= 32 && (1<<uint64(32-c)) <= uint64(n)
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386SHRLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= n && 0 < c && c <= 32 && (1<<uint64(32-c)) <= uint64(n)) {
+ break
+ }
+ v.reset(Op386FlagLT_ULT)
+ return true
+ }
+ // match: (CMPLconst (ANDLconst _ [m]) [n])
+ // cond: 0 <= m && m < n
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386ANDLconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= m && m < n) {
+ break
+ }
+ v.reset(Op386FlagLT_ULT)
+ return true
+ }
+ // match: (CMPLconst l:(ANDL x y) [0])
+ // cond: l.Uses==1
+ // result: (TESTL x y)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ l := v_0
+ if l.Op != Op386ANDL {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v.reset(Op386TESTL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPLconst l:(ANDLconst [c] x) [0])
+ // cond: l.Uses==1
+ // result: (TESTLconst [c] x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ l := v_0
+ if l.Op != Op386ANDLconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v.reset(Op386TESTLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPLconst x [0])
+ // result: (TESTL x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.reset(Op386TESTL)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPLconst l:(MOVLload {sym} [off] ptr mem) [c])
+ // cond: l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l)
+ // result: @l.Block (CMPLconstload {sym} [makeValAndOff32(int32(c),int32(off))] ptr mem)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ l := v_0
+ if l.Op != Op386MOVLload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l)) {
+ break
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, Op386CMPLconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), int32(off)))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPLload {sym} [off] ptr (MOVLconst [c]) mem)
+ // cond: validValAndOff(int64(c),int64(off))
+ // result: (CMPLconstload {sym} [makeValAndOff32(c,off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ if !(validValAndOff(int64(c), int64(off))) {
+ break
+ }
+ v.reset(Op386CMPLconstload)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPW x (MOVLconst [c]))
+ // result: (CMPWconst x [int16(c)])
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386CMPWconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPW (MOVLconst [c]) x)
+ // result: (InvertFlags (CMPWconst x [int16(c)]))
+ for {
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(v.Pos, Op386CMPWconst, types.TypeFlags)
+ v0.AuxInt = int16ToAuxInt(int16(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPW x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPW y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(v.Pos, Op386CMPW, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPW l:(MOVWload {sym} [off] ptr mem) x)
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (CMPWload {sym} [off] ptr x mem)
+ for {
+ l := v_0
+ if l.Op != Op386MOVWload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ x := v_1
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(Op386CMPWload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (CMPW x l:(MOVWload {sym} [off] ptr mem))
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (InvertFlags (CMPWload {sym} [off] ptr x mem))
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVWload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(l.Pos, Op386CMPWload, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, x, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPWconst (MOVLconst [x]) [y])
+ // cond: int16(x)==y
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt16(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int16(x) == y) {
+ break
+ }
+ v.reset(Op386FlagEQ)
+ return true
+ }
+ // match: (CMPWconst (MOVLconst [x]) [y])
+ // cond: int16(x)<y && uint16(x)<uint16(y)
+ // result: (FlagLT_ULT)
+ for {
+ y := auxIntToInt16(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int16(x) < y && uint16(x) < uint16(y)) {
+ break
+ }
+ v.reset(Op386FlagLT_ULT)
+ return true
+ }
+ // match: (CMPWconst (MOVLconst [x]) [y])
+ // cond: int16(x)<y && uint16(x)>uint16(y)
+ // result: (FlagLT_UGT)
+ for {
+ y := auxIntToInt16(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int16(x) < y && uint16(x) > uint16(y)) {
+ break
+ }
+ v.reset(Op386FlagLT_UGT)
+ return true
+ }
+ // match: (CMPWconst (MOVLconst [x]) [y])
+ // cond: int16(x)>y && uint16(x)<uint16(y)
+ // result: (FlagGT_ULT)
+ for {
+ y := auxIntToInt16(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int16(x) > y && uint16(x) < uint16(y)) {
+ break
+ }
+ v.reset(Op386FlagGT_ULT)
+ return true
+ }
+ // match: (CMPWconst (MOVLconst [x]) [y])
+ // cond: int16(x)>y && uint16(x)>uint16(y)
+ // result: (FlagGT_UGT)
+ for {
+ y := auxIntToInt16(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int16(x) > y && uint16(x) > uint16(y)) {
+ break
+ }
+ v.reset(Op386FlagGT_UGT)
+ return true
+ }
+ // match: (CMPWconst (ANDLconst _ [m]) [n])
+ // cond: 0 <= int16(m) && int16(m) < n
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt16(v.AuxInt)
+ if v_0.Op != Op386ANDLconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= int16(m) && int16(m) < n) {
+ break
+ }
+ v.reset(Op386FlagLT_ULT)
+ return true
+ }
+ // match: (CMPWconst l:(ANDL x y) [0])
+ // cond: l.Uses==1
+ // result: (TESTW x y)
+ for {
+ if auxIntToInt16(v.AuxInt) != 0 {
+ break
+ }
+ l := v_0
+ if l.Op != Op386ANDL {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v.reset(Op386TESTW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPWconst l:(ANDLconst [c] x) [0])
+ // cond: l.Uses==1
+ // result: (TESTWconst [int16(c)] x)
+ for {
+ if auxIntToInt16(v.AuxInt) != 0 {
+ break
+ }
+ l := v_0
+ if l.Op != Op386ANDLconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v.reset(Op386TESTWconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPWconst x [0])
+ // result: (TESTW x x)
+ for {
+ if auxIntToInt16(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.reset(Op386TESTW)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPWconst l:(MOVWload {sym} [off] ptr mem) [c])
+ // cond: l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l)
+ // result: @l.Block (CMPWconstload {sym} [makeValAndOff32(int32(c),int32(off))] ptr mem)
+ for {
+ c := auxIntToInt16(v.AuxInt)
+ l := v_0
+ if l.Op != Op386MOVWload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l)) {
+ break
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, Op386CMPWconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), int32(off)))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPWload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPWload {sym} [off] ptr (MOVLconst [c]) mem)
+ // cond: validValAndOff(int64(int16(c)),int64(off))
+ // result: (CMPWconstload {sym} [makeValAndOff32(int32(int16(c)),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ if !(validValAndOff(int64(int16(c)), int64(off))) {
+ break
+ }
+ v.reset(Op386CMPWconstload)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(int16(c)), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386DIVSD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (DIVSD x l:(MOVSDload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (DIVSDload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVSDload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386DIVSDload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386DIVSDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (DIVSDload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (DIVSDload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386DIVSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (DIVSDload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (DIVSDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386DIVSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386DIVSS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (DIVSS x l:(MOVSSload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (DIVSSload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVSSload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386DIVSSload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386DIVSSload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (DIVSSload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (DIVSSload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386DIVSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (DIVSSload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (DIVSSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386DIVSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386LEAL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LEAL [c] {s} (ADDLconst [d] x))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL [c+d] {s} x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(Op386LEAL)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LEAL [c] {s} (ADDL x y))
+ // cond: x.Op != OpSB && y.Op != OpSB
+ // result: (LEAL1 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDL {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if !(x.Op != OpSB && y.Op != OpSB) {
+ continue
+ }
+ v.reset(Op386LEAL1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAL [off1] {sym1} (LEAL [off2] {sym2} x))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAL [off1+off2] {mergeSym(sym1,sym2)} x)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(Op386LEAL)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg(x)
+ return true
+ }
+ // match: (LEAL [off1] {sym1} (LEAL1 [off2] {sym2} x y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAL1 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL1 {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(Op386LEAL1)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL [off1] {sym1} (LEAL2 [off2] {sym2} x y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAL2 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL2 {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(Op386LEAL2)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL [off1] {sym1} (LEAL4 [off2] {sym2} x y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAL4 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL4 {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(Op386LEAL4)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL [off1] {sym1} (LEAL8 [off2] {sym2} x y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAL8 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL8 {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(Op386LEAL8)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386LEAL1(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAL1 [c] {s} (ADDLconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAL1 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386ADDLconst {
+ continue
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ continue
+ }
+ v.reset(Op386LEAL1)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAL1 [c] {s} x (SHLLconst [1] y))
+ // result: (LEAL2 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386SHLLconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(Op386LEAL2)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAL1 [c] {s} x (SHLLconst [2] y))
+ // result: (LEAL4 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386SHLLconst || auxIntToInt32(v_1.AuxInt) != 2 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(Op386LEAL4)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAL1 [c] {s} x (SHLLconst [3] y))
+ // result: (LEAL8 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386SHLLconst || auxIntToInt32(v_1.AuxInt) != 3 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(Op386LEAL8)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAL1 [off1] {sym1} (LEAL [off2] {sym2} x) y)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB
+ // result: (LEAL1 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386LEAL {
+ continue
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB) {
+ continue
+ }
+ v.reset(Op386LEAL1)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAL1 [off1] {sym1} x (LEAL1 [off2] {sym2} y y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAL2 [off1+off2] {mergeSym(sym1, sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386LEAL1 {
+ continue
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ y := v_1.Args[1]
+ if y != v_1.Args[0] || !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ continue
+ }
+ v.reset(Op386LEAL2)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAL1 [off1] {sym1} x (LEAL1 [off2] {sym2} x y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAL2 [off1+off2] {mergeSym(sym1, sym2)} y x)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386LEAL1 {
+ continue
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ continue
+ }
+ v.reset(Op386LEAL2)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(y, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (LEAL1 [0] {nil} x y)
+ // result: (ADDL x y)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 || auxToSym(v.Aux) != nil {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(Op386ADDL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386LEAL2(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAL2 [c] {s} (ADDLconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAL2 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ break
+ }
+ v.reset(Op386LEAL2)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL2 [c] {s} x (ADDLconst [d] y))
+ // cond: is32Bit(int64(c)+2*int64(d)) && y.Op != OpSB
+ // result: (LEAL2 [c+2*d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(is32Bit(int64(c)+2*int64(d)) && y.Op != OpSB) {
+ break
+ }
+ v.reset(Op386LEAL2)
+ v.AuxInt = int32ToAuxInt(c + 2*d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL2 [c] {s} x (SHLLconst [1] y))
+ // result: (LEAL4 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != Op386SHLLconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(Op386LEAL4)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL2 [c] {s} x (SHLLconst [2] y))
+ // result: (LEAL8 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != Op386SHLLconst || auxIntToInt32(v_1.AuxInt) != 2 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(Op386LEAL8)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL2 [off1] {sym1} (LEAL [off2] {sym2} x) y)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB
+ // result: (LEAL2 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB) {
+ break
+ }
+ v.reset(Op386LEAL2)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL2 [off1] {sym} x (LEAL1 [off2] {nil} y y))
+ // cond: is32Bit(int64(off1)+2*int64(off2))
+ // result: (LEAL4 [off1+2*off2] {sym} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != Op386LEAL1 {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ if auxToSym(v_1.Aux) != nil {
+ break
+ }
+ y := v_1.Args[1]
+ if y != v_1.Args[0] || !(is32Bit(int64(off1) + 2*int64(off2))) {
+ break
+ }
+ v.reset(Op386LEAL4)
+ v.AuxInt = int32ToAuxInt(off1 + 2*off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386LEAL4(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAL4 [c] {s} (ADDLconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAL4 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ break
+ }
+ v.reset(Op386LEAL4)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL4 [c] {s} x (ADDLconst [d] y))
+ // cond: is32Bit(int64(c)+4*int64(d)) && y.Op != OpSB
+ // result: (LEAL4 [c+4*d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(is32Bit(int64(c)+4*int64(d)) && y.Op != OpSB) {
+ break
+ }
+ v.reset(Op386LEAL4)
+ v.AuxInt = int32ToAuxInt(c + 4*d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL4 [c] {s} x (SHLLconst [1] y))
+ // result: (LEAL8 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != Op386SHLLconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(Op386LEAL8)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL4 [off1] {sym1} (LEAL [off2] {sym2} x) y)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB
+ // result: (LEAL4 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB) {
+ break
+ }
+ v.reset(Op386LEAL4)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL4 [off1] {sym} x (LEAL1 [off2] {nil} y y))
+ // cond: is32Bit(int64(off1)+4*int64(off2))
+ // result: (LEAL8 [off1+4*off2] {sym} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != Op386LEAL1 {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ if auxToSym(v_1.Aux) != nil {
+ break
+ }
+ y := v_1.Args[1]
+ if y != v_1.Args[0] || !(is32Bit(int64(off1) + 4*int64(off2))) {
+ break
+ }
+ v.reset(Op386LEAL8)
+ v.AuxInt = int32ToAuxInt(off1 + 4*off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386LEAL8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAL8 [c] {s} (ADDLconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAL8 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ break
+ }
+ v.reset(Op386LEAL8)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL8 [c] {s} x (ADDLconst [d] y))
+ // cond: is32Bit(int64(c)+8*int64(d)) && y.Op != OpSB
+ // result: (LEAL8 [c+8*d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(is32Bit(int64(c)+8*int64(d)) && y.Op != OpSB) {
+ break
+ }
+ v.reset(Op386LEAL8)
+ v.AuxInt = int32ToAuxInt(c + 8*d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL8 [off1] {sym1} (LEAL [off2] {sym2} x) y)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB
+ // result: (LEAL8 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB) {
+ break
+ }
+ v.reset(Op386LEAL8)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVBLSX(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVBLSX x:(MOVBload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBLSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != Op386MOVBload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, Op386MOVBLSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBLSX (ANDLconst [c] x))
+ // cond: c & 0x80 == 0
+ // result: (ANDLconst [c & 0x7f] x)
+ for {
+ if v_0.Op != Op386ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c&0x80 == 0) {
+ break
+ }
+ v.reset(Op386ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & 0x7f)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVBLSXload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVBLSXload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVBLSX x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVBstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(Op386MOVBLSX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBLSXload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBLSXload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVBLSXload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVBLZX(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVBLZX x:(MOVBload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != Op386MOVBload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, Op386MOVBload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBLZX (ANDLconst [c] x))
+ // result: (ANDLconst [c & 0xff] x)
+ for {
+ if v_0.Op != Op386ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(Op386ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & 0xff)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVBload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVBLZX x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVBstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(Op386MOVBLZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBload [off1] {sym} (ADDLconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVBload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVLconst [int32(read8(sym, int64(off)))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(int32(read8(sym, int64(off))))
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVBstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVBstore [off] {sym} ptr (MOVBLSX x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVBLSX {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(Op386MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBLZX x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVBLZX {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(Op386MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym} (ADDLconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVLconst [c]) mem)
+ // cond: validOff(int64(off))
+ // result: (MOVBstoreconst [makeValAndOff32(c,off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ if !(validOff(int64(off))) {
+ break
+ }
+ v.reset(Op386MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SHRWconst [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-1] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != Op386SHRWconst || auxIntToInt16(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != Op386MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SHRLconst [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-1] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != Op386SHRLconst || auxIntToInt32(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != Op386MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w x:(MOVBstore {s} [i+1] p (SHRWconst [8] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x := v_2
+ if x.Op != Op386MOVBstore || auxIntToInt32(x.AuxInt) != i+1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != Op386SHRWconst || auxIntToInt16(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w x:(MOVBstore {s} [i+1] p (SHRLconst [8] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x := v_2
+ if x.Op != Op386MOVBstore || auxIntToInt32(x.AuxInt) != i+1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != Op386SHRLconst || auxIntToInt32(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SHRLconst [j-8] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-1] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != Op386SHRLconst {
+ break
+ }
+ j := auxIntToInt32(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != Op386MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != Op386SHRLconst || auxIntToInt32(w0.AuxInt) != j-8 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p1 (SHRWconst [8] w) x:(MOVBstore [i] {s} p0 w mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != Op386SHRWconst || auxIntToInt16(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != Op386MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p1 (SHRLconst [8] w) x:(MOVBstore [i] {s} p0 w mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != Op386SHRLconst || auxIntToInt32(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != Op386MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p0 w x:(MOVBstore {s} [i] p1 (SHRWconst [8] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p0 := v_0
+ w := v_1
+ x := v_2
+ if x.Op != Op386MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p1 := x.Args[0]
+ x_1 := x.Args[1]
+ if x_1.Op != Op386SHRWconst || auxIntToInt16(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p0 w x:(MOVBstore {s} [i] p1 (SHRLconst [8] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p0 := v_0
+ w := v_1
+ x := v_2
+ if x.Op != Op386MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p1 := x.Args[0]
+ x_1 := x.Args[1]
+ if x_1.Op != Op386SHRLconst || auxIntToInt32(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p1 (SHRLconst [j] w) x:(MOVBstore [i] {s} p0 w0:(SHRLconst [j-8] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != Op386SHRLconst {
+ break
+ }
+ j := auxIntToInt32(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != Op386MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != Op386SHRLconst || auxIntToInt32(w0.AuxInt) != j-8 || w != w0.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVBstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVBstoreconst [sc] {s} (ADDLconst [off] ptr) mem)
+ // cond: sc.canAdd32(off)
+ // result: (MOVBstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sc.canAdd32(off)) {
+ break
+ }
+ v.reset(Op386MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && sc.canAdd32(off) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem))
+ // cond: x.Uses == 1 && a.Off() + 1 == c.Off() && clobber(x)
+ // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != Op386MOVBstoreconst {
+ break
+ }
+ a := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(x.Uses == 1 && a.Off()+1 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), a.Off32()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [a] {s} p x:(MOVBstoreconst [c] {s} p mem))
+ // cond: x.Uses == 1 && a.Off() + 1 == c.Off() && clobber(x)
+ // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p mem)
+ for {
+ a := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != Op386MOVBstoreconst {
+ break
+ }
+ c := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(x.Uses == 1 && a.Off()+1 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), a.Off32()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [c] {s} p1 x:(MOVBstoreconst [a] {s} p0 mem))
+ // cond: x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p0 mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ x := v_1
+ if x.Op != Op386MOVBstoreconst {
+ break
+ }
+ a := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ p0 := x.Args[0]
+ if !(x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), a.Off32()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p0, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [a] {s} p0 x:(MOVBstoreconst [c] {s} p1 mem))
+ // cond: x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p0 mem)
+ for {
+ a := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p0 := v_0
+ x := v_1
+ if x.Op != Op386MOVBstoreconst {
+ break
+ }
+ c := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ p1 := x.Args[0]
+ if !(x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), a.Off32()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVLload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVLload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVLstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVLload [off1] {sym} (ADDLconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVLload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MOVLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVLload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVLload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVLconst [int32(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(int32(read32(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVLstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVLstore [off1] {sym} (ADDLconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVLstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MOVLstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr (MOVLconst [c]) mem)
+ // cond: validOff(int64(off))
+ // result: (MOVLstoreconst [makeValAndOff32(c,off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ if !(validOff(int64(off))) {
+ break
+ }
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVLstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVLstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ADDLload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (ADDLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386ADDLload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(Op386ADDLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ANDLload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (ANDLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386ANDLload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(Op386ANDLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ORLload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (ORLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386ORLload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(Op386ORLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(XORLload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (XORLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386XORLload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(Op386XORLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ADDL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (ADDLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386ADDL {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != Op386MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(Op386ADDLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(SUBL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (SUBLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386SUBL {
+ break
+ }
+ x := y.Args[1]
+ l := y.Args[0]
+ if l.Op != Op386MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ break
+ }
+ v.reset(Op386SUBLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ANDL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (ANDLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386ANDL {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != Op386MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(Op386ANDLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ORL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (ORLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386ORL {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != Op386MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(Op386ORLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(XORL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (XORLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386XORL {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != Op386MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(Op386XORLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ADDLconst [c] l:(MOVLload [off] {sym} ptr mem)) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(int64(c),int64(off))
+ // result: (ADDLconstmodify [makeValAndOff32(c,off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386ADDLconst {
+ break
+ }
+ c := auxIntToInt32(y.AuxInt)
+ l := y.Args[0]
+ if l.Op != Op386MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l) && validValAndOff(int64(c), int64(off))) {
+ break
+ }
+ v.reset(Op386ADDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ANDLconst [c] l:(MOVLload [off] {sym} ptr mem)) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(int64(c),int64(off))
+ // result: (ANDLconstmodify [makeValAndOff32(c,off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386ANDLconst {
+ break
+ }
+ c := auxIntToInt32(y.AuxInt)
+ l := y.Args[0]
+ if l.Op != Op386MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l) && validValAndOff(int64(c), int64(off))) {
+ break
+ }
+ v.reset(Op386ANDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ORLconst [c] l:(MOVLload [off] {sym} ptr mem)) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(int64(c),int64(off))
+ // result: (ORLconstmodify [makeValAndOff32(c,off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386ORLconst {
+ break
+ }
+ c := auxIntToInt32(y.AuxInt)
+ l := y.Args[0]
+ if l.Op != Op386MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l) && validValAndOff(int64(c), int64(off))) {
+ break
+ }
+ v.reset(Op386ORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(XORLconst [c] l:(MOVLload [off] {sym} ptr mem)) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(int64(c),int64(off))
+ // result: (XORLconstmodify [makeValAndOff32(c,off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != Op386XORLconst {
+ break
+ }
+ c := auxIntToInt32(y.AuxInt)
+ l := y.Args[0]
+ if l.Op != Op386MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l) && validValAndOff(int64(c), int64(off))) {
+ break
+ }
+ v.reset(Op386XORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVLstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVLstoreconst [sc] {s} (ADDLconst [off] ptr) mem)
+ // cond: sc.canAdd32(off)
+ // result: (MOVLstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sc.canAdd32(off)) {
+ break
+ }
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVLstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && sc.canAdd32(off) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVSDconst(v *Value) bool {
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (MOVSDconst [c])
+ // cond: config.ctxt.Flag_shared
+ // result: (MOVSDconst2 (MOVSDconst1 [c]))
+ for {
+ c := auxIntToFloat64(v.AuxInt)
+ if !(config.ctxt.Flag_shared) {
+ break
+ }
+ v.reset(Op386MOVSDconst2)
+ v0 := b.NewValue0(v.Pos, Op386MOVSDconst1, typ.UInt32)
+ v0.AuxInt = float64ToAuxInt(c)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVSDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVSDload [off1] {sym} (ADDLconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVSDload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MOVSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVSDload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVSDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVSDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVSDstore [off1] {sym} (ADDLconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVSDstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MOVSDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVSDstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVSDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVSDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVSSconst(v *Value) bool {
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (MOVSSconst [c])
+ // cond: config.ctxt.Flag_shared
+ // result: (MOVSSconst2 (MOVSSconst1 [c]))
+ for {
+ c := auxIntToFloat32(v.AuxInt)
+ if !(config.ctxt.Flag_shared) {
+ break
+ }
+ v.reset(Op386MOVSSconst2)
+ v0 := b.NewValue0(v.Pos, Op386MOVSSconst1, typ.UInt32)
+ v0.AuxInt = float32ToAuxInt(c)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVSSload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVSSload [off1] {sym} (ADDLconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVSSload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MOVSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVSSload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVSSload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVSSstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVSSstore [off1] {sym} (ADDLconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVSSstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MOVSSstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVSSstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVSSstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVSSstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVWLSX(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVWLSX x:(MOVWload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWLSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != Op386MOVWload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, Op386MOVWLSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWLSX (ANDLconst [c] x))
+ // cond: c & 0x8000 == 0
+ // result: (ANDLconst [c & 0x7fff] x)
+ for {
+ if v_0.Op != Op386ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c&0x8000 == 0) {
+ break
+ }
+ v.reset(Op386ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & 0x7fff)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVWLSXload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVWLSXload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVWLSX x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVWstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(Op386MOVWLSX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWLSXload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWLSXload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVWLSXload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVWLZX(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVWLZX x:(MOVWload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != Op386MOVWload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, Op386MOVWload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWLZX (ANDLconst [c] x))
+ // result: (ANDLconst [c & 0xffff] x)
+ for {
+ if v_0.Op != Op386ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(Op386ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & 0xffff)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVWload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVWLZX x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVWstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(Op386MOVWLZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWload [off1] {sym} (ADDLconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVWload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVLconst [int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVWstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVWstore [off] {sym} ptr (MOVWLSX x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVWLSX {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWLZX x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVWLZX {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym} (ADDLconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVLconst [c]) mem)
+ // cond: validOff(int64(off))
+ // result: (MOVWstoreconst [makeValAndOff32(c,off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ if !(validOff(int64(off))) {
+ break
+ }
+ v.reset(Op386MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVLstore [i-2] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != Op386SHRLconst || auxIntToInt32(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != Op386MOVWstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVLstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p w0:(SHRLconst [j-16] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVLstore [i-2] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != Op386SHRLconst {
+ break
+ }
+ j := auxIntToInt32(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != Op386MOVWstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != Op386SHRLconst || auxIntToInt32(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVLstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p1 (SHRLconst [16] w) x:(MOVWstore [i] {s} p0 w mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)
+ // result: (MOVLstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != Op386SHRLconst || auxIntToInt32(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != Op386MOVWstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVLstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p1 (SHRLconst [j] w) x:(MOVWstore [i] {s} p0 w0:(SHRLconst [j-16] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)
+ // result: (MOVLstore [i] {s} p0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != Op386SHRLconst {
+ break
+ }
+ j := auxIntToInt32(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != Op386MOVWstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != Op386SHRLconst || auxIntToInt32(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVLstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MOVWstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVWstoreconst [sc] {s} (ADDLconst [off] ptr) mem)
+ // cond: sc.canAdd32(off)
+ // result: (MOVWstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sc.canAdd32(off)) {
+ break
+ }
+ v.reset(Op386MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && sc.canAdd32(off) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem))
+ // cond: x.Uses == 1 && a.Off() + 2 == c.Off() && clobber(x)
+ // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != Op386MOVWstoreconst {
+ break
+ }
+ a := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(x.Uses == 1 && a.Off()+2 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), a.Off32()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [a] {s} p x:(MOVWstoreconst [c] {s} p mem))
+ // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x)
+ // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p mem)
+ for {
+ a := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != Op386MOVWstoreconst {
+ break
+ }
+ c := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), a.Off32()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [c] {s} p1 x:(MOVWstoreconst [a] {s} p0 mem))
+ // cond: x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 2) && clobber(x)
+ // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p0 mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ x := v_1
+ if x.Op != Op386MOVWstoreconst {
+ break
+ }
+ a := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ p0 := x.Args[0]
+ if !(x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 2) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), a.Off32()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p0, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [a] {s} p0 x:(MOVWstoreconst [c] {s} p1 mem))
+ // cond: x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 2) && clobber(x)
+ // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p0 mem)
+ for {
+ a := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p0 := v_0
+ x := v_1
+ if x.Op != Op386MOVWstoreconst {
+ break
+ }
+ c := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ p1 := x.Args[0]
+ if !(x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 2) && clobber(x)) {
+ break
+ }
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), a.Off32()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MULL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULL x (MOVLconst [c]))
+ // result: (MULLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386MULLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MULL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (MULLload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVLload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(Op386MULLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValue386_Op386MULLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MULLconst [c] (MULLconst [d] x))
+ // result: (MULLconst [c * d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MULLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(Op386MULLconst)
+ v.AuxInt = int32ToAuxInt(c * d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MULLconst [-9] x)
+ // result: (NEGL (LEAL8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != -9 {
+ break
+ }
+ x := v_0
+ v.reset(Op386NEGL)
+ v0 := b.NewValue0(v.Pos, Op386LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [-5] x)
+ // result: (NEGL (LEAL4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != -5 {
+ break
+ }
+ x := v_0
+ v.reset(Op386NEGL)
+ v0 := b.NewValue0(v.Pos, Op386LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [-3] x)
+ // result: (NEGL (LEAL2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != -3 {
+ break
+ }
+ x := v_0
+ v.reset(Op386NEGL)
+ v0 := b.NewValue0(v.Pos, Op386LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [-1] x)
+ // result: (NEGL x)
+ for {
+ if auxIntToInt32(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.reset(Op386NEGL)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MULLconst [0] _)
+ // result: (MOVLconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (MULLconst [1] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (MULLconst [3] x)
+ // result: (LEAL2 x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 3 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL2)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (MULLconst [5] x)
+ // result: (LEAL4 x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 5 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL4)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (MULLconst [7] x)
+ // result: (LEAL2 x (LEAL2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 7 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL2)
+ v0 := b.NewValue0(v.Pos, Op386LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [9] x)
+ // result: (LEAL8 x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 9 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL8)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (MULLconst [11] x)
+ // result: (LEAL2 x (LEAL4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 11 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL2)
+ v0 := b.NewValue0(v.Pos, Op386LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [13] x)
+ // result: (LEAL4 x (LEAL2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 13 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL4)
+ v0 := b.NewValue0(v.Pos, Op386LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [19] x)
+ // result: (LEAL2 x (LEAL8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 19 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL2)
+ v0 := b.NewValue0(v.Pos, Op386LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [21] x)
+ // result: (LEAL4 x (LEAL4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 21 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL4)
+ v0 := b.NewValue0(v.Pos, Op386LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [25] x)
+ // result: (LEAL8 x (LEAL2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 25 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL8)
+ v0 := b.NewValue0(v.Pos, Op386LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [27] x)
+ // result: (LEAL8 (LEAL2 <v.Type> x x) (LEAL2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 27 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL8)
+ v0 := b.NewValue0(v.Pos, Op386LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, v0)
+ return true
+ }
+ // match: (MULLconst [37] x)
+ // result: (LEAL4 x (LEAL8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 37 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL4)
+ v0 := b.NewValue0(v.Pos, Op386LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [41] x)
+ // result: (LEAL8 x (LEAL4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 41 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL8)
+ v0 := b.NewValue0(v.Pos, Op386LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [45] x)
+ // result: (LEAL8 (LEAL4 <v.Type> x x) (LEAL4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 45 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL8)
+ v0 := b.NewValue0(v.Pos, Op386LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, v0)
+ return true
+ }
+ // match: (MULLconst [73] x)
+ // result: (LEAL8 x (LEAL8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 73 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL8)
+ v0 := b.NewValue0(v.Pos, Op386LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [81] x)
+ // result: (LEAL8 (LEAL8 <v.Type> x x) (LEAL8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 81 {
+ break
+ }
+ x := v_0
+ v.reset(Op386LEAL8)
+ v0 := b.NewValue0(v.Pos, Op386LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, v0)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: isPowerOfTwo32(c+1) && c >= 15
+ // result: (SUBL (SHLLconst <v.Type> [int32(log32(c+1))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c+1) && c >= 15) {
+ break
+ }
+ v.reset(Op386SUBL)
+ v0 := b.NewValue0(v.Pos, Op386SHLLconst, v.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c + 1)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: isPowerOfTwo32(c-1) && c >= 17
+ // result: (LEAL1 (SHLLconst <v.Type> [int32(log32(c-1))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-1) && c >= 17) {
+ break
+ }
+ v.reset(Op386LEAL1)
+ v0 := b.NewValue0(v.Pos, Op386SHLLconst, v.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c - 1)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: isPowerOfTwo32(c-2) && c >= 34
+ // result: (LEAL2 (SHLLconst <v.Type> [int32(log32(c-2))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-2) && c >= 34) {
+ break
+ }
+ v.reset(Op386LEAL2)
+ v0 := b.NewValue0(v.Pos, Op386SHLLconst, v.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c - 2)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: isPowerOfTwo32(c-4) && c >= 68
+ // result: (LEAL4 (SHLLconst <v.Type> [int32(log32(c-4))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-4) && c >= 68) {
+ break
+ }
+ v.reset(Op386LEAL4)
+ v0 := b.NewValue0(v.Pos, Op386SHLLconst, v.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c - 4)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: isPowerOfTwo32(c-8) && c >= 136
+ // result: (LEAL8 (SHLLconst <v.Type> [int32(log32(c-8))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-8) && c >= 136) {
+ break
+ }
+ v.reset(Op386LEAL8)
+ v0 := b.NewValue0(v.Pos, Op386SHLLconst, v.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c - 8)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: c%3 == 0 && isPowerOfTwo32(c/3)
+ // result: (SHLLconst [int32(log32(c/3))] (LEAL2 <v.Type> x x))
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c%3 == 0 && isPowerOfTwo32(c/3)) {
+ break
+ }
+ v.reset(Op386SHLLconst)
+ v.AuxInt = int32ToAuxInt(int32(log32(c / 3)))
+ v0 := b.NewValue0(v.Pos, Op386LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: c%5 == 0 && isPowerOfTwo32(c/5)
+ // result: (SHLLconst [int32(log32(c/5))] (LEAL4 <v.Type> x x))
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c%5 == 0 && isPowerOfTwo32(c/5)) {
+ break
+ }
+ v.reset(Op386SHLLconst)
+ v.AuxInt = int32ToAuxInt(int32(log32(c / 5)))
+ v0 := b.NewValue0(v.Pos, Op386LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: c%9 == 0 && isPowerOfTwo32(c/9)
+ // result: (SHLLconst [int32(log32(c/9))] (LEAL8 <v.Type> x x))
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c%9 == 0 && isPowerOfTwo32(c/9)) {
+ break
+ }
+ v.reset(Op386SHLLconst)
+ v.AuxInt = int32ToAuxInt(int32(log32(c / 9)))
+ v0 := b.NewValue0(v.Pos, Op386LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [c*d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(c * d)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MULLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MULLload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MULLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MULLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (MULLload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MULLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MULLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MULSD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULSD x l:(MOVSDload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (MULSDload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVSDload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(Op386MULSDload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValue386_Op386MULSDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MULSDload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MULSDload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MULSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (MULSDload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MULSDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MULSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386MULSS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULSS x l:(MOVSSload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (MULSSload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVSSload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(Op386MULSSload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValue386_Op386MULSSload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MULSSload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MULSSload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386MULSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (MULSSload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MULSSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386MULSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386NEGL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEGL (MOVLconst [c]))
+ // result: (MOVLconst [-c])
+ for {
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386NOTL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NOTL (MOVLconst [c]))
+ // result: (MOVLconst [^c])
+ for {
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(^c)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ORL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ORL x (MOVLconst [c]))
+ // result: (ORLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386ORLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: ( ORL (SHLLconst [c] x) (SHRLconst [d] x))
+ // cond: d == 32-c
+ // result: (ROLLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386SHLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != Op386SHRLconst {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 32-c) {
+ continue
+ }
+ v.reset(Op386ROLLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: ( ORL <t> (SHLLconst x [c]) (SHRWconst x [d]))
+ // cond: c < 16 && d == int16(16-c) && t.Size() == 2
+ // result: (ROLWconst x [int16(c)])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386SHLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != Op386SHRWconst {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ if x != v_1.Args[0] || !(c < 16 && d == int16(16-c) && t.Size() == 2) {
+ continue
+ }
+ v.reset(Op386ROLWconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: ( ORL <t> (SHLLconst x [c]) (SHRBconst x [d]))
+ // cond: c < 8 && d == int8(8-c) && t.Size() == 1
+ // result: (ROLBconst x [int8(c)])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386SHLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != Op386SHRBconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(c < 8 && d == int8(8-c) && t.Size() == 1) {
+ continue
+ }
+ v.reset(Op386ROLBconst)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ORLload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVLload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(Op386ORLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORL x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORL x0:(MOVBload [i0] {s} p mem) s0:(SHLLconst [8] x1:(MOVBload [i1] {s} p mem)))
+ // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, s0)
+ // result: @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != Op386MOVBload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ s0 := v_1
+ if s0.Op != Op386SHLLconst || auxIntToInt32(s0.AuxInt) != 8 {
+ continue
+ }
+ x1 := s0.Args[0]
+ if x1.Op != Op386MOVBload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, Op386MOVWload, typ.UInt16)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORL x0:(MOVBload [i] {s} p0 mem) s0:(SHLLconst [8] x1:(MOVBload [i] {s} p1 mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, s0)
+ // result: @mergePoint(b,x0,x1) (MOVWload [i] {s} p0 mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != Op386MOVBload {
+ continue
+ }
+ i := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p0 := x0.Args[0]
+ s0 := v_1
+ if s0.Op != Op386SHLLconst || auxIntToInt32(s0.AuxInt) != 8 {
+ continue
+ }
+ x1 := s0.Args[0]
+ if x1.Op != Op386MOVBload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if mem != x1.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, Op386MOVWload, typ.UInt16)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p0, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORL o0:(ORL x0:(MOVWload [i0] {s} p mem) s0:(SHLLconst [16] x1:(MOVBload [i2] {s} p mem))) s1:(SHLLconst [24] x2:(MOVBload [i3] {s} p mem)))
+ // cond: i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 && mergePoint(b,x0,x1,x2) != nil && clobber(x0, x1, x2, s0, s1, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVLload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != Op386ORL {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ x0 := o0_0
+ if x0.Op != Op386MOVWload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ s0 := o0_1
+ if s0.Op != Op386SHLLconst || auxIntToInt32(s0.AuxInt) != 16 {
+ continue
+ }
+ x1 := s0.Args[0]
+ if x1.Op != Op386MOVBload {
+ continue
+ }
+ i2 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ s1 := v_1
+ if s1.Op != Op386SHLLconst || auxIntToInt32(s1.AuxInt) != 24 {
+ continue
+ }
+ x2 := s1.Args[0]
+ if x2.Op != Op386MOVBload {
+ continue
+ }
+ i3 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] || !(i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x2.Pos, Op386MOVLload, typ.UInt32)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL o0:(ORL x0:(MOVWload [i] {s} p0 mem) s0:(SHLLconst [16] x1:(MOVBload [i] {s} p1 mem))) s1:(SHLLconst [24] x2:(MOVBload [i] {s} p2 mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 && sequentialAddresses(p0, p1, 2) && sequentialAddresses(p1, p2, 1) && mergePoint(b,x0,x1,x2) != nil && clobber(x0, x1, x2, s0, s1, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVLload [i] {s} p0 mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != Op386ORL {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ x0 := o0_0
+ if x0.Op != Op386MOVWload {
+ continue
+ }
+ i := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p0 := x0.Args[0]
+ s0 := o0_1
+ if s0.Op != Op386SHLLconst || auxIntToInt32(s0.AuxInt) != 16 {
+ continue
+ }
+ x1 := s0.Args[0]
+ if x1.Op != Op386MOVBload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if mem != x1.Args[1] {
+ continue
+ }
+ s1 := v_1
+ if s1.Op != Op386SHLLconst || auxIntToInt32(s1.AuxInt) != 24 {
+ continue
+ }
+ x2 := s1.Args[0]
+ if x2.Op != Op386MOVBload || auxIntToInt32(x2.AuxInt) != i || auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ p2 := x2.Args[0]
+ if mem != x2.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 && sequentialAddresses(p0, p1, 2) && sequentialAddresses(p1, p2, 1) && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x2.Pos, Op386MOVLload, typ.UInt32)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p0, mem)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValue386_Op386ORLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ORLconst [c] x)
+ // cond: c==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORLconst [c] _)
+ // cond: c==-1
+ // result: (MOVLconst [-1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if !(c == -1) {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ // match: (ORLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [c|d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(c | d)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ORLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ORLconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem)
+ // cond: valoff1.canAdd32(off2)
+ // result: (ORLconstmodify [valoff1.addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(valoff1.canAdd32(off2)) {
+ break
+ }
+ v.reset(Op386ORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(valoff1.addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (ORLconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: valoff1.canAdd32(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ORLconstmodify [valoff1.addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(valoff1.canAdd32(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(valoff1.addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ORLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ORLload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ORLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386ORLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ORLload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ORLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ORLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ORLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (ORLmodify [off1] {sym} (ADDLconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ORLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386ORLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (ORLmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (ORLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386ORLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ROLBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ROLBconst [c] (ROLBconst [d] x))
+ // result: (ROLBconst [(c+d)& 7] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != Op386ROLBconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(Op386ROLBconst)
+ v.AuxInt = int8ToAuxInt((c + d) & 7)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLBconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ROLLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ROLLconst [c] (ROLLconst [d] x))
+ // result: (ROLLconst [(c+d)&31] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386ROLLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(Op386ROLLconst)
+ v.AuxInt = int32ToAuxInt((c + d) & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLLconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386ROLWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ROLWconst [c] (ROLWconst [d] x))
+ // result: (ROLWconst [(c+d)&15] x)
+ for {
+ c := auxIntToInt16(v.AuxInt)
+ if v_0.Op != Op386ROLWconst {
+ break
+ }
+ d := auxIntToInt16(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(Op386ROLWconst)
+ v.AuxInt = int16ToAuxInt((c + d) & 15)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLWconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt16(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SARB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SARB x (MOVLconst [c]))
+ // result: (SARBconst [int8(min(int64(c&31),7))] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386SARBconst)
+ v.AuxInt = int8ToAuxInt(int8(min(int64(c&31), 7)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SARBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SARBconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SARBconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [d>>uint64(c)])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(d >> uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SARL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SARL x (MOVLconst [c]))
+ // result: (SARLconst [c&31] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386SARLconst)
+ v.AuxInt = int32ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SARL x (ANDLconst [31] y))
+ // result: (SARL x y)
+ for {
+ x := v_0
+ if v_1.Op != Op386ANDLconst || auxIntToInt32(v_1.AuxInt) != 31 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(Op386SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SARLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SARLconst x [0])
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SARLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [d>>uint64(c)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(d >> uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SARW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SARW x (MOVLconst [c]))
+ // result: (SARWconst [int16(min(int64(c&31),15))] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386SARWconst)
+ v.AuxInt = int16ToAuxInt(int16(min(int64(c&31), 15)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SARWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SARWconst x [0])
+ // result: x
+ for {
+ if auxIntToInt16(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SARWconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [d>>uint64(c)])
+ for {
+ c := auxIntToInt16(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(d >> uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SBBL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SBBL x (MOVLconst [c]) f)
+ // result: (SBBLconst [c] x f)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ f := v_2
+ v.reset(Op386SBBLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, f)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SBBLcarrymask(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SBBLcarrymask (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SBBLcarrymask (FlagLT_ULT))
+ // result: (MOVLconst [-1])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ // match: (SBBLcarrymask (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SBBLcarrymask (FlagGT_ULT))
+ // result: (MOVLconst [-1])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ // match: (SBBLcarrymask (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SETA(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETA (InvertFlags x))
+ // result: (SETB x)
+ for {
+ if v_0.Op != Op386InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(Op386SETB)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETA (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETA (FlagLT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETA (FlagLT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETA (FlagGT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETA (FlagGT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SETAE(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETAE (InvertFlags x))
+ // result: (SETBE x)
+ for {
+ if v_0.Op != Op386InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(Op386SETBE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETAE (FlagEQ))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETAE (FlagLT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETAE (FlagLT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETAE (FlagGT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETAE (FlagGT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SETB(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETB (InvertFlags x))
+ // result: (SETA x)
+ for {
+ if v_0.Op != Op386InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(Op386SETA)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETB (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETB (FlagLT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETB (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETB (FlagGT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETB (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SETBE(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETBE (InvertFlags x))
+ // result: (SETAE x)
+ for {
+ if v_0.Op != Op386InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(Op386SETAE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETBE (FlagEQ))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETBE (FlagLT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETBE (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETBE (FlagGT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETBE (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SETEQ(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETEQ (InvertFlags x))
+ // result: (SETEQ x)
+ for {
+ if v_0.Op != Op386InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(Op386SETEQ)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETEQ (FlagEQ))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETEQ (FlagLT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETEQ (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETEQ (FlagGT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETEQ (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SETG(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETG (InvertFlags x))
+ // result: (SETL x)
+ for {
+ if v_0.Op != Op386InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(Op386SETL)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETG (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETG (FlagLT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETG (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETG (FlagGT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETG (FlagGT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SETGE(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETGE (InvertFlags x))
+ // result: (SETLE x)
+ for {
+ if v_0.Op != Op386InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(Op386SETLE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETGE (FlagEQ))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETGE (FlagLT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETGE (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETGE (FlagGT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETGE (FlagGT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SETL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETL (InvertFlags x))
+ // result: (SETG x)
+ for {
+ if v_0.Op != Op386InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(Op386SETG)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETL (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETL (FlagLT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETL (FlagLT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETL (FlagGT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETL (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SETLE(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETLE (InvertFlags x))
+ // result: (SETGE x)
+ for {
+ if v_0.Op != Op386InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(Op386SETGE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETLE (FlagEQ))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETLE (FlagLT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETLE (FlagLT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETLE (FlagGT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETLE (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SETNE(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETNE (InvertFlags x))
+ // result: (SETNE x)
+ for {
+ if v_0.Op != Op386InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(Op386SETNE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETNE (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != Op386FlagEQ {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETNE (FlagLT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagLT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETNE (FlagLT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagLT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETNE (FlagGT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagGT_ULT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETNE (FlagGT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != Op386FlagGT_UGT {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SHLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SHLL x (MOVLconst [c]))
+ // result: (SHLLconst [c&31] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386SHLLconst)
+ v.AuxInt = int32ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHLL x (ANDLconst [31] y))
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ if v_1.Op != Op386ANDLconst || auxIntToInt32(v_1.AuxInt) != 31 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(Op386SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SHLLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SHLLconst x [0])
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SHRB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SHRB x (MOVLconst [c]))
+ // cond: c&31 < 8
+ // result: (SHRBconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c&31 < 8) {
+ break
+ }
+ v.reset(Op386SHRBconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRB _ (MOVLconst [c]))
+ // cond: c&31 >= 8
+ // result: (MOVLconst [0])
+ for {
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c&31 >= 8) {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SHRBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SHRBconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SHRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SHRL x (MOVLconst [c]))
+ // result: (SHRLconst [c&31] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386SHRLconst)
+ v.AuxInt = int32ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRL x (ANDLconst [31] y))
+ // result: (SHRL x y)
+ for {
+ x := v_0
+ if v_1.Op != Op386ANDLconst || auxIntToInt32(v_1.AuxInt) != 31 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(Op386SHRL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SHRLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SHRLconst x [0])
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SHRW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SHRW x (MOVLconst [c]))
+ // cond: c&31 < 16
+ // result: (SHRWconst [int16(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c&31 < 16) {
+ break
+ }
+ v.reset(Op386SHRWconst)
+ v.AuxInt = int16ToAuxInt(int16(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRW _ (MOVLconst [c]))
+ // cond: c&31 >= 16
+ // result: (MOVLconst [0])
+ for {
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c&31 >= 16) {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SHRWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SHRWconst x [0])
+ // result: x
+ for {
+ if auxIntToInt16(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SUBL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBL x (MOVLconst [c]))
+ // result: (SUBLconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386SUBLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBL (MOVLconst [c]) x)
+ // result: (NEGL (SUBLconst <v.Type> x [c]))
+ for {
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(Op386NEGL)
+ v0 := b.NewValue0(v.Pos, Op386SUBLconst, v.Type)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (SUBLload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVLload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386SUBLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (SUBL x x)
+ // result: (MOVLconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SUBLcarry(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBLcarry x (MOVLconst [c]))
+ // result: (SUBLconstcarry [c] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386SUBLconstcarry)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SUBLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SUBLconst [c] x)
+ // cond: c==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUBLconst [c] x)
+ // result: (ADDLconst [-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ v.reset(Op386ADDLconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValue386_Op386SUBLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (SUBLload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SUBLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386SUBLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBLload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (SUBLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386SUBLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SUBLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (SUBLmodify [off1] {sym} (ADDLconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SUBLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386SUBLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SUBLmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (SUBLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386SUBLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SUBSD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBSD x l:(MOVSDload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (SUBSDload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVSDload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386SUBSDload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SUBSDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (SUBSDload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SUBSDload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386SUBSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBSDload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (SUBSDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386SUBSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SUBSS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBSS x l:(MOVSSload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (SUBSSload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVSSload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386SUBSSload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386SUBSSload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (SUBSSload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SUBSSload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386SUBSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBSSload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (SUBSSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386SUBSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386XORL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XORL x (MOVLconst [c]))
+ // result: (XORLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386XORLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORL (SHLLconst [c] x) (SHRLconst [d] x))
+ // cond: d == 32-c
+ // result: (ROLLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386SHLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != Op386SHRLconst {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 32-c) {
+ continue
+ }
+ v.reset(Op386ROLLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORL <t> (SHLLconst x [c]) (SHRWconst x [d]))
+ // cond: c < 16 && d == int16(16-c) && t.Size() == 2
+ // result: (ROLWconst x [int16(c)])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386SHLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != Op386SHRWconst {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ if x != v_1.Args[0] || !(c < 16 && d == int16(16-c) && t.Size() == 2) {
+ continue
+ }
+ v.reset(Op386ROLWconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORL <t> (SHLLconst x [c]) (SHRBconst x [d]))
+ // cond: c < 8 && d == int8(8-c) && t.Size() == 1
+ // result: (ROLBconst x [int8(c)])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != Op386SHLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != Op386SHRBconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(c < 8 && d == int8(8-c) && t.Size() == 1) {
+ continue
+ }
+ v.reset(Op386ROLBconst)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (XORLload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != Op386MOVLload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(Op386XORLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (XORL x x)
+ // result: (MOVLconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386XORLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (XORLconst [c] (XORLconst [d] x))
+ // result: (XORLconst [c ^ d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386XORLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(Op386XORLconst)
+ v.AuxInt = int32ToAuxInt(c ^ d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [c] x)
+ // cond: c==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (XORLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [c^d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != Op386MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(c ^ d)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386XORLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (XORLconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem)
+ // cond: valoff1.canAdd32(off2)
+ // result: (XORLconstmodify [valoff1.addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(valoff1.canAdd32(off2)) {
+ break
+ }
+ v.reset(Op386XORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(valoff1.addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (XORLconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: valoff1.canAdd32(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (XORLconstmodify [valoff1.addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(valoff1.canAdd32(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386XORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(valoff1.addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386XORLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (XORLload [off1] {sym} val (ADDLconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (XORLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386XORLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (XORLload [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (XORLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386XORLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386XORLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (XORLmodify [off1] {sym} (ADDLconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (XORLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != Op386ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(Op386XORLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (XORLmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (XORLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != Op386LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(Op386XORLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Addr {sym} base)
+ // result: (LEAL {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(Op386LEAL)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValue386_OpConst16(v *Value) bool {
+ // match: (Const16 [c])
+ // result: (MOVLconst [int32(c)])
+ for {
+ c := auxIntToInt16(v.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ return true
+ }
+}
+func rewriteValue386_OpConst8(v *Value) bool {
+ // match: (Const8 [c])
+ // result: (MOVLconst [int32(c)])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ return true
+ }
+}
+func rewriteValue386_OpConstBool(v *Value) bool {
+ // match: (ConstBool [c])
+ // result: (MOVLconst [b2i32(c)])
+ for {
+ c := auxIntToBool(v.AuxInt)
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(b2i32(c))
+ return true
+ }
+}
+func rewriteValue386_OpConstNil(v *Value) bool {
+ // match: (ConstNil)
+ // result: (MOVLconst [0])
+ for {
+ v.reset(Op386MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+}
+func rewriteValue386_OpCtz16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz16 x)
+ // result: (BSFL (ORLconst <typ.UInt32> [0x10000] x))
+ for {
+ x := v_0
+ v.reset(Op386BSFL)
+ v0 := b.NewValue0(v.Pos, Op386ORLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0x10000)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 x y)
+ // result: (DIVW (SignExt8to16 x) (SignExt8to16 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386DIVW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to16, typ.Int16)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to16, typ.Int16)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValue386_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u x y)
+ // result: (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386DIVWU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to16, typ.UInt16)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to16, typ.UInt16)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValue386_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq16 x y)
+ // result: (SETEQ (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETEQ)
+ v0 := b.NewValue0(v.Pos, Op386CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32 x y)
+ // result: (SETEQ (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETEQ)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpEq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32F x y)
+ // result: (SETEQF (UCOMISS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETEQF)
+ v0 := b.NewValue0(v.Pos, Op386UCOMISS, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpEq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64F x y)
+ // result: (SETEQF (UCOMISD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETEQF)
+ v0 := b.NewValue0(v.Pos, Op386UCOMISD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq8 x y)
+ // result: (SETEQ (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETEQ)
+ v0 := b.NewValue0(v.Pos, Op386CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpEqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (EqB x y)
+ // result: (SETEQ (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETEQ)
+ v0 := b.NewValue0(v.Pos, Op386CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpEqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (EqPtr x y)
+ // result: (SETEQ (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETEQ)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpIsInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsInBounds idx len)
+ // result: (SETB (CMPL idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(Op386SETB)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsNonNil p)
+ // result: (SETNE (TESTL p p))
+ for {
+ p := v_0
+ v.reset(Op386SETNE)
+ v0 := b.NewValue0(v.Pos, Op386TESTL, types.TypeFlags)
+ v0.AddArg2(p, p)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpIsSliceInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsSliceInBounds idx len)
+ // result: (SETBE (CMPL idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(Op386SETBE)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq16 x y)
+ // result: (SETLE (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETLE)
+ v0 := b.NewValue0(v.Pos, Op386CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq16U x y)
+ // result: (SETBE (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETBE)
+ v0 := b.NewValue0(v.Pos, Op386CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32 x y)
+ // result: (SETLE (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETLE)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32F x y)
+ // result: (SETGEF (UCOMISS y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETGEF)
+ v0 := b.NewValue0(v.Pos, Op386UCOMISS, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32U x y)
+ // result: (SETBE (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETBE)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64F x y)
+ // result: (SETGEF (UCOMISD y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETGEF)
+ v0 := b.NewValue0(v.Pos, Op386UCOMISD, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq8 x y)
+ // result: (SETLE (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETLE)
+ v0 := b.NewValue0(v.Pos, Op386CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq8U x y)
+ // result: (SETBE (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETBE)
+ v0 := b.NewValue0(v.Pos, Op386CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less16 x y)
+ // result: (SETL (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETL)
+ v0 := b.NewValue0(v.Pos, Op386CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less16U x y)
+ // result: (SETB (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETB)
+ v0 := b.NewValue0(v.Pos, Op386CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32 x y)
+ // result: (SETL (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETL)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLess32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32F x y)
+ // result: (SETGF (UCOMISS y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETGF)
+ v0 := b.NewValue0(v.Pos, Op386UCOMISS, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32U x y)
+ // result: (SETB (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETB)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLess64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64F x y)
+ // result: (SETGF (UCOMISD y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETGF)
+ v0 := b.NewValue0(v.Pos, Op386UCOMISD, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less8 x y)
+ // result: (SETL (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETL)
+ v0 := b.NewValue0(v.Pos, Op386CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less8U x y)
+ // result: (SETB (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETB)
+ v0 := b.NewValue0(v.Pos, Op386CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Load <t> ptr mem)
+ // cond: (is32BitInt(t) || isPtr(t))
+ // result: (MOVLload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(Op386MOVLload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is16BitInt(t)
+ // result: (MOVWload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(Op386MOVWload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (t.IsBoolean() || is8BitInt(t))
+ // result: (MOVBload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsBoolean() || is8BitInt(t)) {
+ break
+ }
+ v.reset(Op386MOVBload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitFloat(t)
+ // result: (MOVSSload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(Op386MOVSSload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitFloat(t)
+ // result: (MOVSDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(Op386MOVSDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLocalAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LocalAddr {sym} base _)
+ // result: (LEAL {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(Op386LEAL)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValue386_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh16x16 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHLL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh16x32 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHLL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Lsh16x64 x (Const64 [c]))
+ // cond: uint64(c) < 16
+ // result: (SHLLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 16) {
+ break
+ }
+ v.reset(Op386SHLLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh16x64 _ (Const64 [c]))
+ // cond: uint64(c) >= 16
+ // result: (Const16 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh16x8 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHLL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh32x16 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHLL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh32x32 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHLL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Lsh32x64 x (Const64 [c]))
+ // cond: uint64(c) < 32
+ // result: (SHLLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 32) {
+ break
+ }
+ v.reset(Op386SHLLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh32x64 _ (Const64 [c]))
+ // cond: uint64(c) >= 32
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh32x8 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHLL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh8x16 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHLL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh8x32 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHLL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Lsh8x64 x (Const64 [c]))
+ // cond: uint64(c) < 8
+ // result: (SHLLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 8) {
+ break
+ }
+ v.reset(Op386SHLLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh8x64 _ (Const64 [c]))
+ // cond: uint64(c) >= 8
+ // result: (Const8 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh8x8 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHLL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8 x y)
+ // result: (MODW (SignExt8to16 x) (SignExt8to16 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386MODW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to16, typ.Int16)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to16, typ.Int16)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValue386_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8u x y)
+ // result: (MODWU (ZeroExt8to16 x) (ZeroExt8to16 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386MODWU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to16, typ.UInt16)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to16, typ.UInt16)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValue386_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Move [0] _ _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Move [1] dst src mem)
+ // result: (MOVBstore dst (MOVBload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(Op386MOVBstore)
+ v0 := b.NewValue0(v.Pos, Op386MOVBload, typ.UInt8)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] dst src mem)
+ // result: (MOVWstore dst (MOVWload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(Op386MOVWstore)
+ v0 := b.NewValue0(v.Pos, Op386MOVWload, typ.UInt16)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [4] dst src mem)
+ // result: (MOVLstore dst (MOVLload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(Op386MOVLstore)
+ v0 := b.NewValue0(v.Pos, Op386MOVLload, typ.UInt32)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [3] dst src mem)
+ // result: (MOVBstore [2] dst (MOVBload [2] src mem) (MOVWstore dst (MOVWload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(Op386MOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, Op386MOVBload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, Op386MOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, Op386MOVWload, typ.UInt16)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [5] dst src mem)
+ // result: (MOVBstore [4] dst (MOVBload [4] src mem) (MOVLstore dst (MOVLload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(Op386MOVBstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, Op386MOVBload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, Op386MOVLstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, Op386MOVLload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [6] dst src mem)
+ // result: (MOVWstore [4] dst (MOVWload [4] src mem) (MOVLstore dst (MOVLload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(Op386MOVWstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, Op386MOVWload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, Op386MOVLstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, Op386MOVLload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [7] dst src mem)
+ // result: (MOVLstore [3] dst (MOVLload [3] src mem) (MOVLstore dst (MOVLload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(Op386MOVLstore)
+ v.AuxInt = int32ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, Op386MOVLload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(3)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, Op386MOVLstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, Op386MOVLload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [8] dst src mem)
+ // result: (MOVLstore [4] dst (MOVLload [4] src mem) (MOVLstore dst (MOVLload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(Op386MOVLstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, Op386MOVLload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, Op386MOVLstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, Op386MOVLload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 8 && s%4 != 0
+ // result: (Move [s-s%4] (ADDLconst <dst.Type> dst [int32(s%4)]) (ADDLconst <src.Type> src [int32(s%4)]) (MOVLstore dst (MOVLload src mem) mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 8 && s%4 != 0) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(s - s%4)
+ v0 := b.NewValue0(v.Pos, Op386ADDLconst, dst.Type)
+ v0.AuxInt = int32ToAuxInt(int32(s % 4))
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, Op386ADDLconst, src.Type)
+ v1.AuxInt = int32ToAuxInt(int32(s % 4))
+ v1.AddArg(src)
+ v2 := b.NewValue0(v.Pos, Op386MOVLstore, types.TypeMem)
+ v3 := b.NewValue0(v.Pos, Op386MOVLload, typ.UInt32)
+ v3.AddArg2(src, mem)
+ v2.AddArg3(dst, v3, mem)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 8 && s <= 4*128 && s%4 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
+ // result: (DUFFCOPY [10*(128-s/4)] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 8 && s <= 4*128 && s%4 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(Op386DUFFCOPY)
+ v.AuxInt = int64ToAuxInt(10 * (128 - s/4))
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: (s > 4*128 || config.noDuffDevice) && s%4 == 0 && logLargeCopy(v, s)
+ // result: (REPMOVSL dst src (MOVLconst [int32(s/4)]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !((s > 4*128 || config.noDuffDevice) && s%4 == 0 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(Op386REPMOVSL)
+ v0 := b.NewValue0(v.Pos, Op386MOVLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(s / 4))
+ v.AddArg4(dst, src, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpNeg32F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neg32F x)
+ // result: (PXOR x (MOVSSconst <typ.Float32> [float32(math.Copysign(0, -1))]))
+ for {
+ x := v_0
+ v.reset(Op386PXOR)
+ v0 := b.NewValue0(v.Pos, Op386MOVSSconst, typ.Float32)
+ v0.AuxInt = float32ToAuxInt(float32(math.Copysign(0, -1)))
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValue386_OpNeg64F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neg64F x)
+ // result: (PXOR x (MOVSDconst <typ.Float64> [math.Copysign(0, -1)]))
+ for {
+ x := v_0
+ v.reset(Op386PXOR)
+ v0 := b.NewValue0(v.Pos, Op386MOVSDconst, typ.Float64)
+ v0.AuxInt = float64ToAuxInt(math.Copysign(0, -1))
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValue386_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq16 x y)
+ // result: (SETNE (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETNE)
+ v0 := b.NewValue0(v.Pos, Op386CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32 x y)
+ // result: (SETNE (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETNE)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpNeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32F x y)
+ // result: (SETNEF (UCOMISS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETNEF)
+ v0 := b.NewValue0(v.Pos, Op386UCOMISS, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpNeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64F x y)
+ // result: (SETNEF (UCOMISD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETNEF)
+ v0 := b.NewValue0(v.Pos, Op386UCOMISD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq8 x y)
+ // result: (SETNE (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETNE)
+ v0 := b.NewValue0(v.Pos, Op386CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpNeqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (NeqB x y)
+ // result: (SETNE (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETNE)
+ v0 := b.NewValue0(v.Pos, Op386CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpNeqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (NeqPtr x y)
+ // result: (SETNE (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(Op386SETNE)
+ v0 := b.NewValue0(v.Pos, Op386CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpNot(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Not x)
+ // result: (XORLconst [1] x)
+ for {
+ x := v_0
+ v.reset(Op386XORLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValue386_OpOffPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (OffPtr [off] ptr)
+ // result: (ADDLconst [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ v.reset(Op386ADDLconst)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+}
+func rewriteValue386_OpPanicBounds(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicBoundsA [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(Op386LoweredPanicBoundsA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicBoundsB [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(Op386LoweredPanicBoundsB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicBoundsC [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(Op386LoweredPanicBoundsC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpPanicExtend(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicExtend [kind] hi lo y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicExtendA [kind] hi lo y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ hi := v_0
+ lo := v_1
+ y := v_2
+ mem := v_3
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(Op386LoweredPanicExtendA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg4(hi, lo, y, mem)
+ return true
+ }
+ // match: (PanicExtend [kind] hi lo y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicExtendB [kind] hi lo y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ hi := v_0
+ lo := v_1
+ y := v_2
+ mem := v_3
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(Op386LoweredPanicExtendB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg4(hi, lo, y, mem)
+ return true
+ }
+ // match: (PanicExtend [kind] hi lo y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicExtendC [kind] hi lo y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ hi := v_0
+ lo := v_1
+ y := v_2
+ mem := v_3
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(Op386LoweredPanicExtendC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg4(hi, lo, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRotateLeft16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RotateLeft16 x (MOVLconst [c]))
+ // result: (ROLWconst [int16(c&15)] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386ROLWconst)
+ v.AuxInt = int16ToAuxInt(int16(c & 15))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRotateLeft32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RotateLeft32 x (MOVLconst [c]))
+ // result: (ROLLconst [c&31] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386ROLLconst)
+ v.AuxInt = int32ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRotateLeft8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RotateLeft8 x (MOVLconst [c]))
+ // result: (ROLBconst [int8(c&7)] x)
+ for {
+ x := v_0
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(Op386ROLBconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 7))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16Ux16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPWconst y [16])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(16)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh16Ux16 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRW <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHRW)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16Ux32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPLconst y [16])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(16)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh16Ux32 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRW <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHRW)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Rsh16Ux64 x (Const64 [c]))
+ // cond: uint64(c) < 16
+ // result: (SHRWconst x [int16(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 16) {
+ break
+ }
+ v.reset(Op386SHRWconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh16Ux64 _ (Const64 [c]))
+ // cond: uint64(c) >= 16
+ // result: (Const16 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16Ux8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPBconst y [16])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(16)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh16Ux8 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRW <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHRW)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARW <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [16])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARW)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, Op386ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, Op386NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, Op386SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, Op386CMPWconst, types.TypeFlags)
+ v3.AuxInt = int16ToAuxInt(16)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x16 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARW <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [16])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARW)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, Op386ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, Op386NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, Op386SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(16)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x32 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Rsh16x64 x (Const64 [c]))
+ // cond: uint64(c) < 16
+ // result: (SARWconst x [int16(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 16) {
+ break
+ }
+ v.reset(Op386SARWconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh16x64 x (Const64 [c]))
+ // cond: uint64(c) >= 16
+ // result: (SARWconst x [15])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(Op386SARWconst)
+ v.AuxInt = int16ToAuxInt(15)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARW <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [16])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARW)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, Op386ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, Op386NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, Op386SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, Op386CMPBconst, types.TypeFlags)
+ v3.AuxInt = int8ToAuxInt(16)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x8 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh32Ux16 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHRL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh32Ux32 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHRL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Rsh32Ux64 x (Const64 [c]))
+ // cond: uint64(c) < 32
+ // result: (SHRLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 32) {
+ break
+ }
+ v.reset(Op386SHRLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32Ux64 _ (Const64 [c]))
+ // cond: uint64(c) >= 32
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh32Ux8 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRL <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHRL)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARL <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [32])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARL)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, Op386ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, Op386NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, Op386SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, Op386CMPWconst, types.TypeFlags)
+ v3.AuxInt = int16ToAuxInt(32)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x16 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARL <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [32])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARL)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, Op386ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, Op386NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, Op386SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x32 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Rsh32x64 x (Const64 [c]))
+ // cond: uint64(c) < 32
+ // result: (SARLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 32) {
+ break
+ }
+ v.reset(Op386SARLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32x64 x (Const64 [c]))
+ // cond: uint64(c) >= 32
+ // result: (SARLconst x [31])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(Op386SARLconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARL <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [32])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARL)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, Op386ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, Op386NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, Op386SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, Op386CMPBconst, types.TypeFlags)
+ v3.AuxInt = int8ToAuxInt(32)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x8 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8Ux16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPWconst y [8])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHRB, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(8)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh8Ux16 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRB <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHRB)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8Ux32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPLconst y [8])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHRB, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(8)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh8Ux32 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRB <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHRB)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Rsh8Ux64 x (Const64 [c]))
+ // cond: uint64(c) < 8
+ // result: (SHRBconst x [int8(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 8) {
+ break
+ }
+ v.reset(Op386SHRBconst)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh8Ux64 _ (Const64 [c]))
+ // cond: uint64(c) >= 8
+ // result: (Const8 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8Ux8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPBconst y [8])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386ANDL)
+ v0 := b.NewValue0(v.Pos, Op386SHRB, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, Op386CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(8)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh8Ux8 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRB <t> x y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SHRB)
+ v.Type = t
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARB <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [8])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARB)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, Op386ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, Op386NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, Op386SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, Op386CMPWconst, types.TypeFlags)
+ v3.AuxInt = int16ToAuxInt(8)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x16 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARB <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [8])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARB)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, Op386ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, Op386NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, Op386SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(8)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x32 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Rsh8x64 x (Const64 [c]))
+ // cond: uint64(c) < 8
+ // result: (SARBconst x [int8(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 8) {
+ break
+ }
+ v.reset(Op386SARBconst)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh8x64 x (Const64 [c]))
+ // cond: uint64(c) >= 8
+ // result: (SARBconst x [7])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(Op386SARBconst)
+ v.AuxInt = int8ToAuxInt(7)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARB <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [8])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARB)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, Op386ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, Op386NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, Op386SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, Op386CMPBconst, types.TypeFlags)
+ v3.AuxInt = int8ToAuxInt(8)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x8 <t> x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(Op386SARB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpSelect0(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select0 (Mul32uover x y))
+ // result: (Select0 <typ.UInt32> (MULLU x y))
+ for {
+ if v_0.Op != OpMul32uover {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpSelect0)
+ v.Type = typ.UInt32
+ v0 := b.NewValue0(v.Pos, Op386MULLU, types.NewTuple(typ.UInt32, types.TypeFlags))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpSelect1(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select1 (Mul32uover x y))
+ // result: (SETO (Select1 <types.TypeFlags> (MULLU x y)))
+ for {
+ if v_0.Op != OpMul32uover {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(Op386SETO)
+ v0 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, Op386MULLU, types.NewTuple(typ.UInt32, types.TypeFlags))
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpSignmask(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Signmask x)
+ // result: (SARLconst x [31])
+ for {
+ x := v_0
+ v.reset(Op386SARLconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValue386_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Slicemask <t> x)
+ // result: (SARLconst (NEGL <t> x) [31])
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(Op386SARLconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v0 := b.NewValue0(v.Pos, Op386NEGL, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && is64BitFloat(val.Type)
+ // result: (MOVSDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(Op386MOVSDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && is32BitFloat(val.Type)
+ // result: (MOVSSstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(Op386MOVSSstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4
+ // result: (MOVLstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4) {
+ break
+ }
+ v.reset(Op386MOVLstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 2
+ // result: (MOVWstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 2) {
+ break
+ }
+ v.reset(Op386MOVWstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 1
+ // result: (MOVBstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 1) {
+ break
+ }
+ v.reset(Op386MOVBstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Zero [0] _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_1
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero [1] destptr mem)
+ // result: (MOVBstoreconst [0] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(Op386MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(0)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [2] destptr mem)
+ // result: (MOVWstoreconst [0] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(Op386MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(0)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [4] destptr mem)
+ // result: (MOVLstoreconst [0] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(0)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [3] destptr mem)
+ // result: (MOVBstoreconst [makeValAndOff32(0,2)] destptr (MOVWstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(Op386MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 2))
+ v0 := b.NewValue0(v.Pos, Op386MOVWstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [5] destptr mem)
+ // result: (MOVBstoreconst [makeValAndOff32(0,4)] destptr (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(Op386MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 4))
+ v0 := b.NewValue0(v.Pos, Op386MOVLstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [6] destptr mem)
+ // result: (MOVWstoreconst [makeValAndOff32(0,4)] destptr (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(Op386MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 4))
+ v0 := b.NewValue0(v.Pos, Op386MOVLstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [7] destptr mem)
+ // result: (MOVLstoreconst [makeValAndOff32(0,3)] destptr (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 3))
+ v0 := b.NewValue0(v.Pos, Op386MOVLstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s%4 != 0 && s > 4
+ // result: (Zero [s-s%4] (ADDLconst destptr [int32(s%4)]) (MOVLstoreconst [0] destptr mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s%4 != 0 && s > 4) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(s - s%4)
+ v0 := b.NewValue0(v.Pos, Op386ADDLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(s % 4))
+ v0.AddArg(destptr)
+ v1 := b.NewValue0(v.Pos, Op386MOVLstoreconst, types.TypeMem)
+ v1.AuxInt = valAndOffToAuxInt(0)
+ v1.AddArg2(destptr, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Zero [8] destptr mem)
+ // result: (MOVLstoreconst [makeValAndOff32(0,4)] destptr (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 4))
+ v0 := b.NewValue0(v.Pos, Op386MOVLstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [12] destptr mem)
+ // result: (MOVLstoreconst [makeValAndOff32(0,8)] destptr (MOVLstoreconst [makeValAndOff32(0,4)] destptr (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 8))
+ v0 := b.NewValue0(v.Pos, Op386MOVLstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 4))
+ v1 := b.NewValue0(v.Pos, Op386MOVLstoreconst, types.TypeMem)
+ v1.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v1.AddArg2(destptr, mem)
+ v0.AddArg2(destptr, v1)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [16] destptr mem)
+ // result: (MOVLstoreconst [makeValAndOff32(0,12)] destptr (MOVLstoreconst [makeValAndOff32(0,8)] destptr (MOVLstoreconst [makeValAndOff32(0,4)] destptr (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(Op386MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 12))
+ v0 := b.NewValue0(v.Pos, Op386MOVLstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 8))
+ v1 := b.NewValue0(v.Pos, Op386MOVLstoreconst, types.TypeMem)
+ v1.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 4))
+ v2 := b.NewValue0(v.Pos, Op386MOVLstoreconst, types.TypeMem)
+ v2.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v2.AddArg2(destptr, mem)
+ v1.AddArg2(destptr, v2)
+ v0.AddArg2(destptr, v1)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s > 16 && s <= 4*128 && s%4 == 0 && !config.noDuffDevice
+ // result: (DUFFZERO [1*(128-s/4)] destptr (MOVLconst [0]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s > 16 && s <= 4*128 && s%4 == 0 && !config.noDuffDevice) {
+ break
+ }
+ v.reset(Op386DUFFZERO)
+ v.AuxInt = int64ToAuxInt(1 * (128 - s/4))
+ v0 := b.NewValue0(v.Pos, Op386MOVLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(destptr, v0, mem)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: (s > 4*128 || (config.noDuffDevice && s > 16)) && s%4 == 0
+ // result: (REPSTOSL destptr (MOVLconst [int32(s/4)]) (MOVLconst [0]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !((s > 4*128 || (config.noDuffDevice && s > 16)) && s%4 == 0) {
+ break
+ }
+ v.reset(Op386REPSTOSL)
+ v0 := b.NewValue0(v.Pos, Op386MOVLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(s / 4))
+ v1 := b.NewValue0(v.Pos, Op386MOVLconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v.AddArg4(destptr, v0, v1, mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_OpZeromask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Zeromask <t> x)
+ // result: (XORLconst [-1] (SBBLcarrymask <t> (CMPLconst x [1])))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(Op386XORLconst)
+ v.AuxInt = int32ToAuxInt(-1)
+ v0 := b.NewValue0(v.Pos, Op386SBBLcarrymask, t)
+ v1 := b.NewValue0(v.Pos, Op386CMPLconst, types.TypeFlags)
+ v1.AuxInt = int32ToAuxInt(1)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteBlock386(b *Block) bool {
+ switch b.Kind {
+ case Block386EQ:
+ // match: (EQ (InvertFlags cmp) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == Op386InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386EQ, cmp)
+ return true
+ }
+ // match: (EQ (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (EQ (FlagLT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagLT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (EQ (FlagLT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagLT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (EQ (FlagGT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagGT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (EQ (FlagGT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagGT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case Block386GE:
+ // match: (GE (InvertFlags cmp) yes no)
+ // result: (LE cmp yes no)
+ for b.Controls[0].Op == Op386InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386LE, cmp)
+ return true
+ }
+ // match: (GE (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GE (FlagLT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagLT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GE (FlagLT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagLT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GE (FlagGT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagGT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GE (FlagGT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagGT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ case Block386GT:
+ // match: (GT (InvertFlags cmp) yes no)
+ // result: (LT cmp yes no)
+ for b.Controls[0].Op == Op386InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386LT, cmp)
+ return true
+ }
+ // match: (GT (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GT (FlagLT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagLT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GT (FlagLT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagLT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GT (FlagGT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagGT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GT (FlagGT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagGT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ case BlockIf:
+ // match: (If (SETL cmp) yes no)
+ // result: (LT cmp yes no)
+ for b.Controls[0].Op == Op386SETL {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386LT, cmp)
+ return true
+ }
+ // match: (If (SETLE cmp) yes no)
+ // result: (LE cmp yes no)
+ for b.Controls[0].Op == Op386SETLE {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386LE, cmp)
+ return true
+ }
+ // match: (If (SETG cmp) yes no)
+ // result: (GT cmp yes no)
+ for b.Controls[0].Op == Op386SETG {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386GT, cmp)
+ return true
+ }
+ // match: (If (SETGE cmp) yes no)
+ // result: (GE cmp yes no)
+ for b.Controls[0].Op == Op386SETGE {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386GE, cmp)
+ return true
+ }
+ // match: (If (SETEQ cmp) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == Op386SETEQ {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386EQ, cmp)
+ return true
+ }
+ // match: (If (SETNE cmp) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == Op386SETNE {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386NE, cmp)
+ return true
+ }
+ // match: (If (SETB cmp) yes no)
+ // result: (ULT cmp yes no)
+ for b.Controls[0].Op == Op386SETB {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386ULT, cmp)
+ return true
+ }
+ // match: (If (SETBE cmp) yes no)
+ // result: (ULE cmp yes no)
+ for b.Controls[0].Op == Op386SETBE {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386ULE, cmp)
+ return true
+ }
+ // match: (If (SETA cmp) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == Op386SETA {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386UGT, cmp)
+ return true
+ }
+ // match: (If (SETAE cmp) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == Op386SETAE {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386UGE, cmp)
+ return true
+ }
+ // match: (If (SETO cmp) yes no)
+ // result: (OS cmp yes no)
+ for b.Controls[0].Op == Op386SETO {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386OS, cmp)
+ return true
+ }
+ // match: (If (SETGF cmp) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == Op386SETGF {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386UGT, cmp)
+ return true
+ }
+ // match: (If (SETGEF cmp) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == Op386SETGEF {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386UGE, cmp)
+ return true
+ }
+ // match: (If (SETEQF cmp) yes no)
+ // result: (EQF cmp yes no)
+ for b.Controls[0].Op == Op386SETEQF {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386EQF, cmp)
+ return true
+ }
+ // match: (If (SETNEF cmp) yes no)
+ // result: (NEF cmp yes no)
+ for b.Controls[0].Op == Op386SETNEF {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386NEF, cmp)
+ return true
+ }
+ // match: (If cond yes no)
+ // result: (NE (TESTB cond cond) yes no)
+ for {
+ cond := b.Controls[0]
+ v0 := b.NewValue0(cond.Pos, Op386TESTB, types.TypeFlags)
+ v0.AddArg2(cond, cond)
+ b.resetWithControl(Block386NE, v0)
+ return true
+ }
+ case Block386LE:
+ // match: (LE (InvertFlags cmp) yes no)
+ // result: (GE cmp yes no)
+ for b.Controls[0].Op == Op386InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386GE, cmp)
+ return true
+ }
+ // match: (LE (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LE (FlagLT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagLT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LE (FlagLT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagLT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LE (FlagGT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagGT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LE (FlagGT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagGT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case Block386LT:
+ // match: (LT (InvertFlags cmp) yes no)
+ // result: (GT cmp yes no)
+ for b.Controls[0].Op == Op386InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386GT, cmp)
+ return true
+ }
+ // match: (LT (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LT (FlagLT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagLT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LT (FlagLT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagLT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LT (FlagGT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagGT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LT (FlagGT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagGT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case Block386NE:
+ // match: (NE (TESTB (SETL cmp) (SETL cmp)) yes no)
+ // result: (LT cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETL {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETL || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386LT, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETLE cmp) (SETLE cmp)) yes no)
+ // result: (LE cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETLE {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETLE || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386LE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETG cmp) (SETG cmp)) yes no)
+ // result: (GT cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETG {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETG || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386GT, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETGE cmp) (SETGE cmp)) yes no)
+ // result: (GE cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETGE {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETGE || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386GE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETEQ cmp) (SETEQ cmp)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETEQ {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETEQ || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386EQ, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETNE cmp) (SETNE cmp)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETNE {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETNE || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386NE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETB cmp) (SETB cmp)) yes no)
+ // result: (ULT cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETB {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETB || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386ULT, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETBE cmp) (SETBE cmp)) yes no)
+ // result: (ULE cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETBE {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETBE || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386ULE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETA cmp) (SETA cmp)) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETA {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETA || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386UGT, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETAE cmp) (SETAE cmp)) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETAE {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETAE || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386UGE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETO cmp) (SETO cmp)) yes no)
+ // result: (OS cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETO {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETO || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386OS, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETGF cmp) (SETGF cmp)) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETGF {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETGF || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386UGT, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETGEF cmp) (SETGEF cmp)) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETGEF {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETGEF || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386UGE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETEQF cmp) (SETEQF cmp)) yes no)
+ // result: (EQF cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETEQF {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETEQF || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386EQF, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETNEF cmp) (SETNEF cmp)) yes no)
+ // result: (NEF cmp yes no)
+ for b.Controls[0].Op == Op386TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != Op386SETNEF {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != Op386SETNEF || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(Block386NEF, cmp)
+ return true
+ }
+ // match: (NE (InvertFlags cmp) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == Op386InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386NE, cmp)
+ return true
+ }
+ // match: (NE (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (NE (FlagLT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagLT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (NE (FlagLT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagLT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (NE (FlagGT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagGT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (NE (FlagGT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagGT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ case Block386UGE:
+ // match: (UGE (InvertFlags cmp) yes no)
+ // result: (ULE cmp yes no)
+ for b.Controls[0].Op == Op386InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386ULE, cmp)
+ return true
+ }
+ // match: (UGE (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGE (FlagLT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagLT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGE (FlagLT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagLT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGE (FlagGT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagGT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGE (FlagGT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagGT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ case Block386UGT:
+ // match: (UGT (InvertFlags cmp) yes no)
+ // result: (ULT cmp yes no)
+ for b.Controls[0].Op == Op386InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386ULT, cmp)
+ return true
+ }
+ // match: (UGT (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGT (FlagLT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagLT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGT (FlagLT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagLT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGT (FlagGT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagGT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGT (FlagGT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagGT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ case Block386ULE:
+ // match: (ULE (InvertFlags cmp) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == Op386InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386UGE, cmp)
+ return true
+ }
+ // match: (ULE (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULE (FlagLT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagLT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULE (FlagLT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagLT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULE (FlagGT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagGT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULE (FlagGT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagGT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case Block386ULT:
+ // match: (ULT (InvertFlags cmp) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == Op386InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(Block386UGT, cmp)
+ return true
+ }
+ // match: (ULT (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULT (FlagLT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagLT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULT (FlagLT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagLT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULT (FlagGT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == Op386FlagGT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULT (FlagGT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == Op386FlagGT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewrite386splitload.go b/src/cmd/compile/internal/ssa/rewrite386splitload.go
new file mode 100644
index 0000000..fff26fa
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewrite386splitload.go
@@ -0,0 +1,162 @@
+// Code generated from gen/386splitload.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+func rewriteValue386splitload(v *Value) bool {
+ switch v.Op {
+ case Op386CMPBconstload:
+ return rewriteValue386splitload_Op386CMPBconstload(v)
+ case Op386CMPBload:
+ return rewriteValue386splitload_Op386CMPBload(v)
+ case Op386CMPLconstload:
+ return rewriteValue386splitload_Op386CMPLconstload(v)
+ case Op386CMPLload:
+ return rewriteValue386splitload_Op386CMPLload(v)
+ case Op386CMPWconstload:
+ return rewriteValue386splitload_Op386CMPWconstload(v)
+ case Op386CMPWload:
+ return rewriteValue386splitload_Op386CMPWload(v)
+ }
+ return false
+}
+func rewriteValue386splitload_Op386CMPBconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPBconstload {sym} [vo] ptr mem)
+ // result: (CMPBconst (MOVBload {sym} [vo.Off32()] ptr mem) [vo.Val8()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ v.reset(Op386CMPBconst)
+ v.AuxInt = int8ToAuxInt(vo.Val8())
+ v0 := b.NewValue0(v.Pos, Op386MOVBload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386splitload_Op386CMPBload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPBload {sym} [off] ptr x mem)
+ // result: (CMPB (MOVBload {sym} [off] ptr mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ x := v_1
+ mem := v_2
+ v.reset(Op386CMPB)
+ v0 := b.NewValue0(v.Pos, Op386MOVBload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValue386splitload_Op386CMPLconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPLconstload {sym} [vo] ptr mem)
+ // result: (CMPLconst (MOVLload {sym} [vo.Off32()] ptr mem) [vo.Val32()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ v.reset(Op386CMPLconst)
+ v.AuxInt = int32ToAuxInt(vo.Val32())
+ v0 := b.NewValue0(v.Pos, Op386MOVLload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386splitload_Op386CMPLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPLload {sym} [off] ptr x mem)
+ // result: (CMPL (MOVLload {sym} [off] ptr mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ x := v_1
+ mem := v_2
+ v.reset(Op386CMPL)
+ v0 := b.NewValue0(v.Pos, Op386MOVLload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValue386splitload_Op386CMPWconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPWconstload {sym} [vo] ptr mem)
+ // result: (CMPWconst (MOVWload {sym} [vo.Off32()] ptr mem) [vo.Val16()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ v.reset(Op386CMPWconst)
+ v.AuxInt = int16ToAuxInt(vo.Val16())
+ v0 := b.NewValue0(v.Pos, Op386MOVWload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValue386splitload_Op386CMPWload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPWload {sym} [off] ptr x mem)
+ // result: (CMPW (MOVWload {sym} [off] ptr mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ x := v_1
+ mem := v_2
+ v.reset(Op386CMPW)
+ v0 := b.NewValue0(v.Pos, Op386MOVWload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteBlock386splitload(b *Block) bool {
+ switch b.Kind {
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go
new file mode 100644
index 0000000..8272a40
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go
@@ -0,0 +1,35989 @@
+// Code generated from gen/AMD64.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "math"
+import "cmd/compile/internal/types"
+
+func rewriteValueAMD64(v *Value) bool {
+ switch v.Op {
+ case OpAMD64ADCQ:
+ return rewriteValueAMD64_OpAMD64ADCQ(v)
+ case OpAMD64ADCQconst:
+ return rewriteValueAMD64_OpAMD64ADCQconst(v)
+ case OpAMD64ADDL:
+ return rewriteValueAMD64_OpAMD64ADDL(v)
+ case OpAMD64ADDLconst:
+ return rewriteValueAMD64_OpAMD64ADDLconst(v)
+ case OpAMD64ADDLconstmodify:
+ return rewriteValueAMD64_OpAMD64ADDLconstmodify(v)
+ case OpAMD64ADDLload:
+ return rewriteValueAMD64_OpAMD64ADDLload(v)
+ case OpAMD64ADDLmodify:
+ return rewriteValueAMD64_OpAMD64ADDLmodify(v)
+ case OpAMD64ADDQ:
+ return rewriteValueAMD64_OpAMD64ADDQ(v)
+ case OpAMD64ADDQcarry:
+ return rewriteValueAMD64_OpAMD64ADDQcarry(v)
+ case OpAMD64ADDQconst:
+ return rewriteValueAMD64_OpAMD64ADDQconst(v)
+ case OpAMD64ADDQconstmodify:
+ return rewriteValueAMD64_OpAMD64ADDQconstmodify(v)
+ case OpAMD64ADDQload:
+ return rewriteValueAMD64_OpAMD64ADDQload(v)
+ case OpAMD64ADDQmodify:
+ return rewriteValueAMD64_OpAMD64ADDQmodify(v)
+ case OpAMD64ADDSD:
+ return rewriteValueAMD64_OpAMD64ADDSD(v)
+ case OpAMD64ADDSDload:
+ return rewriteValueAMD64_OpAMD64ADDSDload(v)
+ case OpAMD64ADDSS:
+ return rewriteValueAMD64_OpAMD64ADDSS(v)
+ case OpAMD64ADDSSload:
+ return rewriteValueAMD64_OpAMD64ADDSSload(v)
+ case OpAMD64ANDL:
+ return rewriteValueAMD64_OpAMD64ANDL(v)
+ case OpAMD64ANDLconst:
+ return rewriteValueAMD64_OpAMD64ANDLconst(v)
+ case OpAMD64ANDLconstmodify:
+ return rewriteValueAMD64_OpAMD64ANDLconstmodify(v)
+ case OpAMD64ANDLload:
+ return rewriteValueAMD64_OpAMD64ANDLload(v)
+ case OpAMD64ANDLmodify:
+ return rewriteValueAMD64_OpAMD64ANDLmodify(v)
+ case OpAMD64ANDQ:
+ return rewriteValueAMD64_OpAMD64ANDQ(v)
+ case OpAMD64ANDQconst:
+ return rewriteValueAMD64_OpAMD64ANDQconst(v)
+ case OpAMD64ANDQconstmodify:
+ return rewriteValueAMD64_OpAMD64ANDQconstmodify(v)
+ case OpAMD64ANDQload:
+ return rewriteValueAMD64_OpAMD64ANDQload(v)
+ case OpAMD64ANDQmodify:
+ return rewriteValueAMD64_OpAMD64ANDQmodify(v)
+ case OpAMD64BSFQ:
+ return rewriteValueAMD64_OpAMD64BSFQ(v)
+ case OpAMD64BTCLconst:
+ return rewriteValueAMD64_OpAMD64BTCLconst(v)
+ case OpAMD64BTCLconstmodify:
+ return rewriteValueAMD64_OpAMD64BTCLconstmodify(v)
+ case OpAMD64BTCLmodify:
+ return rewriteValueAMD64_OpAMD64BTCLmodify(v)
+ case OpAMD64BTCQconst:
+ return rewriteValueAMD64_OpAMD64BTCQconst(v)
+ case OpAMD64BTCQconstmodify:
+ return rewriteValueAMD64_OpAMD64BTCQconstmodify(v)
+ case OpAMD64BTCQmodify:
+ return rewriteValueAMD64_OpAMD64BTCQmodify(v)
+ case OpAMD64BTLconst:
+ return rewriteValueAMD64_OpAMD64BTLconst(v)
+ case OpAMD64BTQconst:
+ return rewriteValueAMD64_OpAMD64BTQconst(v)
+ case OpAMD64BTRLconst:
+ return rewriteValueAMD64_OpAMD64BTRLconst(v)
+ case OpAMD64BTRLconstmodify:
+ return rewriteValueAMD64_OpAMD64BTRLconstmodify(v)
+ case OpAMD64BTRLmodify:
+ return rewriteValueAMD64_OpAMD64BTRLmodify(v)
+ case OpAMD64BTRQconst:
+ return rewriteValueAMD64_OpAMD64BTRQconst(v)
+ case OpAMD64BTRQconstmodify:
+ return rewriteValueAMD64_OpAMD64BTRQconstmodify(v)
+ case OpAMD64BTRQmodify:
+ return rewriteValueAMD64_OpAMD64BTRQmodify(v)
+ case OpAMD64BTSLconst:
+ return rewriteValueAMD64_OpAMD64BTSLconst(v)
+ case OpAMD64BTSLconstmodify:
+ return rewriteValueAMD64_OpAMD64BTSLconstmodify(v)
+ case OpAMD64BTSLmodify:
+ return rewriteValueAMD64_OpAMD64BTSLmodify(v)
+ case OpAMD64BTSQconst:
+ return rewriteValueAMD64_OpAMD64BTSQconst(v)
+ case OpAMD64BTSQconstmodify:
+ return rewriteValueAMD64_OpAMD64BTSQconstmodify(v)
+ case OpAMD64BTSQmodify:
+ return rewriteValueAMD64_OpAMD64BTSQmodify(v)
+ case OpAMD64CMOVLCC:
+ return rewriteValueAMD64_OpAMD64CMOVLCC(v)
+ case OpAMD64CMOVLCS:
+ return rewriteValueAMD64_OpAMD64CMOVLCS(v)
+ case OpAMD64CMOVLEQ:
+ return rewriteValueAMD64_OpAMD64CMOVLEQ(v)
+ case OpAMD64CMOVLGE:
+ return rewriteValueAMD64_OpAMD64CMOVLGE(v)
+ case OpAMD64CMOVLGT:
+ return rewriteValueAMD64_OpAMD64CMOVLGT(v)
+ case OpAMD64CMOVLHI:
+ return rewriteValueAMD64_OpAMD64CMOVLHI(v)
+ case OpAMD64CMOVLLE:
+ return rewriteValueAMD64_OpAMD64CMOVLLE(v)
+ case OpAMD64CMOVLLS:
+ return rewriteValueAMD64_OpAMD64CMOVLLS(v)
+ case OpAMD64CMOVLLT:
+ return rewriteValueAMD64_OpAMD64CMOVLLT(v)
+ case OpAMD64CMOVLNE:
+ return rewriteValueAMD64_OpAMD64CMOVLNE(v)
+ case OpAMD64CMOVQCC:
+ return rewriteValueAMD64_OpAMD64CMOVQCC(v)
+ case OpAMD64CMOVQCS:
+ return rewriteValueAMD64_OpAMD64CMOVQCS(v)
+ case OpAMD64CMOVQEQ:
+ return rewriteValueAMD64_OpAMD64CMOVQEQ(v)
+ case OpAMD64CMOVQGE:
+ return rewriteValueAMD64_OpAMD64CMOVQGE(v)
+ case OpAMD64CMOVQGT:
+ return rewriteValueAMD64_OpAMD64CMOVQGT(v)
+ case OpAMD64CMOVQHI:
+ return rewriteValueAMD64_OpAMD64CMOVQHI(v)
+ case OpAMD64CMOVQLE:
+ return rewriteValueAMD64_OpAMD64CMOVQLE(v)
+ case OpAMD64CMOVQLS:
+ return rewriteValueAMD64_OpAMD64CMOVQLS(v)
+ case OpAMD64CMOVQLT:
+ return rewriteValueAMD64_OpAMD64CMOVQLT(v)
+ case OpAMD64CMOVQNE:
+ return rewriteValueAMD64_OpAMD64CMOVQNE(v)
+ case OpAMD64CMOVWCC:
+ return rewriteValueAMD64_OpAMD64CMOVWCC(v)
+ case OpAMD64CMOVWCS:
+ return rewriteValueAMD64_OpAMD64CMOVWCS(v)
+ case OpAMD64CMOVWEQ:
+ return rewriteValueAMD64_OpAMD64CMOVWEQ(v)
+ case OpAMD64CMOVWGE:
+ return rewriteValueAMD64_OpAMD64CMOVWGE(v)
+ case OpAMD64CMOVWGT:
+ return rewriteValueAMD64_OpAMD64CMOVWGT(v)
+ case OpAMD64CMOVWHI:
+ return rewriteValueAMD64_OpAMD64CMOVWHI(v)
+ case OpAMD64CMOVWLE:
+ return rewriteValueAMD64_OpAMD64CMOVWLE(v)
+ case OpAMD64CMOVWLS:
+ return rewriteValueAMD64_OpAMD64CMOVWLS(v)
+ case OpAMD64CMOVWLT:
+ return rewriteValueAMD64_OpAMD64CMOVWLT(v)
+ case OpAMD64CMOVWNE:
+ return rewriteValueAMD64_OpAMD64CMOVWNE(v)
+ case OpAMD64CMPB:
+ return rewriteValueAMD64_OpAMD64CMPB(v)
+ case OpAMD64CMPBconst:
+ return rewriteValueAMD64_OpAMD64CMPBconst(v)
+ case OpAMD64CMPBconstload:
+ return rewriteValueAMD64_OpAMD64CMPBconstload(v)
+ case OpAMD64CMPBload:
+ return rewriteValueAMD64_OpAMD64CMPBload(v)
+ case OpAMD64CMPL:
+ return rewriteValueAMD64_OpAMD64CMPL(v)
+ case OpAMD64CMPLconst:
+ return rewriteValueAMD64_OpAMD64CMPLconst(v)
+ case OpAMD64CMPLconstload:
+ return rewriteValueAMD64_OpAMD64CMPLconstload(v)
+ case OpAMD64CMPLload:
+ return rewriteValueAMD64_OpAMD64CMPLload(v)
+ case OpAMD64CMPQ:
+ return rewriteValueAMD64_OpAMD64CMPQ(v)
+ case OpAMD64CMPQconst:
+ return rewriteValueAMD64_OpAMD64CMPQconst(v)
+ case OpAMD64CMPQconstload:
+ return rewriteValueAMD64_OpAMD64CMPQconstload(v)
+ case OpAMD64CMPQload:
+ return rewriteValueAMD64_OpAMD64CMPQload(v)
+ case OpAMD64CMPW:
+ return rewriteValueAMD64_OpAMD64CMPW(v)
+ case OpAMD64CMPWconst:
+ return rewriteValueAMD64_OpAMD64CMPWconst(v)
+ case OpAMD64CMPWconstload:
+ return rewriteValueAMD64_OpAMD64CMPWconstload(v)
+ case OpAMD64CMPWload:
+ return rewriteValueAMD64_OpAMD64CMPWload(v)
+ case OpAMD64CMPXCHGLlock:
+ return rewriteValueAMD64_OpAMD64CMPXCHGLlock(v)
+ case OpAMD64CMPXCHGQlock:
+ return rewriteValueAMD64_OpAMD64CMPXCHGQlock(v)
+ case OpAMD64DIVSD:
+ return rewriteValueAMD64_OpAMD64DIVSD(v)
+ case OpAMD64DIVSDload:
+ return rewriteValueAMD64_OpAMD64DIVSDload(v)
+ case OpAMD64DIVSS:
+ return rewriteValueAMD64_OpAMD64DIVSS(v)
+ case OpAMD64DIVSSload:
+ return rewriteValueAMD64_OpAMD64DIVSSload(v)
+ case OpAMD64HMULL:
+ return rewriteValueAMD64_OpAMD64HMULL(v)
+ case OpAMD64HMULLU:
+ return rewriteValueAMD64_OpAMD64HMULLU(v)
+ case OpAMD64HMULQ:
+ return rewriteValueAMD64_OpAMD64HMULQ(v)
+ case OpAMD64HMULQU:
+ return rewriteValueAMD64_OpAMD64HMULQU(v)
+ case OpAMD64LEAL:
+ return rewriteValueAMD64_OpAMD64LEAL(v)
+ case OpAMD64LEAL1:
+ return rewriteValueAMD64_OpAMD64LEAL1(v)
+ case OpAMD64LEAL2:
+ return rewriteValueAMD64_OpAMD64LEAL2(v)
+ case OpAMD64LEAL4:
+ return rewriteValueAMD64_OpAMD64LEAL4(v)
+ case OpAMD64LEAL8:
+ return rewriteValueAMD64_OpAMD64LEAL8(v)
+ case OpAMD64LEAQ:
+ return rewriteValueAMD64_OpAMD64LEAQ(v)
+ case OpAMD64LEAQ1:
+ return rewriteValueAMD64_OpAMD64LEAQ1(v)
+ case OpAMD64LEAQ2:
+ return rewriteValueAMD64_OpAMD64LEAQ2(v)
+ case OpAMD64LEAQ4:
+ return rewriteValueAMD64_OpAMD64LEAQ4(v)
+ case OpAMD64LEAQ8:
+ return rewriteValueAMD64_OpAMD64LEAQ8(v)
+ case OpAMD64MOVBQSX:
+ return rewriteValueAMD64_OpAMD64MOVBQSX(v)
+ case OpAMD64MOVBQSXload:
+ return rewriteValueAMD64_OpAMD64MOVBQSXload(v)
+ case OpAMD64MOVBQZX:
+ return rewriteValueAMD64_OpAMD64MOVBQZX(v)
+ case OpAMD64MOVBatomicload:
+ return rewriteValueAMD64_OpAMD64MOVBatomicload(v)
+ case OpAMD64MOVBload:
+ return rewriteValueAMD64_OpAMD64MOVBload(v)
+ case OpAMD64MOVBstore:
+ return rewriteValueAMD64_OpAMD64MOVBstore(v)
+ case OpAMD64MOVBstoreconst:
+ return rewriteValueAMD64_OpAMD64MOVBstoreconst(v)
+ case OpAMD64MOVLQSX:
+ return rewriteValueAMD64_OpAMD64MOVLQSX(v)
+ case OpAMD64MOVLQSXload:
+ return rewriteValueAMD64_OpAMD64MOVLQSXload(v)
+ case OpAMD64MOVLQZX:
+ return rewriteValueAMD64_OpAMD64MOVLQZX(v)
+ case OpAMD64MOVLatomicload:
+ return rewriteValueAMD64_OpAMD64MOVLatomicload(v)
+ case OpAMD64MOVLf2i:
+ return rewriteValueAMD64_OpAMD64MOVLf2i(v)
+ case OpAMD64MOVLi2f:
+ return rewriteValueAMD64_OpAMD64MOVLi2f(v)
+ case OpAMD64MOVLload:
+ return rewriteValueAMD64_OpAMD64MOVLload(v)
+ case OpAMD64MOVLstore:
+ return rewriteValueAMD64_OpAMD64MOVLstore(v)
+ case OpAMD64MOVLstoreconst:
+ return rewriteValueAMD64_OpAMD64MOVLstoreconst(v)
+ case OpAMD64MOVOload:
+ return rewriteValueAMD64_OpAMD64MOVOload(v)
+ case OpAMD64MOVOstore:
+ return rewriteValueAMD64_OpAMD64MOVOstore(v)
+ case OpAMD64MOVQatomicload:
+ return rewriteValueAMD64_OpAMD64MOVQatomicload(v)
+ case OpAMD64MOVQf2i:
+ return rewriteValueAMD64_OpAMD64MOVQf2i(v)
+ case OpAMD64MOVQi2f:
+ return rewriteValueAMD64_OpAMD64MOVQi2f(v)
+ case OpAMD64MOVQload:
+ return rewriteValueAMD64_OpAMD64MOVQload(v)
+ case OpAMD64MOVQstore:
+ return rewriteValueAMD64_OpAMD64MOVQstore(v)
+ case OpAMD64MOVQstoreconst:
+ return rewriteValueAMD64_OpAMD64MOVQstoreconst(v)
+ case OpAMD64MOVSDload:
+ return rewriteValueAMD64_OpAMD64MOVSDload(v)
+ case OpAMD64MOVSDstore:
+ return rewriteValueAMD64_OpAMD64MOVSDstore(v)
+ case OpAMD64MOVSSload:
+ return rewriteValueAMD64_OpAMD64MOVSSload(v)
+ case OpAMD64MOVSSstore:
+ return rewriteValueAMD64_OpAMD64MOVSSstore(v)
+ case OpAMD64MOVWQSX:
+ return rewriteValueAMD64_OpAMD64MOVWQSX(v)
+ case OpAMD64MOVWQSXload:
+ return rewriteValueAMD64_OpAMD64MOVWQSXload(v)
+ case OpAMD64MOVWQZX:
+ return rewriteValueAMD64_OpAMD64MOVWQZX(v)
+ case OpAMD64MOVWload:
+ return rewriteValueAMD64_OpAMD64MOVWload(v)
+ case OpAMD64MOVWstore:
+ return rewriteValueAMD64_OpAMD64MOVWstore(v)
+ case OpAMD64MOVWstoreconst:
+ return rewriteValueAMD64_OpAMD64MOVWstoreconst(v)
+ case OpAMD64MULL:
+ return rewriteValueAMD64_OpAMD64MULL(v)
+ case OpAMD64MULLconst:
+ return rewriteValueAMD64_OpAMD64MULLconst(v)
+ case OpAMD64MULQ:
+ return rewriteValueAMD64_OpAMD64MULQ(v)
+ case OpAMD64MULQconst:
+ return rewriteValueAMD64_OpAMD64MULQconst(v)
+ case OpAMD64MULSD:
+ return rewriteValueAMD64_OpAMD64MULSD(v)
+ case OpAMD64MULSDload:
+ return rewriteValueAMD64_OpAMD64MULSDload(v)
+ case OpAMD64MULSS:
+ return rewriteValueAMD64_OpAMD64MULSS(v)
+ case OpAMD64MULSSload:
+ return rewriteValueAMD64_OpAMD64MULSSload(v)
+ case OpAMD64NEGL:
+ return rewriteValueAMD64_OpAMD64NEGL(v)
+ case OpAMD64NEGQ:
+ return rewriteValueAMD64_OpAMD64NEGQ(v)
+ case OpAMD64NOTL:
+ return rewriteValueAMD64_OpAMD64NOTL(v)
+ case OpAMD64NOTQ:
+ return rewriteValueAMD64_OpAMD64NOTQ(v)
+ case OpAMD64ORL:
+ return rewriteValueAMD64_OpAMD64ORL(v)
+ case OpAMD64ORLconst:
+ return rewriteValueAMD64_OpAMD64ORLconst(v)
+ case OpAMD64ORLconstmodify:
+ return rewriteValueAMD64_OpAMD64ORLconstmodify(v)
+ case OpAMD64ORLload:
+ return rewriteValueAMD64_OpAMD64ORLload(v)
+ case OpAMD64ORLmodify:
+ return rewriteValueAMD64_OpAMD64ORLmodify(v)
+ case OpAMD64ORQ:
+ return rewriteValueAMD64_OpAMD64ORQ(v)
+ case OpAMD64ORQconst:
+ return rewriteValueAMD64_OpAMD64ORQconst(v)
+ case OpAMD64ORQconstmodify:
+ return rewriteValueAMD64_OpAMD64ORQconstmodify(v)
+ case OpAMD64ORQload:
+ return rewriteValueAMD64_OpAMD64ORQload(v)
+ case OpAMD64ORQmodify:
+ return rewriteValueAMD64_OpAMD64ORQmodify(v)
+ case OpAMD64ROLB:
+ return rewriteValueAMD64_OpAMD64ROLB(v)
+ case OpAMD64ROLBconst:
+ return rewriteValueAMD64_OpAMD64ROLBconst(v)
+ case OpAMD64ROLL:
+ return rewriteValueAMD64_OpAMD64ROLL(v)
+ case OpAMD64ROLLconst:
+ return rewriteValueAMD64_OpAMD64ROLLconst(v)
+ case OpAMD64ROLQ:
+ return rewriteValueAMD64_OpAMD64ROLQ(v)
+ case OpAMD64ROLQconst:
+ return rewriteValueAMD64_OpAMD64ROLQconst(v)
+ case OpAMD64ROLW:
+ return rewriteValueAMD64_OpAMD64ROLW(v)
+ case OpAMD64ROLWconst:
+ return rewriteValueAMD64_OpAMD64ROLWconst(v)
+ case OpAMD64RORB:
+ return rewriteValueAMD64_OpAMD64RORB(v)
+ case OpAMD64RORL:
+ return rewriteValueAMD64_OpAMD64RORL(v)
+ case OpAMD64RORQ:
+ return rewriteValueAMD64_OpAMD64RORQ(v)
+ case OpAMD64RORW:
+ return rewriteValueAMD64_OpAMD64RORW(v)
+ case OpAMD64SARB:
+ return rewriteValueAMD64_OpAMD64SARB(v)
+ case OpAMD64SARBconst:
+ return rewriteValueAMD64_OpAMD64SARBconst(v)
+ case OpAMD64SARL:
+ return rewriteValueAMD64_OpAMD64SARL(v)
+ case OpAMD64SARLconst:
+ return rewriteValueAMD64_OpAMD64SARLconst(v)
+ case OpAMD64SARQ:
+ return rewriteValueAMD64_OpAMD64SARQ(v)
+ case OpAMD64SARQconst:
+ return rewriteValueAMD64_OpAMD64SARQconst(v)
+ case OpAMD64SARW:
+ return rewriteValueAMD64_OpAMD64SARW(v)
+ case OpAMD64SARWconst:
+ return rewriteValueAMD64_OpAMD64SARWconst(v)
+ case OpAMD64SBBLcarrymask:
+ return rewriteValueAMD64_OpAMD64SBBLcarrymask(v)
+ case OpAMD64SBBQ:
+ return rewriteValueAMD64_OpAMD64SBBQ(v)
+ case OpAMD64SBBQcarrymask:
+ return rewriteValueAMD64_OpAMD64SBBQcarrymask(v)
+ case OpAMD64SBBQconst:
+ return rewriteValueAMD64_OpAMD64SBBQconst(v)
+ case OpAMD64SETA:
+ return rewriteValueAMD64_OpAMD64SETA(v)
+ case OpAMD64SETAE:
+ return rewriteValueAMD64_OpAMD64SETAE(v)
+ case OpAMD64SETAEstore:
+ return rewriteValueAMD64_OpAMD64SETAEstore(v)
+ case OpAMD64SETAstore:
+ return rewriteValueAMD64_OpAMD64SETAstore(v)
+ case OpAMD64SETB:
+ return rewriteValueAMD64_OpAMD64SETB(v)
+ case OpAMD64SETBE:
+ return rewriteValueAMD64_OpAMD64SETBE(v)
+ case OpAMD64SETBEstore:
+ return rewriteValueAMD64_OpAMD64SETBEstore(v)
+ case OpAMD64SETBstore:
+ return rewriteValueAMD64_OpAMD64SETBstore(v)
+ case OpAMD64SETEQ:
+ return rewriteValueAMD64_OpAMD64SETEQ(v)
+ case OpAMD64SETEQstore:
+ return rewriteValueAMD64_OpAMD64SETEQstore(v)
+ case OpAMD64SETG:
+ return rewriteValueAMD64_OpAMD64SETG(v)
+ case OpAMD64SETGE:
+ return rewriteValueAMD64_OpAMD64SETGE(v)
+ case OpAMD64SETGEstore:
+ return rewriteValueAMD64_OpAMD64SETGEstore(v)
+ case OpAMD64SETGstore:
+ return rewriteValueAMD64_OpAMD64SETGstore(v)
+ case OpAMD64SETL:
+ return rewriteValueAMD64_OpAMD64SETL(v)
+ case OpAMD64SETLE:
+ return rewriteValueAMD64_OpAMD64SETLE(v)
+ case OpAMD64SETLEstore:
+ return rewriteValueAMD64_OpAMD64SETLEstore(v)
+ case OpAMD64SETLstore:
+ return rewriteValueAMD64_OpAMD64SETLstore(v)
+ case OpAMD64SETNE:
+ return rewriteValueAMD64_OpAMD64SETNE(v)
+ case OpAMD64SETNEstore:
+ return rewriteValueAMD64_OpAMD64SETNEstore(v)
+ case OpAMD64SHLL:
+ return rewriteValueAMD64_OpAMD64SHLL(v)
+ case OpAMD64SHLLconst:
+ return rewriteValueAMD64_OpAMD64SHLLconst(v)
+ case OpAMD64SHLQ:
+ return rewriteValueAMD64_OpAMD64SHLQ(v)
+ case OpAMD64SHLQconst:
+ return rewriteValueAMD64_OpAMD64SHLQconst(v)
+ case OpAMD64SHRB:
+ return rewriteValueAMD64_OpAMD64SHRB(v)
+ case OpAMD64SHRBconst:
+ return rewriteValueAMD64_OpAMD64SHRBconst(v)
+ case OpAMD64SHRL:
+ return rewriteValueAMD64_OpAMD64SHRL(v)
+ case OpAMD64SHRLconst:
+ return rewriteValueAMD64_OpAMD64SHRLconst(v)
+ case OpAMD64SHRQ:
+ return rewriteValueAMD64_OpAMD64SHRQ(v)
+ case OpAMD64SHRQconst:
+ return rewriteValueAMD64_OpAMD64SHRQconst(v)
+ case OpAMD64SHRW:
+ return rewriteValueAMD64_OpAMD64SHRW(v)
+ case OpAMD64SHRWconst:
+ return rewriteValueAMD64_OpAMD64SHRWconst(v)
+ case OpAMD64SUBL:
+ return rewriteValueAMD64_OpAMD64SUBL(v)
+ case OpAMD64SUBLconst:
+ return rewriteValueAMD64_OpAMD64SUBLconst(v)
+ case OpAMD64SUBLload:
+ return rewriteValueAMD64_OpAMD64SUBLload(v)
+ case OpAMD64SUBLmodify:
+ return rewriteValueAMD64_OpAMD64SUBLmodify(v)
+ case OpAMD64SUBQ:
+ return rewriteValueAMD64_OpAMD64SUBQ(v)
+ case OpAMD64SUBQborrow:
+ return rewriteValueAMD64_OpAMD64SUBQborrow(v)
+ case OpAMD64SUBQconst:
+ return rewriteValueAMD64_OpAMD64SUBQconst(v)
+ case OpAMD64SUBQload:
+ return rewriteValueAMD64_OpAMD64SUBQload(v)
+ case OpAMD64SUBQmodify:
+ return rewriteValueAMD64_OpAMD64SUBQmodify(v)
+ case OpAMD64SUBSD:
+ return rewriteValueAMD64_OpAMD64SUBSD(v)
+ case OpAMD64SUBSDload:
+ return rewriteValueAMD64_OpAMD64SUBSDload(v)
+ case OpAMD64SUBSS:
+ return rewriteValueAMD64_OpAMD64SUBSS(v)
+ case OpAMD64SUBSSload:
+ return rewriteValueAMD64_OpAMD64SUBSSload(v)
+ case OpAMD64TESTB:
+ return rewriteValueAMD64_OpAMD64TESTB(v)
+ case OpAMD64TESTBconst:
+ return rewriteValueAMD64_OpAMD64TESTBconst(v)
+ case OpAMD64TESTL:
+ return rewriteValueAMD64_OpAMD64TESTL(v)
+ case OpAMD64TESTLconst:
+ return rewriteValueAMD64_OpAMD64TESTLconst(v)
+ case OpAMD64TESTQ:
+ return rewriteValueAMD64_OpAMD64TESTQ(v)
+ case OpAMD64TESTQconst:
+ return rewriteValueAMD64_OpAMD64TESTQconst(v)
+ case OpAMD64TESTW:
+ return rewriteValueAMD64_OpAMD64TESTW(v)
+ case OpAMD64TESTWconst:
+ return rewriteValueAMD64_OpAMD64TESTWconst(v)
+ case OpAMD64XADDLlock:
+ return rewriteValueAMD64_OpAMD64XADDLlock(v)
+ case OpAMD64XADDQlock:
+ return rewriteValueAMD64_OpAMD64XADDQlock(v)
+ case OpAMD64XCHGL:
+ return rewriteValueAMD64_OpAMD64XCHGL(v)
+ case OpAMD64XCHGQ:
+ return rewriteValueAMD64_OpAMD64XCHGQ(v)
+ case OpAMD64XORL:
+ return rewriteValueAMD64_OpAMD64XORL(v)
+ case OpAMD64XORLconst:
+ return rewriteValueAMD64_OpAMD64XORLconst(v)
+ case OpAMD64XORLconstmodify:
+ return rewriteValueAMD64_OpAMD64XORLconstmodify(v)
+ case OpAMD64XORLload:
+ return rewriteValueAMD64_OpAMD64XORLload(v)
+ case OpAMD64XORLmodify:
+ return rewriteValueAMD64_OpAMD64XORLmodify(v)
+ case OpAMD64XORQ:
+ return rewriteValueAMD64_OpAMD64XORQ(v)
+ case OpAMD64XORQconst:
+ return rewriteValueAMD64_OpAMD64XORQconst(v)
+ case OpAMD64XORQconstmodify:
+ return rewriteValueAMD64_OpAMD64XORQconstmodify(v)
+ case OpAMD64XORQload:
+ return rewriteValueAMD64_OpAMD64XORQload(v)
+ case OpAMD64XORQmodify:
+ return rewriteValueAMD64_OpAMD64XORQmodify(v)
+ case OpAdd16:
+ v.Op = OpAMD64ADDL
+ return true
+ case OpAdd32:
+ v.Op = OpAMD64ADDL
+ return true
+ case OpAdd32F:
+ v.Op = OpAMD64ADDSS
+ return true
+ case OpAdd64:
+ v.Op = OpAMD64ADDQ
+ return true
+ case OpAdd64F:
+ v.Op = OpAMD64ADDSD
+ return true
+ case OpAdd8:
+ v.Op = OpAMD64ADDL
+ return true
+ case OpAddPtr:
+ v.Op = OpAMD64ADDQ
+ return true
+ case OpAddr:
+ return rewriteValueAMD64_OpAddr(v)
+ case OpAnd16:
+ v.Op = OpAMD64ANDL
+ return true
+ case OpAnd32:
+ v.Op = OpAMD64ANDL
+ return true
+ case OpAnd64:
+ v.Op = OpAMD64ANDQ
+ return true
+ case OpAnd8:
+ v.Op = OpAMD64ANDL
+ return true
+ case OpAndB:
+ v.Op = OpAMD64ANDL
+ return true
+ case OpAtomicAdd32:
+ return rewriteValueAMD64_OpAtomicAdd32(v)
+ case OpAtomicAdd64:
+ return rewriteValueAMD64_OpAtomicAdd64(v)
+ case OpAtomicAnd32:
+ return rewriteValueAMD64_OpAtomicAnd32(v)
+ case OpAtomicAnd8:
+ return rewriteValueAMD64_OpAtomicAnd8(v)
+ case OpAtomicCompareAndSwap32:
+ return rewriteValueAMD64_OpAtomicCompareAndSwap32(v)
+ case OpAtomicCompareAndSwap64:
+ return rewriteValueAMD64_OpAtomicCompareAndSwap64(v)
+ case OpAtomicExchange32:
+ return rewriteValueAMD64_OpAtomicExchange32(v)
+ case OpAtomicExchange64:
+ return rewriteValueAMD64_OpAtomicExchange64(v)
+ case OpAtomicLoad32:
+ return rewriteValueAMD64_OpAtomicLoad32(v)
+ case OpAtomicLoad64:
+ return rewriteValueAMD64_OpAtomicLoad64(v)
+ case OpAtomicLoad8:
+ return rewriteValueAMD64_OpAtomicLoad8(v)
+ case OpAtomicLoadPtr:
+ return rewriteValueAMD64_OpAtomicLoadPtr(v)
+ case OpAtomicOr32:
+ return rewriteValueAMD64_OpAtomicOr32(v)
+ case OpAtomicOr8:
+ return rewriteValueAMD64_OpAtomicOr8(v)
+ case OpAtomicStore32:
+ return rewriteValueAMD64_OpAtomicStore32(v)
+ case OpAtomicStore64:
+ return rewriteValueAMD64_OpAtomicStore64(v)
+ case OpAtomicStore8:
+ return rewriteValueAMD64_OpAtomicStore8(v)
+ case OpAtomicStorePtrNoWB:
+ return rewriteValueAMD64_OpAtomicStorePtrNoWB(v)
+ case OpAvg64u:
+ v.Op = OpAMD64AVGQU
+ return true
+ case OpBitLen16:
+ return rewriteValueAMD64_OpBitLen16(v)
+ case OpBitLen32:
+ return rewriteValueAMD64_OpBitLen32(v)
+ case OpBitLen64:
+ return rewriteValueAMD64_OpBitLen64(v)
+ case OpBitLen8:
+ return rewriteValueAMD64_OpBitLen8(v)
+ case OpBswap32:
+ v.Op = OpAMD64BSWAPL
+ return true
+ case OpBswap64:
+ v.Op = OpAMD64BSWAPQ
+ return true
+ case OpCeil:
+ return rewriteValueAMD64_OpCeil(v)
+ case OpClosureCall:
+ v.Op = OpAMD64CALLclosure
+ return true
+ case OpCom16:
+ v.Op = OpAMD64NOTL
+ return true
+ case OpCom32:
+ v.Op = OpAMD64NOTL
+ return true
+ case OpCom64:
+ v.Op = OpAMD64NOTQ
+ return true
+ case OpCom8:
+ v.Op = OpAMD64NOTL
+ return true
+ case OpCondSelect:
+ return rewriteValueAMD64_OpCondSelect(v)
+ case OpConst16:
+ return rewriteValueAMD64_OpConst16(v)
+ case OpConst32:
+ v.Op = OpAMD64MOVLconst
+ return true
+ case OpConst32F:
+ v.Op = OpAMD64MOVSSconst
+ return true
+ case OpConst64:
+ v.Op = OpAMD64MOVQconst
+ return true
+ case OpConst64F:
+ v.Op = OpAMD64MOVSDconst
+ return true
+ case OpConst8:
+ return rewriteValueAMD64_OpConst8(v)
+ case OpConstBool:
+ return rewriteValueAMD64_OpConstBool(v)
+ case OpConstNil:
+ return rewriteValueAMD64_OpConstNil(v)
+ case OpCtz16:
+ return rewriteValueAMD64_OpCtz16(v)
+ case OpCtz16NonZero:
+ v.Op = OpAMD64BSFL
+ return true
+ case OpCtz32:
+ return rewriteValueAMD64_OpCtz32(v)
+ case OpCtz32NonZero:
+ v.Op = OpAMD64BSFL
+ return true
+ case OpCtz64:
+ return rewriteValueAMD64_OpCtz64(v)
+ case OpCtz64NonZero:
+ return rewriteValueAMD64_OpCtz64NonZero(v)
+ case OpCtz8:
+ return rewriteValueAMD64_OpCtz8(v)
+ case OpCtz8NonZero:
+ v.Op = OpAMD64BSFL
+ return true
+ case OpCvt32Fto32:
+ v.Op = OpAMD64CVTTSS2SL
+ return true
+ case OpCvt32Fto64:
+ v.Op = OpAMD64CVTTSS2SQ
+ return true
+ case OpCvt32Fto64F:
+ v.Op = OpAMD64CVTSS2SD
+ return true
+ case OpCvt32to32F:
+ v.Op = OpAMD64CVTSL2SS
+ return true
+ case OpCvt32to64F:
+ v.Op = OpAMD64CVTSL2SD
+ return true
+ case OpCvt64Fto32:
+ v.Op = OpAMD64CVTTSD2SL
+ return true
+ case OpCvt64Fto32F:
+ v.Op = OpAMD64CVTSD2SS
+ return true
+ case OpCvt64Fto64:
+ v.Op = OpAMD64CVTTSD2SQ
+ return true
+ case OpCvt64to32F:
+ v.Op = OpAMD64CVTSQ2SS
+ return true
+ case OpCvt64to64F:
+ v.Op = OpAMD64CVTSQ2SD
+ return true
+ case OpCvtBoolToUint8:
+ v.Op = OpCopy
+ return true
+ case OpDiv128u:
+ v.Op = OpAMD64DIVQU2
+ return true
+ case OpDiv16:
+ return rewriteValueAMD64_OpDiv16(v)
+ case OpDiv16u:
+ return rewriteValueAMD64_OpDiv16u(v)
+ case OpDiv32:
+ return rewriteValueAMD64_OpDiv32(v)
+ case OpDiv32F:
+ v.Op = OpAMD64DIVSS
+ return true
+ case OpDiv32u:
+ return rewriteValueAMD64_OpDiv32u(v)
+ case OpDiv64:
+ return rewriteValueAMD64_OpDiv64(v)
+ case OpDiv64F:
+ v.Op = OpAMD64DIVSD
+ return true
+ case OpDiv64u:
+ return rewriteValueAMD64_OpDiv64u(v)
+ case OpDiv8:
+ return rewriteValueAMD64_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValueAMD64_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValueAMD64_OpEq16(v)
+ case OpEq32:
+ return rewriteValueAMD64_OpEq32(v)
+ case OpEq32F:
+ return rewriteValueAMD64_OpEq32F(v)
+ case OpEq64:
+ return rewriteValueAMD64_OpEq64(v)
+ case OpEq64F:
+ return rewriteValueAMD64_OpEq64F(v)
+ case OpEq8:
+ return rewriteValueAMD64_OpEq8(v)
+ case OpEqB:
+ return rewriteValueAMD64_OpEqB(v)
+ case OpEqPtr:
+ return rewriteValueAMD64_OpEqPtr(v)
+ case OpFMA:
+ return rewriteValueAMD64_OpFMA(v)
+ case OpFloor:
+ return rewriteValueAMD64_OpFloor(v)
+ case OpGetCallerPC:
+ v.Op = OpAMD64LoweredGetCallerPC
+ return true
+ case OpGetCallerSP:
+ v.Op = OpAMD64LoweredGetCallerSP
+ return true
+ case OpGetClosurePtr:
+ v.Op = OpAMD64LoweredGetClosurePtr
+ return true
+ case OpGetG:
+ v.Op = OpAMD64LoweredGetG
+ return true
+ case OpHasCPUFeature:
+ return rewriteValueAMD64_OpHasCPUFeature(v)
+ case OpHmul32:
+ v.Op = OpAMD64HMULL
+ return true
+ case OpHmul32u:
+ v.Op = OpAMD64HMULLU
+ return true
+ case OpHmul64:
+ v.Op = OpAMD64HMULQ
+ return true
+ case OpHmul64u:
+ v.Op = OpAMD64HMULQU
+ return true
+ case OpInterCall:
+ v.Op = OpAMD64CALLinter
+ return true
+ case OpIsInBounds:
+ return rewriteValueAMD64_OpIsInBounds(v)
+ case OpIsNonNil:
+ return rewriteValueAMD64_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ return rewriteValueAMD64_OpIsSliceInBounds(v)
+ case OpLeq16:
+ return rewriteValueAMD64_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValueAMD64_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValueAMD64_OpLeq32(v)
+ case OpLeq32F:
+ return rewriteValueAMD64_OpLeq32F(v)
+ case OpLeq32U:
+ return rewriteValueAMD64_OpLeq32U(v)
+ case OpLeq64:
+ return rewriteValueAMD64_OpLeq64(v)
+ case OpLeq64F:
+ return rewriteValueAMD64_OpLeq64F(v)
+ case OpLeq64U:
+ return rewriteValueAMD64_OpLeq64U(v)
+ case OpLeq8:
+ return rewriteValueAMD64_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValueAMD64_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValueAMD64_OpLess16(v)
+ case OpLess16U:
+ return rewriteValueAMD64_OpLess16U(v)
+ case OpLess32:
+ return rewriteValueAMD64_OpLess32(v)
+ case OpLess32F:
+ return rewriteValueAMD64_OpLess32F(v)
+ case OpLess32U:
+ return rewriteValueAMD64_OpLess32U(v)
+ case OpLess64:
+ return rewriteValueAMD64_OpLess64(v)
+ case OpLess64F:
+ return rewriteValueAMD64_OpLess64F(v)
+ case OpLess64U:
+ return rewriteValueAMD64_OpLess64U(v)
+ case OpLess8:
+ return rewriteValueAMD64_OpLess8(v)
+ case OpLess8U:
+ return rewriteValueAMD64_OpLess8U(v)
+ case OpLoad:
+ return rewriteValueAMD64_OpLoad(v)
+ case OpLocalAddr:
+ return rewriteValueAMD64_OpLocalAddr(v)
+ case OpLsh16x16:
+ return rewriteValueAMD64_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValueAMD64_OpLsh16x32(v)
+ case OpLsh16x64:
+ return rewriteValueAMD64_OpLsh16x64(v)
+ case OpLsh16x8:
+ return rewriteValueAMD64_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValueAMD64_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValueAMD64_OpLsh32x32(v)
+ case OpLsh32x64:
+ return rewriteValueAMD64_OpLsh32x64(v)
+ case OpLsh32x8:
+ return rewriteValueAMD64_OpLsh32x8(v)
+ case OpLsh64x16:
+ return rewriteValueAMD64_OpLsh64x16(v)
+ case OpLsh64x32:
+ return rewriteValueAMD64_OpLsh64x32(v)
+ case OpLsh64x64:
+ return rewriteValueAMD64_OpLsh64x64(v)
+ case OpLsh64x8:
+ return rewriteValueAMD64_OpLsh64x8(v)
+ case OpLsh8x16:
+ return rewriteValueAMD64_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValueAMD64_OpLsh8x32(v)
+ case OpLsh8x64:
+ return rewriteValueAMD64_OpLsh8x64(v)
+ case OpLsh8x8:
+ return rewriteValueAMD64_OpLsh8x8(v)
+ case OpMod16:
+ return rewriteValueAMD64_OpMod16(v)
+ case OpMod16u:
+ return rewriteValueAMD64_OpMod16u(v)
+ case OpMod32:
+ return rewriteValueAMD64_OpMod32(v)
+ case OpMod32u:
+ return rewriteValueAMD64_OpMod32u(v)
+ case OpMod64:
+ return rewriteValueAMD64_OpMod64(v)
+ case OpMod64u:
+ return rewriteValueAMD64_OpMod64u(v)
+ case OpMod8:
+ return rewriteValueAMD64_OpMod8(v)
+ case OpMod8u:
+ return rewriteValueAMD64_OpMod8u(v)
+ case OpMove:
+ return rewriteValueAMD64_OpMove(v)
+ case OpMul16:
+ v.Op = OpAMD64MULL
+ return true
+ case OpMul32:
+ v.Op = OpAMD64MULL
+ return true
+ case OpMul32F:
+ v.Op = OpAMD64MULSS
+ return true
+ case OpMul64:
+ v.Op = OpAMD64MULQ
+ return true
+ case OpMul64F:
+ v.Op = OpAMD64MULSD
+ return true
+ case OpMul64uhilo:
+ v.Op = OpAMD64MULQU2
+ return true
+ case OpMul8:
+ v.Op = OpAMD64MULL
+ return true
+ case OpNeg16:
+ v.Op = OpAMD64NEGL
+ return true
+ case OpNeg32:
+ v.Op = OpAMD64NEGL
+ return true
+ case OpNeg32F:
+ return rewriteValueAMD64_OpNeg32F(v)
+ case OpNeg64:
+ v.Op = OpAMD64NEGQ
+ return true
+ case OpNeg64F:
+ return rewriteValueAMD64_OpNeg64F(v)
+ case OpNeg8:
+ v.Op = OpAMD64NEGL
+ return true
+ case OpNeq16:
+ return rewriteValueAMD64_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValueAMD64_OpNeq32(v)
+ case OpNeq32F:
+ return rewriteValueAMD64_OpNeq32F(v)
+ case OpNeq64:
+ return rewriteValueAMD64_OpNeq64(v)
+ case OpNeq64F:
+ return rewriteValueAMD64_OpNeq64F(v)
+ case OpNeq8:
+ return rewriteValueAMD64_OpNeq8(v)
+ case OpNeqB:
+ return rewriteValueAMD64_OpNeqB(v)
+ case OpNeqPtr:
+ return rewriteValueAMD64_OpNeqPtr(v)
+ case OpNilCheck:
+ v.Op = OpAMD64LoweredNilCheck
+ return true
+ case OpNot:
+ return rewriteValueAMD64_OpNot(v)
+ case OpOffPtr:
+ return rewriteValueAMD64_OpOffPtr(v)
+ case OpOr16:
+ v.Op = OpAMD64ORL
+ return true
+ case OpOr32:
+ v.Op = OpAMD64ORL
+ return true
+ case OpOr64:
+ v.Op = OpAMD64ORQ
+ return true
+ case OpOr8:
+ v.Op = OpAMD64ORL
+ return true
+ case OpOrB:
+ v.Op = OpAMD64ORL
+ return true
+ case OpPanicBounds:
+ return rewriteValueAMD64_OpPanicBounds(v)
+ case OpPopCount16:
+ return rewriteValueAMD64_OpPopCount16(v)
+ case OpPopCount32:
+ v.Op = OpAMD64POPCNTL
+ return true
+ case OpPopCount64:
+ v.Op = OpAMD64POPCNTQ
+ return true
+ case OpPopCount8:
+ return rewriteValueAMD64_OpPopCount8(v)
+ case OpRotateLeft16:
+ v.Op = OpAMD64ROLW
+ return true
+ case OpRotateLeft32:
+ v.Op = OpAMD64ROLL
+ return true
+ case OpRotateLeft64:
+ v.Op = OpAMD64ROLQ
+ return true
+ case OpRotateLeft8:
+ v.Op = OpAMD64ROLB
+ return true
+ case OpRound32F:
+ v.Op = OpCopy
+ return true
+ case OpRound64F:
+ v.Op = OpCopy
+ return true
+ case OpRoundToEven:
+ return rewriteValueAMD64_OpRoundToEven(v)
+ case OpRsh16Ux16:
+ return rewriteValueAMD64_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValueAMD64_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValueAMD64_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValueAMD64_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValueAMD64_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValueAMD64_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValueAMD64_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValueAMD64_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValueAMD64_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValueAMD64_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValueAMD64_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValueAMD64_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValueAMD64_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValueAMD64_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValueAMD64_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValueAMD64_OpRsh32x8(v)
+ case OpRsh64Ux16:
+ return rewriteValueAMD64_OpRsh64Ux16(v)
+ case OpRsh64Ux32:
+ return rewriteValueAMD64_OpRsh64Ux32(v)
+ case OpRsh64Ux64:
+ return rewriteValueAMD64_OpRsh64Ux64(v)
+ case OpRsh64Ux8:
+ return rewriteValueAMD64_OpRsh64Ux8(v)
+ case OpRsh64x16:
+ return rewriteValueAMD64_OpRsh64x16(v)
+ case OpRsh64x32:
+ return rewriteValueAMD64_OpRsh64x32(v)
+ case OpRsh64x64:
+ return rewriteValueAMD64_OpRsh64x64(v)
+ case OpRsh64x8:
+ return rewriteValueAMD64_OpRsh64x8(v)
+ case OpRsh8Ux16:
+ return rewriteValueAMD64_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValueAMD64_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValueAMD64_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValueAMD64_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValueAMD64_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValueAMD64_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValueAMD64_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValueAMD64_OpRsh8x8(v)
+ case OpSelect0:
+ return rewriteValueAMD64_OpSelect0(v)
+ case OpSelect1:
+ return rewriteValueAMD64_OpSelect1(v)
+ case OpSignExt16to32:
+ v.Op = OpAMD64MOVWQSX
+ return true
+ case OpSignExt16to64:
+ v.Op = OpAMD64MOVWQSX
+ return true
+ case OpSignExt32to64:
+ v.Op = OpAMD64MOVLQSX
+ return true
+ case OpSignExt8to16:
+ v.Op = OpAMD64MOVBQSX
+ return true
+ case OpSignExt8to32:
+ v.Op = OpAMD64MOVBQSX
+ return true
+ case OpSignExt8to64:
+ v.Op = OpAMD64MOVBQSX
+ return true
+ case OpSlicemask:
+ return rewriteValueAMD64_OpSlicemask(v)
+ case OpSpectreIndex:
+ return rewriteValueAMD64_OpSpectreIndex(v)
+ case OpSpectreSliceIndex:
+ return rewriteValueAMD64_OpSpectreSliceIndex(v)
+ case OpSqrt:
+ v.Op = OpAMD64SQRTSD
+ return true
+ case OpStaticCall:
+ v.Op = OpAMD64CALLstatic
+ return true
+ case OpStore:
+ return rewriteValueAMD64_OpStore(v)
+ case OpSub16:
+ v.Op = OpAMD64SUBL
+ return true
+ case OpSub32:
+ v.Op = OpAMD64SUBL
+ return true
+ case OpSub32F:
+ v.Op = OpAMD64SUBSS
+ return true
+ case OpSub64:
+ v.Op = OpAMD64SUBQ
+ return true
+ case OpSub64F:
+ v.Op = OpAMD64SUBSD
+ return true
+ case OpSub8:
+ v.Op = OpAMD64SUBL
+ return true
+ case OpSubPtr:
+ v.Op = OpAMD64SUBQ
+ return true
+ case OpTrunc:
+ return rewriteValueAMD64_OpTrunc(v)
+ case OpTrunc16to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to32:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to8:
+ v.Op = OpCopy
+ return true
+ case OpWB:
+ v.Op = OpAMD64LoweredWB
+ return true
+ case OpXor16:
+ v.Op = OpAMD64XORL
+ return true
+ case OpXor32:
+ v.Op = OpAMD64XORL
+ return true
+ case OpXor64:
+ v.Op = OpAMD64XORQ
+ return true
+ case OpXor8:
+ v.Op = OpAMD64XORL
+ return true
+ case OpZero:
+ return rewriteValueAMD64_OpZero(v)
+ case OpZeroExt16to32:
+ v.Op = OpAMD64MOVWQZX
+ return true
+ case OpZeroExt16to64:
+ v.Op = OpAMD64MOVWQZX
+ return true
+ case OpZeroExt32to64:
+ v.Op = OpAMD64MOVLQZX
+ return true
+ case OpZeroExt8to16:
+ v.Op = OpAMD64MOVBQZX
+ return true
+ case OpZeroExt8to32:
+ v.Op = OpAMD64MOVBQZX
+ return true
+ case OpZeroExt8to64:
+ v.Op = OpAMD64MOVBQZX
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADCQ(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADCQ x (MOVQconst [c]) carry)
+ // cond: is32Bit(c)
+ // result: (ADCQconst x [int32(c)] carry)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ carry := v_2
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpAMD64ADCQconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(x, carry)
+ return true
+ }
+ break
+ }
+ // match: (ADCQ x y (FlagEQ))
+ // result: (ADDQcarry x y)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64ADDQcarry)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADCQconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADCQconst x [c] (FlagEQ))
+ // result: (ADDQconstcarry x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64ADDQconstcarry)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDL x (MOVLconst [c]))
+ // result: (ADDLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ADDLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDL (SHLLconst x [c]) (SHRLconst x [d]))
+ // cond: d==32-c
+ // result: (ROLLconst x [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRLconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 32-c) {
+ continue
+ }
+ v.reset(OpAMD64ROLLconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDL <t> (SHLLconst x [c]) (SHRWconst x [d]))
+ // cond: d==16-c && c < 16 && t.Size() == 2
+ // result: (ROLWconst x [c])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRWconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 16-c && c < 16 && t.Size() == 2) {
+ continue
+ }
+ v.reset(OpAMD64ROLWconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDL <t> (SHLLconst x [c]) (SHRBconst x [d]))
+ // cond: d==8-c && c < 8 && t.Size() == 1
+ // result: (ROLBconst x [c])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRBconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 8-c && c < 8 && t.Size() == 1) {
+ continue
+ }
+ v.reset(OpAMD64ROLBconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (SHLLconst [3] y))
+ // result: (LEAL8 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 3 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAL8)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (SHLLconst [2] y))
+ // result: (LEAL4 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 2 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAL4)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (SHLLconst [1] y))
+ // result: (LEAL2 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 1 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAL2)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (ADDL y y))
+ // result: (LEAL2 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64ADDL {
+ continue
+ }
+ y := v_1.Args[1]
+ if y != v_1.Args[0] {
+ continue
+ }
+ v.reset(OpAMD64LEAL2)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (ADDL x y))
+ // result: (LEAL2 y x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64ADDL {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(OpAMD64LEAL2)
+ v.AddArg2(y, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ADDL (ADDLconst [c] x) y)
+ // result: (LEAL1 [c] x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64ADDLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpAMD64LEAL1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (LEAL [c] {s} y))
+ // cond: x.Op != OpSB && y.Op != OpSB
+ // result: (LEAL1 [c] {s} x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64LEAL {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ s := auxToSym(v_1.Aux)
+ y := v_1.Args[0]
+ if !(x.Op != OpSB && y.Op != OpSB) {
+ continue
+ }
+ v.reset(OpAMD64LEAL1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x (NEGL y))
+ // result: (SUBL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64SUBL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ADDLload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVLload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64ADDLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDLconst [c] (ADDL x y))
+ // result: (LEAL1 [c] x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ADDL {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpAMD64LEAL1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDLconst [c] (SHLLconst [1] x))
+ // result: (LEAL1 [c] x x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64SHLLconst || auxIntToInt8(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64LEAL1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (ADDLconst [c] (LEAL [d] {s} x))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL [c+d] {s} x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAL)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDLconst [c] (LEAL1 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL1 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64LEAL1 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAL1)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDLconst [c] (LEAL2 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL2 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64LEAL2 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAL2)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDLconst [c] (LEAL4 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL4 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64LEAL4 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAL4)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDLconst [c] (LEAL8 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL8 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64LEAL8 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAL8)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDLconst [c] x)
+ // cond: c==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ADDLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [c+d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ return true
+ }
+ // match: (ADDLconst [c] (ADDLconst [d] x))
+ // result: (ADDLconst [c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ADDLconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDLconst [off] x:(SP))
+ // result: (LEAL [off] x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpSP {
+ break
+ }
+ v.reset(OpAMD64LEAL)
+ v.AuxInt = int32ToAuxInt(off)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDLconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (ADDLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64ADDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (ADDLconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (ADDLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ADDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ADDLload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ADDLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ADDLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDLload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ADDLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ADDLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDLload x [off] {sym} ptr (MOVSSstore [off] {sym} ptr y _))
+ // result: (ADDL x (MOVLf2i y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVSSstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64ADDL)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVLf2i, typ.UInt32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ADDLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ADDLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (ADDLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ADDLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ADDLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDQ x (MOVQconst [c]))
+ // cond: is32Bit(c)
+ // result: (ADDQconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpAMD64ADDQconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDQ x (MOVLconst [c]))
+ // result: (ADDQconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ADDQconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDQ (SHLQconst x [c]) (SHRQconst x [d]))
+ // cond: d==64-c
+ // result: (ROLQconst x [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRQconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 64-c) {
+ continue
+ }
+ v.reset(OpAMD64ROLQconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDQ x (SHLQconst [3] y))
+ // result: (LEAQ8 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 3 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAQ8)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDQ x (SHLQconst [2] y))
+ // result: (LEAQ4 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 2 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAQ4)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDQ x (SHLQconst [1] y))
+ // result: (LEAQ2 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 1 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAQ2)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDQ x (ADDQ y y))
+ // result: (LEAQ2 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64ADDQ {
+ continue
+ }
+ y := v_1.Args[1]
+ if y != v_1.Args[0] {
+ continue
+ }
+ v.reset(OpAMD64LEAQ2)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDQ x (ADDQ x y))
+ // result: (LEAQ2 y x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64ADDQ {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(OpAMD64LEAQ2)
+ v.AddArg2(y, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ADDQ (ADDQconst [c] x) y)
+ // result: (LEAQ1 [c] x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64ADDQconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpAMD64LEAQ1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDQ x (LEAQ [c] {s} y))
+ // cond: x.Op != OpSB && y.Op != OpSB
+ // result: (LEAQ1 [c] {s} x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ s := auxToSym(v_1.Aux)
+ y := v_1.Args[0]
+ if !(x.Op != OpSB && y.Op != OpSB) {
+ continue
+ }
+ v.reset(OpAMD64LEAQ1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDQ x (NEGQ y))
+ // result: (SUBQ x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64SUBQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDQ x l:(MOVQload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ADDQload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVQload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64ADDQload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDQcarry(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDQcarry x (MOVQconst [c]))
+ // cond: is32Bit(c)
+ // result: (ADDQconstcarry x [int32(c)])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpAMD64ADDQconstcarry)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDQconst [c] (ADDQ x y))
+ // result: (LEAQ1 [c] x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ADDQ {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpAMD64LEAQ1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDQconst [c] (SHLQconst [1] x))
+ // result: (LEAQ1 [c] x x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64SHLQconst || auxIntToInt8(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64LEAQ1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (ADDQconst [c] (LEAQ [d] {s} x))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAQ [c+d] {s} x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAQ)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDQconst [c] (LEAQ1 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAQ1 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64LEAQ1 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAQ1)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDQconst [c] (LEAQ2 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAQ2 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64LEAQ2 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAQ2)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDQconst [c] (LEAQ4 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAQ4 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64LEAQ4 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAQ4)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDQconst [c] (LEAQ8 [d] {s} x y))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAQ8 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64LEAQ8 {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAQ8)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDQconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ADDQconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [int64(c)+d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(c) + d)
+ return true
+ }
+ // match: (ADDQconst [c] (ADDQconst [d] x))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (ADDQconst [c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64ADDQconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDQconst [off] x:(SP))
+ // result: (LEAQ [off] x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpSP {
+ break
+ }
+ v.reset(OpAMD64LEAQ)
+ v.AuxInt = int32ToAuxInt(off)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDQconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDQconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (ADDQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64ADDQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (ADDQconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (ADDQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ADDQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDQload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ADDQload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ADDQload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ADDQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDQload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ADDQload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ADDQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDQload x [off] {sym} ptr (MOVSDstore [off] {sym} ptr y _))
+ // result: (ADDQ x (MOVQf2i y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVSDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64ADDQ)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVQf2i, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDQmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ADDQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ADDQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (ADDQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ADDQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ADDQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDSD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDSD x l:(MOVSDload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ADDSDload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVSDload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64ADDSDload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDSDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ADDSDload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ADDSDload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ADDSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDSDload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ADDSDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ADDSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDSDload x [off] {sym} ptr (MOVQstore [off] {sym} ptr y _))
+ // result: (ADDSD x (MOVQi2f y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVQstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64ADDSD)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVQi2f, typ.Float64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDSS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDSS x l:(MOVSSload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ADDSSload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVSSload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64ADDSSload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ADDSSload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ADDSSload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ADDSSload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ADDSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDSSload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ADDSSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ADDSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ADDSSload x [off] {sym} ptr (MOVLstore [off] {sym} ptr y _))
+ // result: (ADDSS x (MOVLi2f y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVLstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64ADDSS)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVLi2f, typ.Float32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ANDL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ANDL (NOTL (SHLL (MOVLconst [1]) y)) x)
+ // result: (BTRL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64NOTL {
+ continue
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SHLL {
+ continue
+ }
+ y := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_0_0_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpAMD64BTRL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ANDL (MOVLconst [c]) x)
+ // cond: isUint32PowerOfTwo(int64(^c)) && uint64(^c) >= 128
+ // result: (BTRLconst [int8(log32(^c))] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ if !(isUint32PowerOfTwo(int64(^c)) && uint64(^c) >= 128) {
+ continue
+ }
+ v.reset(OpAMD64BTRLconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(^c)))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ANDL x (MOVLconst [c]))
+ // result: (ANDLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ANDL x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ANDLload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVLload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64ANDLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ANDLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ANDLconst [c] x)
+ // cond: isUint32PowerOfTwo(int64(^c)) && uint64(^c) >= 128
+ // result: (BTRLconst [int8(log32(^c))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isUint32PowerOfTwo(int64(^c)) && uint64(^c) >= 128) {
+ break
+ }
+ v.reset(OpAMD64BTRLconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(^c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDLconst [c] (ANDLconst [d] x))
+ // result: (ANDLconst [c & d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDLconst [c] (BTRLconst [d] x))
+ // result: (ANDLconst [c &^ (1<<uint32(d))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64BTRLconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(c &^ (1 << uint32(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDLconst [ 0xFF] x)
+ // result: (MOVBQZX x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0xFF {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64MOVBQZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDLconst [0xFFFF] x)
+ // result: (MOVWQZX x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0xFFFF {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64MOVWQZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDLconst [c] _)
+ // cond: c==0
+ // result: (MOVLconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if !(c == 0) {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (ANDLconst [c] x)
+ // cond: c==-1
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c == -1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [c&d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(c & d)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ANDLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ANDLconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (ANDLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64ANDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (ANDLconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (ANDLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ANDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ANDLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ANDLload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ANDLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ANDLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ANDLload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ANDLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ANDLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ANDLload x [off] {sym} ptr (MOVSSstore [off] {sym} ptr y _))
+ // result: (ANDL x (MOVLf2i y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVSSstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVLf2i, typ.UInt32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ANDLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDLmodify [off] {sym} ptr (NOTL s:(SHLL (MOVLconst [1]) <t> x)) mem)
+ // result: (BTRLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64NOTL {
+ break
+ }
+ s := v_1.Args[0]
+ if s.Op != OpAMD64SHLL {
+ break
+ }
+ t := s.Type
+ x := s.Args[1]
+ s_0 := s.Args[0]
+ if s_0.Op != OpAMD64MOVLconst || auxIntToInt32(s_0.AuxInt) != 1 {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64BTRLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64ANDLconst, t)
+ v0.AuxInt = int32ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (ANDLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ANDLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ANDLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (ANDLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ANDLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ANDLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ANDQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ANDQ (NOTQ (SHLQ (MOVQconst [1]) y)) x)
+ // result: (BTRQ x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64NOTQ {
+ continue
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ y := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_0_0_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpAMD64BTRQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ANDQ (MOVQconst [c]) x)
+ // cond: isUint64PowerOfTwo(^c) && uint64(^c) >= 128
+ // result: (BTRQconst [int8(log64(^c))] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(isUint64PowerOfTwo(^c) && uint64(^c) >= 128) {
+ continue
+ }
+ v.reset(OpAMD64BTRQconst)
+ v.AuxInt = int8ToAuxInt(int8(log64(^c)))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ANDQ x (MOVQconst [c]))
+ // cond: is32Bit(c)
+ // result: (ANDQconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpAMD64ANDQconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ANDQ x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDQ x l:(MOVQload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ANDQload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVQload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64ANDQload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ANDQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ANDQconst [c] x)
+ // cond: isUint64PowerOfTwo(int64(^c)) && uint64(^c) >= 128
+ // result: (BTRQconst [int8(log32(^c))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isUint64PowerOfTwo(int64(^c)) && uint64(^c) >= 128) {
+ break
+ }
+ v.reset(OpAMD64BTRQconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(^c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDQconst [c] (ANDQconst [d] x))
+ // result: (ANDQconst [c & d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ANDQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDQconst)
+ v.AuxInt = int32ToAuxInt(c & d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDQconst [c] (BTRQconst [d] x))
+ // cond: is32Bit(int64(c) &^ (1<<uint32(d)))
+ // result: (ANDQconst [c &^ (1<<uint32(d))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64BTRQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) &^ (1 << uint32(d)))) {
+ break
+ }
+ v.reset(OpAMD64ANDQconst)
+ v.AuxInt = int32ToAuxInt(c &^ (1 << uint32(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDQconst [ 0xFF] x)
+ // result: (MOVBQZX x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0xFF {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64MOVBQZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDQconst [0xFFFF] x)
+ // result: (MOVWQZX x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0xFFFF {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64MOVWQZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDQconst [0] _)
+ // result: (MOVQconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ANDQconst [-1] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDQconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [int64(c)&d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(c) & d)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ANDQconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ANDQconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (ANDQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64ANDQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (ANDQconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (ANDQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ANDQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ANDQload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ANDQload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ANDQload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ANDQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ANDQload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ANDQload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ANDQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ANDQload x [off] {sym} ptr (MOVSDstore [off] {sym} ptr y _))
+ // result: (ANDQ x (MOVQf2i y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVSDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64ANDQ)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVQf2i, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ANDQmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDQmodify [off] {sym} ptr (NOTQ s:(SHLQ (MOVQconst [1]) <t> x)) mem)
+ // result: (BTRQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64NOTQ {
+ break
+ }
+ s := v_1.Args[0]
+ if s.Op != OpAMD64SHLQ {
+ break
+ }
+ t := s.Type
+ x := s.Args[1]
+ s_0 := s.Args[0]
+ if s_0.Op != OpAMD64MOVQconst || auxIntToInt64(s_0.AuxInt) != 1 {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64BTRQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64ANDQconst, t)
+ v0.AuxInt = int32ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (ANDQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ANDQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ANDQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (ANDQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ANDQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ANDQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BSFQ(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (BSFQ (ORQconst <t> [1<<8] (MOVBQZX x)))
+ // result: (BSFQ (ORQconst <t> [1<<8] x))
+ for {
+ if v_0.Op != OpAMD64ORQconst {
+ break
+ }
+ t := v_0.Type
+ if auxIntToInt32(v_0.AuxInt) != 1<<8 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64MOVBQZX {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpAMD64BSFQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64ORQconst, t)
+ v0.AuxInt = int32ToAuxInt(1 << 8)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (BSFQ (ORQconst <t> [1<<16] (MOVWQZX x)))
+ // result: (BSFQ (ORQconst <t> [1<<16] x))
+ for {
+ if v_0.Op != OpAMD64ORQconst {
+ break
+ }
+ t := v_0.Type
+ if auxIntToInt32(v_0.AuxInt) != 1<<16 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64MOVWQZX {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpAMD64BSFQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64ORQconst, t)
+ v0.AuxInt = int32ToAuxInt(1 << 16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BTCLconst [c] (XORLconst [d] x))
+ // result: (XORLconst [d ^ 1<<uint32(c)] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64XORLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = int32ToAuxInt(d ^ 1<<uint32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTCLconst [c] (BTCLconst [d] x))
+ // result: (XORLconst [1<<uint32(c) | 1<<uint32(d)] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTCLconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = int32ToAuxInt(1<<uint32(c) | 1<<uint32(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTCLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [d^(1<<uint32(c))])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(d ^ (1 << uint32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTCLconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (BTCLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTCLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (BTCLconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (BTCLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTCLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTCLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (BTCLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64BTCLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (BTCLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (BTCLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTCLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BTCQconst [c] (XORQconst [d] x))
+ // cond: is32Bit(int64(d) ^ 1<<uint32(c))
+ // result: (XORQconst [d ^ 1<<uint32(c)] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64XORQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(d) ^ 1<<uint32(c))) {
+ break
+ }
+ v.reset(OpAMD64XORQconst)
+ v.AuxInt = int32ToAuxInt(d ^ 1<<uint32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTCQconst [c] (BTCQconst [d] x))
+ // cond: is32Bit(1<<uint32(c) ^ 1<<uint32(d))
+ // result: (XORQconst [1<<uint32(c) ^ 1<<uint32(d)] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTCQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(1<<uint32(c) ^ 1<<uint32(d))) {
+ break
+ }
+ v.reset(OpAMD64XORQconst)
+ v.AuxInt = int32ToAuxInt(1<<uint32(c) ^ 1<<uint32(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTCQconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [d^(1<<uint32(c))])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(d ^ (1 << uint32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCQconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTCQconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (BTCQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTCQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (BTCQconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (BTCQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTCQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCQmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTCQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (BTCQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64BTCQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (BTCQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (BTCQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTCQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BTLconst [c] (SHRQconst [d] x))
+ // cond: (c+d)<64
+ // result: (BTQconst [c+d] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64SHRQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !((c + d) < 64) {
+ break
+ }
+ v.reset(OpAMD64BTQconst)
+ v.AuxInt = int8ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTLconst [c] (SHLQconst [d] x))
+ // cond: c>d
+ // result: (BTLconst [c-d] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64SHLQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c > d) {
+ break
+ }
+ v.reset(OpAMD64BTLconst)
+ v.AuxInt = int8ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTLconst [0] s:(SHRQ x y))
+ // result: (BTQ y x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ s := v_0
+ if s.Op != OpAMD64SHRQ {
+ break
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ v.reset(OpAMD64BTQ)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (BTLconst [c] (SHRLconst [d] x))
+ // cond: (c+d)<32
+ // result: (BTLconst [c+d] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64SHRLconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !((c + d) < 32) {
+ break
+ }
+ v.reset(OpAMD64BTLconst)
+ v.AuxInt = int8ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTLconst [c] (SHLLconst [d] x))
+ // cond: c>d
+ // result: (BTLconst [c-d] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64SHLLconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c > d) {
+ break
+ }
+ v.reset(OpAMD64BTLconst)
+ v.AuxInt = int8ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTLconst [0] s:(SHRL x y))
+ // result: (BTL y x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ s := v_0
+ if s.Op != OpAMD64SHRL {
+ break
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ v.reset(OpAMD64BTL)
+ v.AddArg2(y, x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BTQconst [c] (SHRQconst [d] x))
+ // cond: (c+d)<64
+ // result: (BTQconst [c+d] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64SHRQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !((c + d) < 64) {
+ break
+ }
+ v.reset(OpAMD64BTQconst)
+ v.AuxInt = int8ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTQconst [c] (SHLQconst [d] x))
+ // cond: c>d
+ // result: (BTQconst [c-d] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64SHLQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c > d) {
+ break
+ }
+ v.reset(OpAMD64BTQconst)
+ v.AuxInt = int8ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTQconst [0] s:(SHRQ x y))
+ // result: (BTQ y x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ s := v_0
+ if s.Op != OpAMD64SHRQ {
+ break
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ v.reset(OpAMD64BTQ)
+ v.AddArg2(y, x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTRLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BTRLconst [c] (BTSLconst [c] x))
+ // result: (BTRLconst [c] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTSLconst || auxIntToInt8(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTRLconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRLconst [c] (BTCLconst [c] x))
+ // result: (BTRLconst [c] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTCLconst || auxIntToInt8(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTRLconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRLconst [c] (ANDLconst [d] x))
+ // result: (ANDLconst [d &^ (1<<uint32(c))] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(d &^ (1 << uint32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRLconst [c] (BTRLconst [d] x))
+ // result: (ANDLconst [^(1<<uint32(c) | 1<<uint32(d))] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTRLconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(^(1<<uint32(c) | 1<<uint32(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [d&^(1<<uint32(c))])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(d &^ (1 << uint32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTRLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTRLconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (BTRLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTRLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (BTRLconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (BTRLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTRLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTRLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTRLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (BTRLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64BTRLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (BTRLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (BTRLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTRLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTRQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BTRQconst [c] (BTSQconst [c] x))
+ // result: (BTRQconst [c] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTSQconst || auxIntToInt8(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTRQconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRQconst [c] (BTCQconst [c] x))
+ // result: (BTRQconst [c] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTCQconst || auxIntToInt8(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTRQconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRQconst [c] (ANDQconst [d] x))
+ // cond: is32Bit(int64(d) &^ (1<<uint32(c)))
+ // result: (ANDQconst [d &^ (1<<uint32(c))] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64ANDQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(d) &^ (1 << uint32(c)))) {
+ break
+ }
+ v.reset(OpAMD64ANDQconst)
+ v.AuxInt = int32ToAuxInt(d &^ (1 << uint32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRQconst [c] (BTRQconst [d] x))
+ // cond: is32Bit(^(1<<uint32(c) | 1<<uint32(d)))
+ // result: (ANDQconst [^(1<<uint32(c) | 1<<uint32(d))] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTRQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(^(1<<uint32(c) | 1<<uint32(d)))) {
+ break
+ }
+ v.reset(OpAMD64ANDQconst)
+ v.AuxInt = int32ToAuxInt(^(1<<uint32(c) | 1<<uint32(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRQconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [d&^(1<<uint32(c))])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(d &^ (1 << uint32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTRQconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTRQconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (BTRQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTRQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (BTRQconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (BTRQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTRQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTRQmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTRQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (BTRQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64BTRQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (BTRQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (BTRQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTRQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTSLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BTSLconst [c] (BTRLconst [c] x))
+ // result: (BTSLconst [c] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTRLconst || auxIntToInt8(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTSLconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSLconst [c] (BTCLconst [c] x))
+ // result: (BTSLconst [c] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTCLconst || auxIntToInt8(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTSLconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSLconst [c] (ORLconst [d] x))
+ // result: (ORLconst [d | 1<<uint32(c)] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64ORLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORLconst)
+ v.AuxInt = int32ToAuxInt(d | 1<<uint32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSLconst [c] (BTSLconst [d] x))
+ // result: (ORLconst [1<<uint32(c) | 1<<uint32(d)] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTSLconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORLconst)
+ v.AuxInt = int32ToAuxInt(1<<uint32(c) | 1<<uint32(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [d|(1<<uint32(c))])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(d | (1 << uint32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTSLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTSLconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (BTSLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTSLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (BTSLconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (BTSLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTSLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTSLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTSLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (BTSLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64BTSLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (BTSLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (BTSLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTSLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTSQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BTSQconst [c] (BTRQconst [c] x))
+ // result: (BTSQconst [c] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTRQconst || auxIntToInt8(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTSQconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSQconst [c] (BTCQconst [c] x))
+ // result: (BTSQconst [c] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTCQconst || auxIntToInt8(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTSQconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSQconst [c] (ORQconst [d] x))
+ // cond: is32Bit(int64(d) | 1<<uint32(c))
+ // result: (ORQconst [d | 1<<uint32(c)] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64ORQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(d) | 1<<uint32(c))) {
+ break
+ }
+ v.reset(OpAMD64ORQconst)
+ v.AuxInt = int32ToAuxInt(d | 1<<uint32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSQconst [c] (BTSQconst [d] x))
+ // cond: is32Bit(1<<uint32(c) | 1<<uint32(d))
+ // result: (ORQconst [1<<uint32(c) | 1<<uint32(d)] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64BTSQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(1<<uint32(c) | 1<<uint32(d))) {
+ break
+ }
+ v.reset(OpAMD64ORQconst)
+ v.AuxInt = int32ToAuxInt(1<<uint32(c) | 1<<uint32(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSQconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [d|(1<<uint32(c))])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(d | (1 << uint32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTSQconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTSQconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (BTSQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTSQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (BTSQconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (BTSQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTSQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTSQmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BTSQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (BTSQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64BTSQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (BTSQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (BTSQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTSQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVLCC(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVLCC x y (InvertFlags cond))
+ // result: (CMOVLLS x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVLLS)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVLCC _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLCC _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLCC y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLCC y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLCC _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVLCS(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVLCS x y (InvertFlags cond))
+ // result: (CMOVLHI x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVLHI)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVLCS y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLCS y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLCS _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLCS _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLCS y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVLEQ(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVLEQ x y (InvertFlags cond))
+ // result: (CMOVLEQ x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVLEQ)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVLEQ _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLEQ y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLEQ y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLEQ y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLEQ y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVLGE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVLGE x y (InvertFlags cond))
+ // result: (CMOVLLE x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVLLE)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVLGE _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLGE _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLGE _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLGE y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLGE y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVLGT(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVLGT x y (InvertFlags cond))
+ // result: (CMOVLLT x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVLLT)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVLGT y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLGT _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLGT _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLGT y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLGT y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVLHI(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVLHI x y (InvertFlags cond))
+ // result: (CMOVLCS x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVLCS)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVLHI y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLHI _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLHI y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLHI y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLHI _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVLLE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVLLE x y (InvertFlags cond))
+ // result: (CMOVLGE x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVLGE)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVLLE _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLLE y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLLE y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLLE _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLLE _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVLLS(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVLLS x y (InvertFlags cond))
+ // result: (CMOVLCC x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVLCC)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVLLS _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLLS y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLLS _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLLS _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLLS y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVLLT(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVLLT x y (InvertFlags cond))
+ // result: (CMOVLGT x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVLGT)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVLLT y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLLT y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLLT y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLLT _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLLT _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVLNE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVLNE x y (InvertFlags cond))
+ // result: (CMOVLNE x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVLNE)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVLNE y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVLNE _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLNE _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLNE _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVLNE _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVQCC(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVQCC x y (InvertFlags cond))
+ // result: (CMOVQLS x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVQLS)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVQCC _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQCC _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQCC y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQCC y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQCC _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVQCS(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVQCS x y (InvertFlags cond))
+ // result: (CMOVQHI x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVQHI)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVQCS y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQCS y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQCS _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQCS _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQCS y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVQEQ(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVQEQ x y (InvertFlags cond))
+ // result: (CMOVQEQ x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVQEQ)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVQEQ _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQEQ y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQEQ y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQEQ y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQEQ y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQEQ x _ (Select1 (BSFQ (ORQconst [c] _))))
+ // cond: c != 0
+ // result: x
+ for {
+ x := v_0
+ if v_2.Op != OpSelect1 {
+ break
+ }
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpAMD64BSFQ {
+ break
+ }
+ v_2_0_0 := v_2_0.Args[0]
+ if v_2_0_0.Op != OpAMD64ORQconst {
+ break
+ }
+ c := auxIntToInt32(v_2_0_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVQGE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVQGE x y (InvertFlags cond))
+ // result: (CMOVQLE x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVQLE)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVQGE _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQGE _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQGE _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQGE y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQGE y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVQGT(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVQGT x y (InvertFlags cond))
+ // result: (CMOVQLT x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVQLT)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVQGT y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQGT _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQGT _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQGT y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQGT y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVQHI(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVQHI x y (InvertFlags cond))
+ // result: (CMOVQCS x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVQCS)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVQHI y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQHI _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQHI y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQHI y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQHI _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVQLE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVQLE x y (InvertFlags cond))
+ // result: (CMOVQGE x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVQGE)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVQLE _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQLE y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQLE y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQLE _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQLE _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVQLS(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVQLS x y (InvertFlags cond))
+ // result: (CMOVQCC x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVQCC)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVQLS _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQLS y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQLS _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQLS _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQLS y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVQLT(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVQLT x y (InvertFlags cond))
+ // result: (CMOVQGT x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVQGT)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVQLT y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQLT y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQLT y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQLT _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQLT _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVQNE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVQNE x y (InvertFlags cond))
+ // result: (CMOVQNE x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVQNE)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVQNE y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVQNE _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQNE _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQNE _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVQNE _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVWCC(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWCC x y (InvertFlags cond))
+ // result: (CMOVWLS x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVWLS)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVWCC _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWCC _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWCC y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWCC y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWCC _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVWCS(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWCS x y (InvertFlags cond))
+ // result: (CMOVWHI x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVWHI)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVWCS y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWCS y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWCS _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWCS _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWCS y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVWEQ(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWEQ x y (InvertFlags cond))
+ // result: (CMOVWEQ x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVWEQ)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVWEQ _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWEQ y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWEQ y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWEQ y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWEQ y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVWGE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWGE x y (InvertFlags cond))
+ // result: (CMOVWLE x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVWLE)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVWGE _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWGE _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWGE _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWGE y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWGE y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVWGT(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWGT x y (InvertFlags cond))
+ // result: (CMOVWLT x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVWLT)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVWGT y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWGT _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWGT _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWGT y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWGT y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVWHI(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWHI x y (InvertFlags cond))
+ // result: (CMOVWCS x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVWCS)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVWHI y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWHI _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWHI y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWHI y _ (FlagLT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWHI _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVWLE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWLE x y (InvertFlags cond))
+ // result: (CMOVWGE x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVWGE)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVWLE _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWLE y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWLE y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWLE _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWLE _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVWLS(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWLS x y (InvertFlags cond))
+ // result: (CMOVWCC x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVWCC)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVWLS _ x (FlagEQ))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWLS y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWLS _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWLS _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWLS y _ (FlagLT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVWLT(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWLT x y (InvertFlags cond))
+ // result: (CMOVWGT x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVWGT)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVWLT y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWLT y _ (FlagGT_UGT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWLT y _ (FlagGT_ULT))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWLT _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWLT _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMOVWNE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWNE x y (InvertFlags cond))
+ // result: (CMOVWNE x y cond)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64InvertFlags {
+ break
+ }
+ cond := v_2.Args[0]
+ v.reset(OpAMD64CMOVWNE)
+ v.AddArg3(x, y, cond)
+ return true
+ }
+ // match: (CMOVWNE y _ (FlagEQ))
+ // result: y
+ for {
+ y := v_0
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CMOVWNE _ x (FlagGT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWNE _ x (FlagGT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWNE _ x (FlagLT_ULT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWNE _ x (FlagLT_UGT))
+ // result: x
+ for {
+ x := v_1
+ if v_2.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPB x (MOVLconst [c]))
+ // result: (CMPBconst x [int8(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64CMPBconst)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPB (MOVLconst [c]) x)
+ // result: (InvertFlags (CMPBconst x [int8(c)]))
+ for {
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPB x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPB y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPB, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPB l:(MOVBload {sym} [off] ptr mem) x)
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (CMPBload {sym} [off] ptr x mem)
+ for {
+ l := v_0
+ if l.Op != OpAMD64MOVBload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ x := v_1
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64CMPBload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (CMPB x l:(MOVBload {sym} [off] ptr mem))
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (InvertFlags (CMPBload {sym} [off] ptr x mem))
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVBload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPBload, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, x, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPBconst (MOVLconst [x]) [y])
+ // cond: int8(x)==y
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int8(x) == y) {
+ break
+ }
+ v.reset(OpAMD64FlagEQ)
+ return true
+ }
+ // match: (CMPBconst (MOVLconst [x]) [y])
+ // cond: int8(x)<y && uint8(x)<uint8(y)
+ // result: (FlagLT_ULT)
+ for {
+ y := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int8(x) < y && uint8(x) < uint8(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPBconst (MOVLconst [x]) [y])
+ // cond: int8(x)<y && uint8(x)>uint8(y)
+ // result: (FlagLT_UGT)
+ for {
+ y := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int8(x) < y && uint8(x) > uint8(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_UGT)
+ return true
+ }
+ // match: (CMPBconst (MOVLconst [x]) [y])
+ // cond: int8(x)>y && uint8(x)<uint8(y)
+ // result: (FlagGT_ULT)
+ for {
+ y := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int8(x) > y && uint8(x) < uint8(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_ULT)
+ return true
+ }
+ // match: (CMPBconst (MOVLconst [x]) [y])
+ // cond: int8(x)>y && uint8(x)>uint8(y)
+ // result: (FlagGT_UGT)
+ for {
+ y := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int8(x) > y && uint8(x) > uint8(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_UGT)
+ return true
+ }
+ // match: (CMPBconst (ANDLconst _ [m]) [n])
+ // cond: 0 <= int8(m) && int8(m) < n
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= int8(m) && int8(m) < n) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPBconst a:(ANDL x y) [0])
+ // cond: a.Uses == 1
+ // result: (TESTB x y)
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ a := v_0
+ if a.Op != OpAMD64ANDL {
+ break
+ }
+ y := a.Args[1]
+ x := a.Args[0]
+ if !(a.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64TESTB)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPBconst a:(ANDLconst [c] x) [0])
+ // cond: a.Uses == 1
+ // result: (TESTBconst [int8(c)] x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ a := v_0
+ if a.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ x := a.Args[0]
+ if !(a.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64TESTBconst)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPBconst x [0])
+ // result: (TESTB x x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64TESTB)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPBconst l:(MOVBload {sym} [off] ptr mem) [c])
+ // cond: l.Uses == 1 && clobber(l)
+ // result: @l.Block (CMPBconstload {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ l := v_0
+ if l.Op != OpAMD64MOVBload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(l.Uses == 1 && clobber(l)) {
+ break
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPBconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPBconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPBconstload [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (CMPBconstload [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPBconstload)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (CMPBconstload [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (CMPBconstload [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPBconstload)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPBload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPBload [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (CMPBload [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64CMPBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (CMPBload [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (CMPBload [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (CMPBload {sym} [off] ptr (MOVLconst [c]) mem)
+ // cond: validValAndOff(int64(int8(c)),int64(off))
+ // result: (CMPBconstload {sym} [makeValAndOff32(int32(int8(c)),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ if !(validValAndOff(int64(int8(c)), int64(off))) {
+ break
+ }
+ v.reset(OpAMD64CMPBconstload)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(int8(c)), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPL x (MOVLconst [c]))
+ // result: (CMPLconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64CMPLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPL (MOVLconst [c]) x)
+ // result: (InvertFlags (CMPLconst x [c]))
+ for {
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPL x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPL y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPL l:(MOVLload {sym} [off] ptr mem) x)
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (CMPLload {sym} [off] ptr x mem)
+ for {
+ l := v_0
+ if l.Op != OpAMD64MOVLload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ x := v_1
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64CMPLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (CMPL x l:(MOVLload {sym} [off] ptr mem))
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (InvertFlags (CMPLload {sym} [off] ptr x mem))
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVLload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPLload, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, x, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPLconst (MOVLconst [x]) [y])
+ // cond: x==y
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x == y) {
+ break
+ }
+ v.reset(OpAMD64FlagEQ)
+ return true
+ }
+ // match: (CMPLconst (MOVLconst [x]) [y])
+ // cond: x<y && uint32(x)<uint32(y)
+ // result: (FlagLT_ULT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x < y && uint32(x) < uint32(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPLconst (MOVLconst [x]) [y])
+ // cond: x<y && uint32(x)>uint32(y)
+ // result: (FlagLT_UGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x < y && uint32(x) > uint32(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_UGT)
+ return true
+ }
+ // match: (CMPLconst (MOVLconst [x]) [y])
+ // cond: x>y && uint32(x)<uint32(y)
+ // result: (FlagGT_ULT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x > y && uint32(x) < uint32(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_ULT)
+ return true
+ }
+ // match: (CMPLconst (MOVLconst [x]) [y])
+ // cond: x>y && uint32(x)>uint32(y)
+ // result: (FlagGT_UGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x > y && uint32(x) > uint32(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_UGT)
+ return true
+ }
+ // match: (CMPLconst (SHRLconst _ [c]) [n])
+ // cond: 0 <= n && 0 < c && c <= 32 && (1<<uint64(32-c)) <= uint64(n)
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64SHRLconst {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if !(0 <= n && 0 < c && c <= 32 && (1<<uint64(32-c)) <= uint64(n)) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPLconst (ANDLconst _ [m]) [n])
+ // cond: 0 <= m && m < n
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= m && m < n) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPLconst a:(ANDL x y) [0])
+ // cond: a.Uses == 1
+ // result: (TESTL x y)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ a := v_0
+ if a.Op != OpAMD64ANDL {
+ break
+ }
+ y := a.Args[1]
+ x := a.Args[0]
+ if !(a.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64TESTL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPLconst a:(ANDLconst [c] x) [0])
+ // cond: a.Uses == 1
+ // result: (TESTLconst [c] x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ a := v_0
+ if a.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ x := a.Args[0]
+ if !(a.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64TESTLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPLconst x [0])
+ // result: (TESTL x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64TESTL)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPLconst l:(MOVLload {sym} [off] ptr mem) [c])
+ // cond: l.Uses == 1 && clobber(l)
+ // result: @l.Block (CMPLconstload {sym} [makeValAndOff32(c,off)] ptr mem)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ l := v_0
+ if l.Op != OpAMD64MOVLload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(l.Uses == 1 && clobber(l)) {
+ break
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPLconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPLconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPLconstload [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (CMPLconstload [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPLconstload)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (CMPLconstload [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (CMPLconstload [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPLconstload)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPLload [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (CMPLload [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64CMPLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (CMPLload [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (CMPLload [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (CMPLload {sym} [off] ptr (MOVLconst [c]) mem)
+ // cond: validValAndOff(int64(c),int64(off))
+ // result: (CMPLconstload {sym} [makeValAndOff32(c,off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ if !(validValAndOff(int64(c), int64(off))) {
+ break
+ }
+ v.reset(OpAMD64CMPLconstload)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPQ x (MOVQconst [c]))
+ // cond: is32Bit(c)
+ // result: (CMPQconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpAMD64CMPQconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPQ (MOVQconst [c]) x)
+ // cond: is32Bit(c)
+ // result: (InvertFlags (CMPQconst x [int32(c)]))
+ for {
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPQ x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPQ y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPQ (MOVQconst [x]) (MOVQconst [y]))
+ // cond: x==y
+ // result: (FlagEQ)
+ for {
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ if !(x == y) {
+ break
+ }
+ v.reset(OpAMD64FlagEQ)
+ return true
+ }
+ // match: (CMPQ (MOVQconst [x]) (MOVQconst [y]))
+ // cond: x<y && uint64(x)<uint64(y)
+ // result: (FlagLT_ULT)
+ for {
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ if !(x < y && uint64(x) < uint64(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPQ (MOVQconst [x]) (MOVQconst [y]))
+ // cond: x<y && uint64(x)>uint64(y)
+ // result: (FlagLT_UGT)
+ for {
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ if !(x < y && uint64(x) > uint64(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_UGT)
+ return true
+ }
+ // match: (CMPQ (MOVQconst [x]) (MOVQconst [y]))
+ // cond: x>y && uint64(x)<uint64(y)
+ // result: (FlagGT_ULT)
+ for {
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ if !(x > y && uint64(x) < uint64(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_ULT)
+ return true
+ }
+ // match: (CMPQ (MOVQconst [x]) (MOVQconst [y]))
+ // cond: x>y && uint64(x)>uint64(y)
+ // result: (FlagGT_UGT)
+ for {
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ if !(x > y && uint64(x) > uint64(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_UGT)
+ return true
+ }
+ // match: (CMPQ l:(MOVQload {sym} [off] ptr mem) x)
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (CMPQload {sym} [off] ptr x mem)
+ for {
+ l := v_0
+ if l.Op != OpAMD64MOVQload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ x := v_1
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64CMPQload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (CMPQ x l:(MOVQload {sym} [off] ptr mem))
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (InvertFlags (CMPQload {sym} [off] ptr x mem))
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVQload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPQload, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, x, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPQconst (NEGQ (ADDQconst [-16] (ANDQconst [15] _))) [32])
+ // result: (FlagLT_ULT)
+ for {
+ if auxIntToInt32(v.AuxInt) != 32 || v_0.Op != OpAMD64NEGQ {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_0_0.AuxInt) != -16 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_0_0_0.AuxInt) != 15 {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPQconst (NEGQ (ADDQconst [ -8] (ANDQconst [7] _))) [32])
+ // result: (FlagLT_ULT)
+ for {
+ if auxIntToInt32(v.AuxInt) != 32 || v_0.Op != OpAMD64NEGQ {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_0_0.AuxInt) != -8 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_0_0_0.AuxInt) != 7 {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPQconst (MOVQconst [x]) [y])
+ // cond: x==int64(y)
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x == int64(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagEQ)
+ return true
+ }
+ // match: (CMPQconst (MOVQconst [x]) [y])
+ // cond: x<int64(y) && uint64(x)<uint64(int64(y))
+ // result: (FlagLT_ULT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x < int64(y) && uint64(x) < uint64(int64(y))) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPQconst (MOVQconst [x]) [y])
+ // cond: x<int64(y) && uint64(x)>uint64(int64(y))
+ // result: (FlagLT_UGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x < int64(y) && uint64(x) > uint64(int64(y))) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_UGT)
+ return true
+ }
+ // match: (CMPQconst (MOVQconst [x]) [y])
+ // cond: x>int64(y) && uint64(x)<uint64(int64(y))
+ // result: (FlagGT_ULT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x > int64(y) && uint64(x) < uint64(int64(y))) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_ULT)
+ return true
+ }
+ // match: (CMPQconst (MOVQconst [x]) [y])
+ // cond: x>int64(y) && uint64(x)>uint64(int64(y))
+ // result: (FlagGT_UGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x > int64(y) && uint64(x) > uint64(int64(y))) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_UGT)
+ return true
+ }
+ // match: (CMPQconst (MOVBQZX _) [c])
+ // cond: 0xFF < c
+ // result: (FlagLT_ULT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVBQZX || !(0xFF < c) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPQconst (MOVWQZX _) [c])
+ // cond: 0xFFFF < c
+ // result: (FlagLT_ULT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVWQZX || !(0xFFFF < c) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPQconst (SHRQconst _ [c]) [n])
+ // cond: 0 <= n && 0 < c && c <= 64 && (1<<uint64(64-c)) <= uint64(n)
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64SHRQconst {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if !(0 <= n && 0 < c && c <= 64 && (1<<uint64(64-c)) <= uint64(n)) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPQconst (ANDQconst _ [m]) [n])
+ // cond: 0 <= m && m < n
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ANDQconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= m && m < n) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPQconst (ANDLconst _ [m]) [n])
+ // cond: 0 <= m && m < n
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= m && m < n) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPQconst a:(ANDQ x y) [0])
+ // cond: a.Uses == 1
+ // result: (TESTQ x y)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ a := v_0
+ if a.Op != OpAMD64ANDQ {
+ break
+ }
+ y := a.Args[1]
+ x := a.Args[0]
+ if !(a.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64TESTQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPQconst a:(ANDQconst [c] x) [0])
+ // cond: a.Uses == 1
+ // result: (TESTQconst [c] x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ a := v_0
+ if a.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ x := a.Args[0]
+ if !(a.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64TESTQconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPQconst x [0])
+ // result: (TESTQ x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64TESTQ)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPQconst l:(MOVQload {sym} [off] ptr mem) [c])
+ // cond: l.Uses == 1 && clobber(l)
+ // result: @l.Block (CMPQconstload {sym} [makeValAndOff32(c,off)] ptr mem)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ l := v_0
+ if l.Op != OpAMD64MOVQload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(l.Uses == 1 && clobber(l)) {
+ break
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPQconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(c, off))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPQconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPQconstload [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (CMPQconstload [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPQconstload)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (CMPQconstload [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (CMPQconstload [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPQconstload)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPQload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPQload [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (CMPQload [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64CMPQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (CMPQload [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (CMPQload [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (CMPQload {sym} [off] ptr (MOVQconst [c]) mem)
+ // cond: validValAndOff(c,int64(off))
+ // result: (CMPQconstload {sym} [makeValAndOff64(c,int64(off))] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(validValAndOff(c, int64(off))) {
+ break
+ }
+ v.reset(OpAMD64CMPQconstload)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff64(c, int64(off)))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPW x (MOVLconst [c]))
+ // result: (CMPWconst x [int16(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64CMPWconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPW (MOVLconst [c]) x)
+ // result: (InvertFlags (CMPWconst x [int16(c)]))
+ for {
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v0.AuxInt = int16ToAuxInt(int16(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPW x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPW y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPW, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPW l:(MOVWload {sym} [off] ptr mem) x)
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (CMPWload {sym} [off] ptr x mem)
+ for {
+ l := v_0
+ if l.Op != OpAMD64MOVWload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ x := v_1
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64CMPWload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (CMPW x l:(MOVWload {sym} [off] ptr mem))
+ // cond: canMergeLoad(v, l) && clobber(l)
+ // result: (InvertFlags (CMPWload {sym} [off] ptr x mem))
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVWload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoad(v, l) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64InvertFlags)
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPWload, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, x, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPWconst (MOVLconst [x]) [y])
+ // cond: int16(x)==y
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt16(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int16(x) == y) {
+ break
+ }
+ v.reset(OpAMD64FlagEQ)
+ return true
+ }
+ // match: (CMPWconst (MOVLconst [x]) [y])
+ // cond: int16(x)<y && uint16(x)<uint16(y)
+ // result: (FlagLT_ULT)
+ for {
+ y := auxIntToInt16(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int16(x) < y && uint16(x) < uint16(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPWconst (MOVLconst [x]) [y])
+ // cond: int16(x)<y && uint16(x)>uint16(y)
+ // result: (FlagLT_UGT)
+ for {
+ y := auxIntToInt16(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int16(x) < y && uint16(x) > uint16(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_UGT)
+ return true
+ }
+ // match: (CMPWconst (MOVLconst [x]) [y])
+ // cond: int16(x)>y && uint16(x)<uint16(y)
+ // result: (FlagGT_ULT)
+ for {
+ y := auxIntToInt16(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int16(x) > y && uint16(x) < uint16(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_ULT)
+ return true
+ }
+ // match: (CMPWconst (MOVLconst [x]) [y])
+ // cond: int16(x)>y && uint16(x)>uint16(y)
+ // result: (FlagGT_UGT)
+ for {
+ y := auxIntToInt16(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(int16(x) > y && uint16(x) > uint16(y)) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_UGT)
+ return true
+ }
+ // match: (CMPWconst (ANDLconst _ [m]) [n])
+ // cond: 0 <= int16(m) && int16(m) < n
+ // result: (FlagLT_ULT)
+ for {
+ n := auxIntToInt16(v.AuxInt)
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= int16(m) && int16(m) < n) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_ULT)
+ return true
+ }
+ // match: (CMPWconst a:(ANDL x y) [0])
+ // cond: a.Uses == 1
+ // result: (TESTW x y)
+ for {
+ if auxIntToInt16(v.AuxInt) != 0 {
+ break
+ }
+ a := v_0
+ if a.Op != OpAMD64ANDL {
+ break
+ }
+ y := a.Args[1]
+ x := a.Args[0]
+ if !(a.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64TESTW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPWconst a:(ANDLconst [c] x) [0])
+ // cond: a.Uses == 1
+ // result: (TESTWconst [int16(c)] x)
+ for {
+ if auxIntToInt16(v.AuxInt) != 0 {
+ break
+ }
+ a := v_0
+ if a.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ x := a.Args[0]
+ if !(a.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64TESTWconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPWconst x [0])
+ // result: (TESTW x x)
+ for {
+ if auxIntToInt16(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64TESTW)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPWconst l:(MOVWload {sym} [off] ptr mem) [c])
+ // cond: l.Uses == 1 && clobber(l)
+ // result: @l.Block (CMPWconstload {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ c := auxIntToInt16(v.AuxInt)
+ l := v_0
+ if l.Op != OpAMD64MOVWload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(l.Uses == 1 && clobber(l)) {
+ break
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPWconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPWconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPWconstload [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (CMPWconstload [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPWconstload)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (CMPWconstload [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (CMPWconstload [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPWconstload)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPWload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPWload [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (CMPWload [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64CMPWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (CMPWload [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (CMPWload [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (CMPWload {sym} [off] ptr (MOVLconst [c]) mem)
+ // cond: validValAndOff(int64(int16(c)),int64(off))
+ // result: (CMPWconstload {sym} [makeValAndOff32(int32(int16(c)),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ if !(validValAndOff(int64(int16(c)), int64(off))) {
+ break
+ }
+ v.reset(OpAMD64CMPWconstload)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(int16(c)), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPXCHGLlock(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPXCHGLlock [off1] {sym} (ADDQconst [off2] ptr) old new_ mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (CMPXCHGLlock [off1+off2] {sym} ptr old new_ mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ old := v_1
+ new_ := v_2
+ mem := v_3
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64CMPXCHGLlock)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg4(ptr, old, new_, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64CMPXCHGQlock(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPXCHGQlock [off1] {sym} (ADDQconst [off2] ptr) old new_ mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (CMPXCHGQlock [off1+off2] {sym} ptr old new_ mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ old := v_1
+ new_ := v_2
+ mem := v_3
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64CMPXCHGQlock)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg4(ptr, old, new_, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64DIVSD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (DIVSD x l:(MOVSDload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (DIVSDload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVSDload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64DIVSDload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64DIVSDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (DIVSDload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (DIVSDload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64DIVSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (DIVSDload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (DIVSDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64DIVSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64DIVSS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (DIVSS x l:(MOVSSload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (DIVSSload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVSSload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64DIVSSload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64DIVSSload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (DIVSSload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (DIVSSload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64DIVSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (DIVSSload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (DIVSSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64DIVSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64HMULL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (HMULL x y)
+ // cond: !x.rematerializeable() && y.rematerializeable()
+ // result: (HMULL y x)
+ for {
+ x := v_0
+ y := v_1
+ if !(!x.rematerializeable() && y.rematerializeable()) {
+ break
+ }
+ v.reset(OpAMD64HMULL)
+ v.AddArg2(y, x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64HMULLU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (HMULLU x y)
+ // cond: !x.rematerializeable() && y.rematerializeable()
+ // result: (HMULLU y x)
+ for {
+ x := v_0
+ y := v_1
+ if !(!x.rematerializeable() && y.rematerializeable()) {
+ break
+ }
+ v.reset(OpAMD64HMULLU)
+ v.AddArg2(y, x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64HMULQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (HMULQ x y)
+ // cond: !x.rematerializeable() && y.rematerializeable()
+ // result: (HMULQ y x)
+ for {
+ x := v_0
+ y := v_1
+ if !(!x.rematerializeable() && y.rematerializeable()) {
+ break
+ }
+ v.reset(OpAMD64HMULQ)
+ v.AddArg2(y, x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64HMULQU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (HMULQU x y)
+ // cond: !x.rematerializeable() && y.rematerializeable()
+ // result: (HMULQU y x)
+ for {
+ x := v_0
+ y := v_1
+ if !(!x.rematerializeable() && y.rematerializeable()) {
+ break
+ }
+ v.reset(OpAMD64HMULQU)
+ v.AddArg2(y, x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64LEAL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LEAL [c] {s} (ADDLconst [d] x))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAL [c+d] {s} x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAL)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LEAL [c] {s} (ADDL x y))
+ // cond: x.Op != OpSB && y.Op != OpSB
+ // result: (LEAL1 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDL {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if !(x.Op != OpSB && y.Op != OpSB) {
+ continue
+ }
+ v.reset(OpAMD64LEAL1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64LEAL1(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAL1 [c] {s} (ADDLconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAL1 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64ADDLconst {
+ continue
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ continue
+ }
+ v.reset(OpAMD64LEAL1)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAL1 [c] {s} x (SHLLconst [1] y))
+ // result: (LEAL2 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 1 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAL2)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAL1 [c] {s} x (SHLLconst [2] y))
+ // result: (LEAL4 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 2 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAL4)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAL1 [c] {s} x (SHLLconst [3] y))
+ // result: (LEAL8 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 3 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAL8)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64LEAL2(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAL2 [c] {s} (ADDLconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAL2 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAL2)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL2 [c] {s} x (ADDLconst [d] y))
+ // cond: is32Bit(int64(c)+2*int64(d)) && y.Op != OpSB
+ // result: (LEAL2 [c+2*d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(is32Bit(int64(c)+2*int64(d)) && y.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAL2)
+ v.AuxInt = int32ToAuxInt(c + 2*d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL2 [c] {s} x (SHLLconst [1] y))
+ // result: (LEAL4 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 1 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAL4)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL2 [c] {s} x (SHLLconst [2] y))
+ // result: (LEAL8 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 2 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAL8)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64LEAL4(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAL4 [c] {s} (ADDLconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAL4 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAL4)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL4 [c] {s} x (ADDLconst [d] y))
+ // cond: is32Bit(int64(c)+4*int64(d)) && y.Op != OpSB
+ // result: (LEAL4 [c+4*d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(is32Bit(int64(c)+4*int64(d)) && y.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAL4)
+ v.AuxInt = int32ToAuxInt(c + 4*d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL4 [c] {s} x (SHLLconst [1] y))
+ // result: (LEAL8 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 1 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAL8)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64LEAL8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAL8 [c] {s} (ADDLconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAL8 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAL8)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAL8 [c] {s} x (ADDLconst [d] y))
+ // cond: is32Bit(int64(c)+8*int64(d)) && y.Op != OpSB
+ // result: (LEAL8 [c+8*d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64ADDLconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(is32Bit(int64(c)+8*int64(d)) && y.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAL8)
+ v.AuxInt = int32ToAuxInt(c + 8*d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64LEAQ(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LEAQ [c] {s} (ADDQconst [d] x))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (LEAQ [c+d] {s} x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpAMD64LEAQ)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LEAQ [c] {s} (ADDQ x y))
+ // cond: x.Op != OpSB && y.Op != OpSB
+ // result: (LEAQ1 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if !(x.Op != OpSB && y.Op != OpSB) {
+ continue
+ }
+ v.reset(OpAMD64LEAQ1)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAQ [off1] {sym1} (LEAQ [off2] {sym2} x))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAQ [off1+off2] {mergeSym(sym1,sym2)} x)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg(x)
+ return true
+ }
+ // match: (LEAQ [off1] {sym1} (LEAQ1 [off2] {sym2} x y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAQ1 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ1 {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ1)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ [off1] {sym1} (LEAQ2 [off2] {sym2} x y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAQ2 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ2 {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ2)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ [off1] {sym1} (LEAQ4 [off2] {sym2} x y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAQ4 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ4 {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ4)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ [off1] {sym1} (LEAQ8 [off2] {sym2} x y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAQ8 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ8 {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ8)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64LEAQ1(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAQ1 [c] {s} (ADDQconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAQ1 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64ADDQconst {
+ continue
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ continue
+ }
+ v.reset(OpAMD64LEAQ1)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAQ1 [c] {s} x (SHLQconst [1] y))
+ // result: (LEAQ2 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 1 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAQ2)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAQ1 [c] {s} x (SHLQconst [2] y))
+ // result: (LEAQ4 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 2 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAQ4)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAQ1 [c] {s} x (SHLQconst [3] y))
+ // result: (LEAQ8 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 3 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAQ8)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAQ1 [off1] {sym1} (LEAQ [off2] {sym2} x) y)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB
+ // result: (LEAQ1 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64LEAQ {
+ continue
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB) {
+ continue
+ }
+ v.reset(OpAMD64LEAQ1)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAQ1 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAQ2 [off1+off2] {mergeSym(sym1, sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64LEAQ1 {
+ continue
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ y := v_1.Args[1]
+ if y != v_1.Args[0] || !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ continue
+ }
+ v.reset(OpAMD64LEAQ2)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (LEAQ1 [off1] {sym1} x (LEAQ1 [off2] {sym2} x y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (LEAQ2 [off1+off2] {mergeSym(sym1, sym2)} y x)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64LEAQ1 {
+ continue
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ continue
+ }
+ v.reset(OpAMD64LEAQ2)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(y, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (LEAQ1 [0] x y)
+ // cond: v.Aux == nil
+ // result: (ADDQ x y)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ y := v_1
+ if !(v.Aux == nil) {
+ break
+ }
+ v.reset(OpAMD64ADDQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64LEAQ2(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAQ2 [c] {s} (ADDQconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAQ2 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAQ2)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ2 [c] {s} x (ADDQconst [d] y))
+ // cond: is32Bit(int64(c)+2*int64(d)) && y.Op != OpSB
+ // result: (LEAQ2 [c+2*d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(is32Bit(int64(c)+2*int64(d)) && y.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAQ2)
+ v.AuxInt = int32ToAuxInt(c + 2*d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ2 [c] {s} x (SHLQconst [1] y))
+ // result: (LEAQ4 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 1 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAQ4)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ2 [c] {s} x (SHLQconst [2] y))
+ // result: (LEAQ8 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 2 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAQ8)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ2 [off1] {sym1} (LEAQ [off2] {sym2} x) y)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB
+ // result: (LEAQ2 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAQ2)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ2 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y))
+ // cond: is32Bit(int64(off1)+2*int64(off2)) && sym2 == nil
+ // result: (LEAQ4 [off1+2*off2] {sym1} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64LEAQ1 {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ y := v_1.Args[1]
+ if y != v_1.Args[0] || !(is32Bit(int64(off1)+2*int64(off2)) && sym2 == nil) {
+ break
+ }
+ v.reset(OpAMD64LEAQ4)
+ v.AuxInt = int32ToAuxInt(off1 + 2*off2)
+ v.Aux = symToAux(sym1)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ2 [off] {sym} x (MOVQconst [scale]))
+ // cond: is32Bit(int64(off)+int64(scale)*2)
+ // result: (LEAQ [off+int32(scale)*2] {sym} x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ scale := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(int64(off) + int64(scale)*2)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ)
+ v.AuxInt = int32ToAuxInt(off + int32(scale)*2)
+ v.Aux = symToAux(sym)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LEAQ2 [off] {sym} x (MOVLconst [scale]))
+ // cond: is32Bit(int64(off)+int64(scale)*2)
+ // result: (LEAQ [off+int32(scale)*2] {sym} x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ scale := auxIntToInt32(v_1.AuxInt)
+ if !(is32Bit(int64(off) + int64(scale)*2)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ)
+ v.AuxInt = int32ToAuxInt(off + int32(scale)*2)
+ v.Aux = symToAux(sym)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64LEAQ4(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAQ4 [c] {s} (ADDQconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAQ4 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAQ4)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ4 [c] {s} x (ADDQconst [d] y))
+ // cond: is32Bit(int64(c)+4*int64(d)) && y.Op != OpSB
+ // result: (LEAQ4 [c+4*d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(is32Bit(int64(c)+4*int64(d)) && y.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAQ4)
+ v.AuxInt = int32ToAuxInt(c + 4*d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ4 [c] {s} x (SHLQconst [1] y))
+ // result: (LEAQ8 [c] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 1 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64LEAQ8)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ4 [off1] {sym1} (LEAQ [off2] {sym2} x) y)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB
+ // result: (LEAQ4 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAQ4)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ4 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y))
+ // cond: is32Bit(int64(off1)+4*int64(off2)) && sym2 == nil
+ // result: (LEAQ8 [off1+4*off2] {sym1} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64LEAQ1 {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ y := v_1.Args[1]
+ if y != v_1.Args[0] || !(is32Bit(int64(off1)+4*int64(off2)) && sym2 == nil) {
+ break
+ }
+ v.reset(OpAMD64LEAQ8)
+ v.AuxInt = int32ToAuxInt(off1 + 4*off2)
+ v.Aux = symToAux(sym1)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ4 [off] {sym} x (MOVQconst [scale]))
+ // cond: is32Bit(int64(off)+int64(scale)*4)
+ // result: (LEAQ [off+int32(scale)*4] {sym} x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ scale := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(int64(off) + int64(scale)*4)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ)
+ v.AuxInt = int32ToAuxInt(off + int32(scale)*4)
+ v.Aux = symToAux(sym)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LEAQ4 [off] {sym} x (MOVLconst [scale]))
+ // cond: is32Bit(int64(off)+int64(scale)*4)
+ // result: (LEAQ [off+int32(scale)*4] {sym} x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ scale := auxIntToInt32(v_1.AuxInt)
+ if !(is32Bit(int64(off) + int64(scale)*4)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ)
+ v.AuxInt = int32ToAuxInt(off + int32(scale)*4)
+ v.Aux = symToAux(sym)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64LEAQ8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LEAQ8 [c] {s} (ADDQconst [d] x) y)
+ // cond: is32Bit(int64(c)+int64(d)) && x.Op != OpSB
+ // result: (LEAQ8 [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(c)+int64(d)) && x.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAQ8)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ8 [c] {s} x (ADDQconst [d] y))
+ // cond: is32Bit(int64(c)+8*int64(d)) && y.Op != OpSB
+ // result: (LEAQ8 [c+8*d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(is32Bit(int64(c)+8*int64(d)) && y.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAQ8)
+ v.AuxInt = int32ToAuxInt(c + 8*d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ8 [off1] {sym1} (LEAQ [off2] {sym2} x) y)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB
+ // result: (LEAQ8 [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64LEAQ8)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (LEAQ8 [off] {sym} x (MOVQconst [scale]))
+ // cond: is32Bit(int64(off)+int64(scale)*8)
+ // result: (LEAQ [off+int32(scale)*8] {sym} x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ scale := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(int64(off) + int64(scale)*8)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ)
+ v.AuxInt = int32ToAuxInt(off + int32(scale)*8)
+ v.Aux = symToAux(sym)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LEAQ8 [off] {sym} x (MOVLconst [scale]))
+ // cond: is32Bit(int64(off)+int64(scale)*8)
+ // result: (LEAQ [off+int32(scale)*8] {sym} x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ scale := auxIntToInt32(v_1.AuxInt)
+ if !(is32Bit(int64(off) + int64(scale)*8)) {
+ break
+ }
+ v.reset(OpAMD64LEAQ)
+ v.AuxInt = int32ToAuxInt(off + int32(scale)*8)
+ v.Aux = symToAux(sym)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVBQSX(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVBQSX x:(MOVBload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVBload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVBQSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBQSX x:(MOVWload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVWload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVBQSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBQSX x:(MOVLload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVLload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVBQSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBQSX x:(MOVQload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVQload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVBQSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBQSX (ANDLconst [c] x))
+ // cond: c & 0x80 == 0
+ // result: (ANDLconst [c & 0x7f] x)
+ for {
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c&0x80 == 0) {
+ break
+ }
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & 0x7f)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBQSX (MOVBQSX x))
+ // result: (MOVBQSX x)
+ for {
+ if v_0.Op != OpAMD64MOVBQSX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVBQSX)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVBQSXload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBQSXload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVBQSX x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVBstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpAMD64MOVBQSX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBQSXload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVBQSXload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVBQSXload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVBQZX(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVBQZX x:(MOVBload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVBload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVBload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBQZX x:(MOVWload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVWload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVBload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBQZX x:(MOVLload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVLload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVBload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBQZX x:(MOVQload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVQload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVBload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBQZX x)
+ // cond: zeroUpper56Bits(x,3)
+ // result: x
+ for {
+ x := v_0
+ if !(zeroUpper56Bits(x, 3)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVBQZX (ANDLconst [c] x))
+ // result: (ANDLconst [c & 0xff] x)
+ for {
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & 0xff)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBQZX (MOVBQZX x))
+ // result: (MOVBQZX x)
+ for {
+ if v_0.Op != OpAMD64MOVBQZX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVBQZX)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVBatomicload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBatomicload [off1] {sym} (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBatomicload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVBatomicload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBatomicload [off1] {sym1} (LEAQ [off2] {sym2} ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVBatomicload [off1+off2] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVBatomicload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVBload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVBQZX x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVBstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpAMD64MOVBQZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBload [off1] {sym} (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym} (ADDLconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVLconst [int32(read8(sym, int64(off)))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(int32(read8(sym, int64(off))))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVBstore [off] {sym} ptr y:(SETL x) mem)
+ // cond: y.Uses == 1
+ // result: (SETLstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SETL {
+ break
+ }
+ x := y.Args[0]
+ mem := v_2
+ if !(y.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SETLstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr y:(SETLE x) mem)
+ // cond: y.Uses == 1
+ // result: (SETLEstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SETLE {
+ break
+ }
+ x := y.Args[0]
+ mem := v_2
+ if !(y.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SETLEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr y:(SETG x) mem)
+ // cond: y.Uses == 1
+ // result: (SETGstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SETG {
+ break
+ }
+ x := y.Args[0]
+ mem := v_2
+ if !(y.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SETGstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr y:(SETGE x) mem)
+ // cond: y.Uses == 1
+ // result: (SETGEstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SETGE {
+ break
+ }
+ x := y.Args[0]
+ mem := v_2
+ if !(y.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SETGEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr y:(SETEQ x) mem)
+ // cond: y.Uses == 1
+ // result: (SETEQstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SETEQ {
+ break
+ }
+ x := y.Args[0]
+ mem := v_2
+ if !(y.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SETEQstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr y:(SETNE x) mem)
+ // cond: y.Uses == 1
+ // result: (SETNEstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SETNE {
+ break
+ }
+ x := y.Args[0]
+ mem := v_2
+ if !(y.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SETNEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr y:(SETB x) mem)
+ // cond: y.Uses == 1
+ // result: (SETBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SETB {
+ break
+ }
+ x := y.Args[0]
+ mem := v_2
+ if !(y.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr y:(SETBE x) mem)
+ // cond: y.Uses == 1
+ // result: (SETBEstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SETBE {
+ break
+ }
+ x := y.Args[0]
+ mem := v_2
+ if !(y.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SETBEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr y:(SETA x) mem)
+ // cond: y.Uses == 1
+ // result: (SETAstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SETA {
+ break
+ }
+ x := y.Args[0]
+ mem := v_2
+ if !(y.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SETAstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr y:(SETAE x) mem)
+ // cond: y.Uses == 1
+ // result: (SETAEstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SETAE {
+ break
+ }
+ x := y.Args[0]
+ mem := v_2
+ if !(y.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBQSX x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVBQSX {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBQZX x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVBQZX {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym} (ADDQconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVLconst [c]) mem)
+ // result: (MOVBstoreconst [makeValAndOff32(int32(int8(c)),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpAMD64MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(int8(c)), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVQconst [c]) mem)
+ // result: (MOVBstoreconst [makeValAndOff32(int32(int8(c)),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpAMD64MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(int8(c)), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w x0:(MOVBstore [i-1] {s} p (SHRWconst [8] w) mem))
+ // cond: x0.Uses == 1 && clobber(x0)
+ // result: (MOVWstore [i-1] {s} p (ROLWconst <w.Type> [8] w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpAMD64MOVBstore || auxIntToInt32(x0.AuxInt) != i-1 || auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpAMD64SHRWconst || auxIntToInt8(x0_1.AuxInt) != 8 || w != x0_1.Args[0] || !(x0.Uses == 1 && clobber(x0)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ROLWconst, w.Type)
+ v0.AuxInt = int8ToAuxInt(8)
+ v0.AddArg(w)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p1 w x0:(MOVBstore [i] {s} p0 (SHRWconst [8] w) mem))
+ // cond: x0.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x0)
+ // result: (MOVWstore [i] {s} p0 (ROLWconst <w.Type> [8] w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpAMD64MOVBstore || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ p0 := x0.Args[0]
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpAMD64SHRWconst || auxIntToInt8(x0_1.AuxInt) != 8 || w != x0_1.Args[0] || !(x0.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x0)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ROLWconst, w.Type)
+ v0.AuxInt = int8ToAuxInt(8)
+ v0.AddArg(w)
+ v.AddArg3(p0, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w x2:(MOVBstore [i-1] {s} p (SHRLconst [8] w) x1:(MOVBstore [i-2] {s} p (SHRLconst [16] w) x0:(MOVBstore [i-3] {s} p (SHRLconst [24] w) mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)
+ // result: (MOVLstore [i-3] {s} p (BSWAPL <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x2 := v_2
+ if x2.Op != OpAMD64MOVBstore || auxIntToInt32(x2.AuxInt) != i-1 || auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[2]
+ if p != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpAMD64SHRLconst || auxIntToInt8(x2_1.AuxInt) != 8 || w != x2_1.Args[0] {
+ break
+ }
+ x1 := x2.Args[2]
+ if x1.Op != OpAMD64MOVBstore || auxIntToInt32(x1.AuxInt) != i-2 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ if p != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpAMD64SHRLconst || auxIntToInt8(x1_1.AuxInt) != 16 || w != x1_1.Args[0] {
+ break
+ }
+ x0 := x1.Args[2]
+ if x0.Op != OpAMD64MOVBstore || auxIntToInt32(x0.AuxInt) != i-3 || auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpAMD64SHRLconst || auxIntToInt8(x0_1.AuxInt) != 24 || w != x0_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i - 3)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPL, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p3 w x2:(MOVBstore [i] {s} p2 (SHRLconst [8] w) x1:(MOVBstore [i] {s} p1 (SHRLconst [16] w) x0:(MOVBstore [i] {s} p0 (SHRLconst [24] w) mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && sequentialAddresses(p0, p1, 1) && sequentialAddresses(p1, p2, 1) && sequentialAddresses(p2, p3, 1) && clobber(x0, x1, x2)
+ // result: (MOVLstore [i] {s} p0 (BSWAPL <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p3 := v_0
+ w := v_1
+ x2 := v_2
+ if x2.Op != OpAMD64MOVBstore || auxIntToInt32(x2.AuxInt) != i || auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[2]
+ p2 := x2.Args[0]
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpAMD64SHRLconst || auxIntToInt8(x2_1.AuxInt) != 8 || w != x2_1.Args[0] {
+ break
+ }
+ x1 := x2.Args[2]
+ if x1.Op != OpAMD64MOVBstore || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ p1 := x1.Args[0]
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpAMD64SHRLconst || auxIntToInt8(x1_1.AuxInt) != 16 || w != x1_1.Args[0] {
+ break
+ }
+ x0 := x1.Args[2]
+ if x0.Op != OpAMD64MOVBstore || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ p0 := x0.Args[0]
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpAMD64SHRLconst || auxIntToInt8(x0_1.AuxInt) != 24 || w != x0_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && sequentialAddresses(p0, p1, 1) && sequentialAddresses(p1, p2, 1) && sequentialAddresses(p2, p3, 1) && clobber(x0, x1, x2)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPL, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(p0, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w x6:(MOVBstore [i-1] {s} p (SHRQconst [8] w) x5:(MOVBstore [i-2] {s} p (SHRQconst [16] w) x4:(MOVBstore [i-3] {s} p (SHRQconst [24] w) x3:(MOVBstore [i-4] {s} p (SHRQconst [32] w) x2:(MOVBstore [i-5] {s} p (SHRQconst [40] w) x1:(MOVBstore [i-6] {s} p (SHRQconst [48] w) x0:(MOVBstore [i-7] {s} p (SHRQconst [56] w) mem))))))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && clobber(x0, x1, x2, x3, x4, x5, x6)
+ // result: (MOVQstore [i-7] {s} p (BSWAPQ <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x6 := v_2
+ if x6.Op != OpAMD64MOVBstore || auxIntToInt32(x6.AuxInt) != i-1 || auxToSym(x6.Aux) != s {
+ break
+ }
+ _ = x6.Args[2]
+ if p != x6.Args[0] {
+ break
+ }
+ x6_1 := x6.Args[1]
+ if x6_1.Op != OpAMD64SHRQconst || auxIntToInt8(x6_1.AuxInt) != 8 || w != x6_1.Args[0] {
+ break
+ }
+ x5 := x6.Args[2]
+ if x5.Op != OpAMD64MOVBstore || auxIntToInt32(x5.AuxInt) != i-2 || auxToSym(x5.Aux) != s {
+ break
+ }
+ _ = x5.Args[2]
+ if p != x5.Args[0] {
+ break
+ }
+ x5_1 := x5.Args[1]
+ if x5_1.Op != OpAMD64SHRQconst || auxIntToInt8(x5_1.AuxInt) != 16 || w != x5_1.Args[0] {
+ break
+ }
+ x4 := x5.Args[2]
+ if x4.Op != OpAMD64MOVBstore || auxIntToInt32(x4.AuxInt) != i-3 || auxToSym(x4.Aux) != s {
+ break
+ }
+ _ = x4.Args[2]
+ if p != x4.Args[0] {
+ break
+ }
+ x4_1 := x4.Args[1]
+ if x4_1.Op != OpAMD64SHRQconst || auxIntToInt8(x4_1.AuxInt) != 24 || w != x4_1.Args[0] {
+ break
+ }
+ x3 := x4.Args[2]
+ if x3.Op != OpAMD64MOVBstore || auxIntToInt32(x3.AuxInt) != i-4 || auxToSym(x3.Aux) != s {
+ break
+ }
+ _ = x3.Args[2]
+ if p != x3.Args[0] {
+ break
+ }
+ x3_1 := x3.Args[1]
+ if x3_1.Op != OpAMD64SHRQconst || auxIntToInt8(x3_1.AuxInt) != 32 || w != x3_1.Args[0] {
+ break
+ }
+ x2 := x3.Args[2]
+ if x2.Op != OpAMD64MOVBstore || auxIntToInt32(x2.AuxInt) != i-5 || auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[2]
+ if p != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpAMD64SHRQconst || auxIntToInt8(x2_1.AuxInt) != 40 || w != x2_1.Args[0] {
+ break
+ }
+ x1 := x2.Args[2]
+ if x1.Op != OpAMD64MOVBstore || auxIntToInt32(x1.AuxInt) != i-6 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ if p != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpAMD64SHRQconst || auxIntToInt8(x1_1.AuxInt) != 48 || w != x1_1.Args[0] {
+ break
+ }
+ x0 := x1.Args[2]
+ if x0.Op != OpAMD64MOVBstore || auxIntToInt32(x0.AuxInt) != i-7 || auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpAMD64SHRQconst || auxIntToInt8(x0_1.AuxInt) != 56 || w != x0_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && clobber(x0, x1, x2, x3, x4, x5, x6)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(i - 7)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPQ, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p7 w x6:(MOVBstore [i] {s} p6 (SHRQconst [8] w) x5:(MOVBstore [i] {s} p5 (SHRQconst [16] w) x4:(MOVBstore [i] {s} p4 (SHRQconst [24] w) x3:(MOVBstore [i] {s} p3 (SHRQconst [32] w) x2:(MOVBstore [i] {s} p2 (SHRQconst [40] w) x1:(MOVBstore [i] {s} p1 (SHRQconst [48] w) x0:(MOVBstore [i] {s} p0 (SHRQconst [56] w) mem))))))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && sequentialAddresses(p0, p1, 1) && sequentialAddresses(p1, p2, 1) && sequentialAddresses(p2, p3, 1) && sequentialAddresses(p3, p4, 1) && sequentialAddresses(p4, p5, 1) && sequentialAddresses(p5, p6, 1) && sequentialAddresses(p6, p7, 1) && clobber(x0, x1, x2, x3, x4, x5, x6)
+ // result: (MOVQstore [i] {s} p0 (BSWAPQ <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p7 := v_0
+ w := v_1
+ x6 := v_2
+ if x6.Op != OpAMD64MOVBstore || auxIntToInt32(x6.AuxInt) != i || auxToSym(x6.Aux) != s {
+ break
+ }
+ _ = x6.Args[2]
+ p6 := x6.Args[0]
+ x6_1 := x6.Args[1]
+ if x6_1.Op != OpAMD64SHRQconst || auxIntToInt8(x6_1.AuxInt) != 8 || w != x6_1.Args[0] {
+ break
+ }
+ x5 := x6.Args[2]
+ if x5.Op != OpAMD64MOVBstore || auxIntToInt32(x5.AuxInt) != i || auxToSym(x5.Aux) != s {
+ break
+ }
+ _ = x5.Args[2]
+ p5 := x5.Args[0]
+ x5_1 := x5.Args[1]
+ if x5_1.Op != OpAMD64SHRQconst || auxIntToInt8(x5_1.AuxInt) != 16 || w != x5_1.Args[0] {
+ break
+ }
+ x4 := x5.Args[2]
+ if x4.Op != OpAMD64MOVBstore || auxIntToInt32(x4.AuxInt) != i || auxToSym(x4.Aux) != s {
+ break
+ }
+ _ = x4.Args[2]
+ p4 := x4.Args[0]
+ x4_1 := x4.Args[1]
+ if x4_1.Op != OpAMD64SHRQconst || auxIntToInt8(x4_1.AuxInt) != 24 || w != x4_1.Args[0] {
+ break
+ }
+ x3 := x4.Args[2]
+ if x3.Op != OpAMD64MOVBstore || auxIntToInt32(x3.AuxInt) != i || auxToSym(x3.Aux) != s {
+ break
+ }
+ _ = x3.Args[2]
+ p3 := x3.Args[0]
+ x3_1 := x3.Args[1]
+ if x3_1.Op != OpAMD64SHRQconst || auxIntToInt8(x3_1.AuxInt) != 32 || w != x3_1.Args[0] {
+ break
+ }
+ x2 := x3.Args[2]
+ if x2.Op != OpAMD64MOVBstore || auxIntToInt32(x2.AuxInt) != i || auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[2]
+ p2 := x2.Args[0]
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpAMD64SHRQconst || auxIntToInt8(x2_1.AuxInt) != 40 || w != x2_1.Args[0] {
+ break
+ }
+ x1 := x2.Args[2]
+ if x1.Op != OpAMD64MOVBstore || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ p1 := x1.Args[0]
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpAMD64SHRQconst || auxIntToInt8(x1_1.AuxInt) != 48 || w != x1_1.Args[0] {
+ break
+ }
+ x0 := x1.Args[2]
+ if x0.Op != OpAMD64MOVBstore || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ p0 := x0.Args[0]
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpAMD64SHRQconst || auxIntToInt8(x0_1.AuxInt) != 56 || w != x0_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && sequentialAddresses(p0, p1, 1) && sequentialAddresses(p1, p2, 1) && sequentialAddresses(p2, p3, 1) && sequentialAddresses(p3, p4, 1) && sequentialAddresses(p4, p5, 1) && sequentialAddresses(p5, p6, 1) && sequentialAddresses(p6, p7, 1) && clobber(x0, x1, x2, x3, x4, x5, x6)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPQ, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(p0, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SHRWconst [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-1] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRWconst || auxIntToInt8(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SHRLconst [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-1] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRLconst || auxIntToInt8(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SHRQconst [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-1] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRQconst || auxIntToInt8(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w x:(MOVBstore [i+1] {s} p (SHRWconst [8] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i+1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpAMD64SHRWconst || auxIntToInt8(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w x:(MOVBstore [i+1] {s} p (SHRLconst [8] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i+1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpAMD64SHRLconst || auxIntToInt8(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w x:(MOVBstore [i+1] {s} p (SHRQconst [8] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i+1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpAMD64SHRQconst || auxIntToInt8(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SHRLconst [j-8] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-1] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRLconst {
+ break
+ }
+ j := auxIntToInt8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != OpAMD64SHRLconst || auxIntToInt8(w0.AuxInt) != j-8 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SHRQconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SHRQconst [j-8] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-1] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRQconst {
+ break
+ }
+ j := auxIntToInt8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != OpAMD64SHRQconst || auxIntToInt8(w0.AuxInt) != j-8 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p1 (SHRWconst [8] w) x:(MOVBstore [i] {s} p0 w mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRWconst || auxIntToInt8(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p1 (SHRLconst [8] w) x:(MOVBstore [i] {s} p0 w mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRLconst || auxIntToInt8(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p1 (SHRQconst [8] w) x:(MOVBstore [i] {s} p0 w mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRQconst || auxIntToInt8(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p0 w x:(MOVBstore [i] {s} p1 (SHRWconst [8] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p0 := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p1 := x.Args[0]
+ x_1 := x.Args[1]
+ if x_1.Op != OpAMD64SHRWconst || auxIntToInt8(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p0 w x:(MOVBstore [i] {s} p1 (SHRLconst [8] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p0 := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p1 := x.Args[0]
+ x_1 := x.Args[1]
+ if x_1.Op != OpAMD64SHRLconst || auxIntToInt8(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p0 w x:(MOVBstore [i] {s} p1 (SHRQconst [8] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p0 := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p1 := x.Args[0]
+ x_1 := x.Args[1]
+ if x_1.Op != OpAMD64SHRQconst || auxIntToInt8(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p1 (SHRLconst [j] w) x:(MOVBstore [i] {s} p0 w0:(SHRLconst [j-8] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRLconst {
+ break
+ }
+ j := auxIntToInt8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != OpAMD64SHRLconst || auxIntToInt8(w0.AuxInt) != j-8 || w != w0.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p1 (SHRQconst [j] w) x:(MOVBstore [i] {s} p0 w0:(SHRQconst [j-8] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)
+ // result: (MOVWstore [i] {s} p0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRQconst {
+ break
+ }
+ j := auxIntToInt8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVBstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != OpAMD64SHRQconst || auxIntToInt8(w0.AuxInt) != j-8 || w != w0.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 1) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p x1:(MOVBload [j] {s2} p2 mem) mem2:(MOVBstore [i-1] {s} p x2:(MOVBload [j-1] {s2} p2 mem) mem))
+ // cond: x1.Uses == 1 && x2.Uses == 1 && mem2.Uses == 1 && clobber(x1, x2, mem2)
+ // result: (MOVWstore [i-1] {s} p (MOVWload [j-1] {s2} p2 mem) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x1 := v_1
+ if x1.Op != OpAMD64MOVBload {
+ break
+ }
+ j := auxIntToInt32(x1.AuxInt)
+ s2 := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p2 := x1.Args[0]
+ mem2 := v_2
+ if mem2.Op != OpAMD64MOVBstore || auxIntToInt32(mem2.AuxInt) != i-1 || auxToSym(mem2.Aux) != s {
+ break
+ }
+ _ = mem2.Args[2]
+ if p != mem2.Args[0] {
+ break
+ }
+ x2 := mem2.Args[1]
+ if x2.Op != OpAMD64MOVBload || auxIntToInt32(x2.AuxInt) != j-1 || auxToSym(x2.Aux) != s2 {
+ break
+ }
+ _ = x2.Args[1]
+ if p2 != x2.Args[0] || mem != x2.Args[1] || mem != mem2.Args[2] || !(x1.Uses == 1 && x2.Uses == 1 && mem2.Uses == 1 && clobber(x1, x2, mem2)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x2.Pos, OpAMD64MOVWload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(j - 1)
+ v0.Aux = symToAux(s2)
+ v0.AddArg2(p2, mem)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym} (ADDLconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVBstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstoreconst [sc] {s} (ADDQconst [off] ptr) mem)
+ // cond: ValAndOff(sc).canAdd32(off)
+ // result: (MOVBstoreconst [ValAndOff(sc).addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(sc).canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)
+ // result: (MOVBstoreconst [ValAndOff(sc).addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem))
+ // cond: x.Uses == 1 && a.Off() + 1 == c.Off() && clobber(x)
+ // result: (MOVWstoreconst [makeValAndOff64(a.Val()&0xff | c.Val()<<8, a.Off())] {s} p mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != OpAMD64MOVBstoreconst {
+ break
+ }
+ a := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(x.Uses == 1 && a.Off()+1 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff64(a.Val()&0xff|c.Val()<<8, a.Off()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [a] {s} p x:(MOVBstoreconst [c] {s} p mem))
+ // cond: x.Uses == 1 && a.Off() + 1 == c.Off() && clobber(x)
+ // result: (MOVWstoreconst [makeValAndOff64(a.Val()&0xff | c.Val()<<8, a.Off())] {s} p mem)
+ for {
+ a := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != OpAMD64MOVBstoreconst {
+ break
+ }
+ c := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(x.Uses == 1 && a.Off()+1 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff64(a.Val()&0xff|c.Val()<<8, a.Off()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off)
+ // result: (MOVBstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [sc] {s} (ADDLconst [off] ptr) mem)
+ // cond: sc.canAdd32(off)
+ // result: (MOVBstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVLQSX(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVLQSX x:(MOVLload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVLQSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVLload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVLQSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLQSX x:(MOVQload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVLQSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVQload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVLQSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLQSX (ANDLconst [c] x))
+ // cond: uint32(c) & 0x80000000 == 0
+ // result: (ANDLconst [c & 0x7fffffff] x)
+ for {
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(uint32(c)&0x80000000 == 0) {
+ break
+ }
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & 0x7fffffff)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVLQSX (MOVLQSX x))
+ // result: (MOVLQSX x)
+ for {
+ if v_0.Op != OpAMD64MOVLQSX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVLQSX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVLQSX (MOVWQSX x))
+ // result: (MOVWQSX x)
+ for {
+ if v_0.Op != OpAMD64MOVWQSX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVWQSX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVLQSX (MOVBQSX x))
+ // result: (MOVBQSX x)
+ for {
+ if v_0.Op != OpAMD64MOVBQSX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVBQSX)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVLQSXload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVLQSXload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVLQSX x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpAMD64MOVLQSX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVLQSXload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVLQSXload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVLQSXload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVLQZX(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVLQZX x:(MOVLload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVLload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVLload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVLload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLQZX x:(MOVQload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVLload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVQload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVLload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLQZX x)
+ // cond: zeroUpper32Bits(x,3)
+ // result: x
+ for {
+ x := v_0
+ if !(zeroUpper32Bits(x, 3)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVLQZX (ANDLconst [c] x))
+ // result: (ANDLconst [c] x)
+ for {
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVLQZX (MOVLQZX x))
+ // result: (MOVLQZX x)
+ for {
+ if v_0.Op != OpAMD64MOVLQZX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVLQZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVLQZX (MOVWQZX x))
+ // result: (MOVWQZX x)
+ for {
+ if v_0.Op != OpAMD64MOVWQZX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVWQZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVLQZX (MOVBQZX x))
+ // result: (MOVBQZX x)
+ for {
+ if v_0.Op != OpAMD64MOVBQZX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVBQZX)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVLatomicload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVLatomicload [off1] {sym} (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVLatomicload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVLatomicload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLatomicload [off1] {sym1} (LEAQ [off2] {sym2} ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVLatomicload [off1+off2] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVLatomicload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVLf2i(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVLf2i <t> (Arg <u> [off] {sym}))
+ // cond: t.Size() == u.Size()
+ // result: @b.Func.Entry (Arg <t> [off] {sym})
+ for {
+ t := v.Type
+ if v_0.Op != OpArg {
+ break
+ }
+ u := v_0.Type
+ off := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ if !(t.Size() == u.Size()) {
+ break
+ }
+ b = b.Func.Entry
+ v0 := b.NewValue0(v.Pos, OpArg, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVLi2f(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVLi2f <t> (Arg <u> [off] {sym}))
+ // cond: t.Size() == u.Size()
+ // result: @b.Func.Entry (Arg <t> [off] {sym})
+ for {
+ t := v.Type
+ if v_0.Op != OpArg {
+ break
+ }
+ u := v_0.Type
+ off := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ if !(t.Size() == u.Size()) {
+ break
+ }
+ b = b.Func.Entry
+ v0 := b.NewValue0(v.Pos, OpArg, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVLload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVLload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVLQZX x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpAMD64MOVLQZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVLload [off1] {sym} (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVLload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVLload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVLload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVLload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVLload [off1] {sym} (ADDLconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVLload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLload [off] {sym} ptr (MOVSSstore [off] {sym} ptr val _))
+ // result: (MOVLf2i val)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVSSstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ val := v_1.Args[1]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ v.reset(OpAMD64MOVLf2i)
+ v.AddArg(val)
+ return true
+ }
+ // match: (MOVLload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVQconst [int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVLstore [off] {sym} ptr (MOVLQSX x) mem)
+ // result: (MOVLstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLQSX {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr (MOVLQZX x) mem)
+ // result: (MOVLstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLQZX {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore [off1] {sym} (ADDQconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVLstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr (MOVLconst [c]) mem)
+ // result: (MOVLstoreconst [makeValAndOff32(int32(c),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpAMD64MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr (MOVQconst [c]) mem)
+ // result: (MOVLstoreconst [makeValAndOff32(int32(c),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpAMD64MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVLstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVLstore [i] {s} p (SHRQconst [32] w) x:(MOVLstore [i-4] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVQstore [i-4] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRQconst || auxIntToInt8(v_1.AuxInt) != 32 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVLstore || auxIntToInt32(x.AuxInt) != i-4 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(i - 4)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVLstore [i] {s} p (SHRQconst [j] w) x:(MOVLstore [i-4] {s} p w0:(SHRQconst [j-32] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVQstore [i-4] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRQconst {
+ break
+ }
+ j := auxIntToInt8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVLstore || auxIntToInt32(x.AuxInt) != i-4 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != OpAMD64SHRQconst || auxIntToInt8(w0.AuxInt) != j-32 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(i - 4)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVLstore [i] {s} p1 (SHRQconst [32] w) x:(MOVLstore [i] {s} p0 w mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 4) && clobber(x)
+ // result: (MOVQstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRQconst || auxIntToInt8(v_1.AuxInt) != 32 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVLstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 4) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVLstore [i] {s} p1 (SHRQconst [j] w) x:(MOVLstore [i] {s} p0 w0:(SHRQconst [j-32] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 4) && clobber(x)
+ // result: (MOVQstore [i] {s} p0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRQconst {
+ break
+ }
+ j := auxIntToInt8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVLstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != OpAMD64SHRQconst || auxIntToInt8(w0.AuxInt) != j-32 || w != w0.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 4) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w0, mem)
+ return true
+ }
+ // match: (MOVLstore [i] {s} p x1:(MOVLload [j] {s2} p2 mem) mem2:(MOVLstore [i-4] {s} p x2:(MOVLload [j-4] {s2} p2 mem) mem))
+ // cond: x1.Uses == 1 && x2.Uses == 1 && mem2.Uses == 1 && clobber(x1, x2, mem2)
+ // result: (MOVQstore [i-4] {s} p (MOVQload [j-4] {s2} p2 mem) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x1 := v_1
+ if x1.Op != OpAMD64MOVLload {
+ break
+ }
+ j := auxIntToInt32(x1.AuxInt)
+ s2 := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p2 := x1.Args[0]
+ mem2 := v_2
+ if mem2.Op != OpAMD64MOVLstore || auxIntToInt32(mem2.AuxInt) != i-4 || auxToSym(mem2.Aux) != s {
+ break
+ }
+ _ = mem2.Args[2]
+ if p != mem2.Args[0] {
+ break
+ }
+ x2 := mem2.Args[1]
+ if x2.Op != OpAMD64MOVLload || auxIntToInt32(x2.AuxInt) != j-4 || auxToSym(x2.Aux) != s2 {
+ break
+ }
+ _ = x2.Args[1]
+ if p2 != x2.Args[0] || mem != x2.Args[1] || mem != mem2.Args[2] || !(x1.Uses == 1 && x2.Uses == 1 && mem2.Uses == 1 && clobber(x1, x2, mem2)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(i - 4)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x2.Pos, OpAMD64MOVQload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(j - 4)
+ v0.Aux = symToAux(s2)
+ v0.AddArg2(p2, mem)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVLstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVLstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVLstore [off1] {sym} (ADDLconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVLstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ADDLload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (ADDLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ADDLload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(OpAMD64ADDLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ANDLload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (ANDLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ANDLload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(OpAMD64ANDLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ORLload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (ORLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ORLload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(OpAMD64ORLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(XORLload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (XORLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64XORLload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(OpAMD64XORLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ADDL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (ADDLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ADDL {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(OpAMD64ADDLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(SUBL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (SUBLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SUBL {
+ break
+ }
+ x := y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ break
+ }
+ v.reset(OpAMD64SUBLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ANDL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (ANDLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ANDL {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(OpAMD64ANDLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(ORL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (ORLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ORL {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(OpAMD64ORLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(XORL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (XORLmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64XORL {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(OpAMD64XORLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(BTCL l:(MOVLload [off] {sym} ptr mem) <t> x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (BTCLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64BTCL {
+ break
+ }
+ t := y.Type
+ x := y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ break
+ }
+ v.reset(OpAMD64BTCLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(l.Pos, OpAMD64ANDLconst, t)
+ v0.AuxInt = int32ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(BTRL l:(MOVLload [off] {sym} ptr mem) <t> x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (BTRLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64BTRL {
+ break
+ }
+ t := y.Type
+ x := y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ break
+ }
+ v.reset(OpAMD64BTRLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(l.Pos, OpAMD64ANDLconst, t)
+ v0.AuxInt = int32ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(BTSL l:(MOVLload [off] {sym} ptr mem) <t> x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (BTSLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64BTSL {
+ break
+ }
+ t := y.Type
+ x := y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ break
+ }
+ v.reset(OpAMD64BTSLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(l.Pos, OpAMD64ANDLconst, t)
+ v0.AuxInt = int32ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr a:(ADDLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (ADDLconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64ADDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr a:(ANDLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (ANDLconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64ANDLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr a:(ORLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (ORLconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64ORLconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64ORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr a:(XORLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (XORLconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64XORLconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64XORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr a:(BTCLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (BTCLconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64BTCLconst {
+ break
+ }
+ c := auxIntToInt8(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64BTCLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr a:(BTRLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (BTRLconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64BTRLconst {
+ break
+ }
+ c := auxIntToInt8(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64BTRLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr a:(BTSLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (BTSLconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64BTSLconst {
+ break
+ }
+ c := auxIntToInt8(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64BTSLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr (MOVLf2i val) mem)
+ // result: (MOVSSstore [off] {sym} ptr val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLf2i {
+ break
+ }
+ val := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64MOVSSstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVLstoreconst [sc] {s} (ADDQconst [off] ptr) mem)
+ // cond: ValAndOff(sc).canAdd32(off)
+ // result: (MOVLstoreconst [ValAndOff(sc).addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(sc).canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstoreconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)
+ // result: (MOVLstoreconst [ValAndOff(sc).addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstoreconst [c] {s} p x:(MOVLstoreconst [a] {s} p mem))
+ // cond: x.Uses == 1 && a.Off() + 4 == c.Off() && clobber(x)
+ // result: (MOVQstore [a.Off32()] {s} p (MOVQconst [a.Val()&0xffffffff | c.Val()<<32]) mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != OpAMD64MOVLstoreconst {
+ break
+ }
+ a := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(x.Uses == 1 && a.Off()+4 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(a.Off32())
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVQconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(a.Val()&0xffffffff | c.Val()<<32)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVLstoreconst [a] {s} p x:(MOVLstoreconst [c] {s} p mem))
+ // cond: x.Uses == 1 && a.Off() + 4 == c.Off() && clobber(x)
+ // result: (MOVQstore [a.Off32()] {s} p (MOVQconst [a.Val()&0xffffffff | c.Val()<<32]) mem)
+ for {
+ a := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != OpAMD64MOVLstoreconst {
+ break
+ }
+ c := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(x.Uses == 1 && a.Off()+4 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(a.Off32())
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVQconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(a.Val()&0xffffffff | c.Val()<<32)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVLstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off)
+ // result: (MOVLstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVLstoreconst [sc] {s} (ADDLconst [off] ptr) mem)
+ // cond: sc.canAdd32(off)
+ // result: (MOVLstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVOload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVOload [off1] {sym} (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVOload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVOload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVOload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVOload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVOload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVOstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (MOVOstore [off1] {sym} (ADDQconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVOstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVOstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVOstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVOstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVOstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVOstore [dstOff] {dstSym} ptr (MOVOload [srcOff] {srcSym} (SB) _) mem)
+ // cond: symIsRO(srcSym)
+ // result: (MOVQstore [dstOff+8] {dstSym} ptr (MOVQconst [int64(read64(srcSym, int64(srcOff)+8, config.ctxt.Arch.ByteOrder))]) (MOVQstore [dstOff] {dstSym} ptr (MOVQconst [int64(read64(srcSym, int64(srcOff), config.ctxt.Arch.ByteOrder))]) mem))
+ for {
+ dstOff := auxIntToInt32(v.AuxInt)
+ dstSym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVOload {
+ break
+ }
+ srcOff := auxIntToInt32(v_1.AuxInt)
+ srcSym := auxToSym(v_1.Aux)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpSB {
+ break
+ }
+ mem := v_2
+ if !(symIsRO(srcSym)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(dstOff + 8)
+ v.Aux = symToAux(dstSym)
+ v0 := b.NewValue0(v_1.Pos, OpAMD64MOVQconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(int64(read64(srcSym, int64(srcOff)+8, config.ctxt.Arch.ByteOrder)))
+ v1 := b.NewValue0(v_1.Pos, OpAMD64MOVQstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(dstOff)
+ v1.Aux = symToAux(dstSym)
+ v2 := b.NewValue0(v_1.Pos, OpAMD64MOVQconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(read64(srcSym, int64(srcOff), config.ctxt.Arch.ByteOrder)))
+ v1.AddArg3(ptr, v2, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVQatomicload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVQatomicload [off1] {sym} (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVQatomicload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVQatomicload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQatomicload [off1] {sym1} (LEAQ [off2] {sym2} ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVQatomicload [off1+off2] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVQatomicload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVQf2i(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVQf2i <t> (Arg <u> [off] {sym}))
+ // cond: t.Size() == u.Size()
+ // result: @b.Func.Entry (Arg <t> [off] {sym})
+ for {
+ t := v.Type
+ if v_0.Op != OpArg {
+ break
+ }
+ u := v_0.Type
+ off := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ if !(t.Size() == u.Size()) {
+ break
+ }
+ b = b.Func.Entry
+ v0 := b.NewValue0(v.Pos, OpArg, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVQi2f(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVQi2f <t> (Arg <u> [off] {sym}))
+ // cond: t.Size() == u.Size()
+ // result: @b.Func.Entry (Arg <t> [off] {sym})
+ for {
+ t := v.Type
+ if v_0.Op != OpArg {
+ break
+ }
+ u := v_0.Type
+ off := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ if !(t.Size() == u.Size()) {
+ break
+ }
+ b = b.Func.Entry
+ v0 := b.NewValue0(v.Pos, OpArg, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVQload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVQload [off] {sym} ptr (MOVQstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVQstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVQload [off1] {sym} (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVQload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVQload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVQload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVQload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVQload [off1] {sym} (ADDLconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVQload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQload [off] {sym} ptr (MOVSDstore [off] {sym} ptr val _))
+ // result: (MOVQf2i val)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVSDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ val := v_1.Args[1]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ v.reset(OpAMD64MOVQf2i)
+ v.AddArg(val)
+ return true
+ }
+ // match: (MOVQload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVQconst [int64(read64(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(read64(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVQstore [off1] {sym} (ADDQconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVQstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVQstore [off] {sym} ptr (MOVQconst [c]) mem)
+ // cond: validVal(c)
+ // result: (MOVQstoreconst [makeValAndOff32(int32(c),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(validVal(c)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVQstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVQstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVQstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVQstore [off1] {sym} (ADDLconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVQstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(ADDQload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (ADDQmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ADDQload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(OpAMD64ADDQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(ANDQload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (ANDQmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ANDQload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(OpAMD64ANDQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(ORQload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (ORQmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ORQload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(OpAMD64ORQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(XORQload x [off] {sym} ptr mem) mem)
+ // cond: y.Uses==1 && clobber(y)
+ // result: (XORQmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64XORQload || auxIntToInt32(y.AuxInt) != off || auxToSym(y.Aux) != sym {
+ break
+ }
+ mem := y.Args[2]
+ x := y.Args[0]
+ if ptr != y.Args[1] || mem != v_2 || !(y.Uses == 1 && clobber(y)) {
+ break
+ }
+ v.reset(OpAMD64XORQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(ADDQ l:(MOVQload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (ADDQmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ADDQ {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(OpAMD64ADDQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(SUBQ l:(MOVQload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (SUBQmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64SUBQ {
+ break
+ }
+ x := y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ break
+ }
+ v.reset(OpAMD64SUBQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(ANDQ l:(MOVQload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (ANDQmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ANDQ {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(OpAMD64ANDQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(ORQ l:(MOVQload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (ORQmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64ORQ {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(OpAMD64ORQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(XORQ l:(MOVQload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (XORQmodify [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64XORQ {
+ break
+ }
+ _ = y.Args[1]
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ l := y_0
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ continue
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] {
+ continue
+ }
+ x := y_1
+ if mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ continue
+ }
+ v.reset(OpAMD64XORQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(BTCQ l:(MOVQload [off] {sym} ptr mem) <t> x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (BTCQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64BTCQ {
+ break
+ }
+ t := y.Type
+ x := y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ break
+ }
+ v.reset(OpAMD64BTCQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(l.Pos, OpAMD64ANDQconst, t)
+ v0.AuxInt = int32ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(BTRQ l:(MOVQload [off] {sym} ptr mem) <t> x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (BTRQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64BTRQ {
+ break
+ }
+ t := y.Type
+ x := y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ break
+ }
+ v.reset(OpAMD64BTRQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(l.Pos, OpAMD64ANDQconst, t)
+ v0.AuxInt = int32ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(BTSQ l:(MOVQload [off] {sym} ptr mem) <t> x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
+ // result: (BTSQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ y := v_1
+ if y.Op != OpAMD64BTSQ {
+ break
+ }
+ t := y.Type
+ x := y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ if ptr != l.Args[0] || mem != v_2 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) {
+ break
+ }
+ v.reset(OpAMD64BTSQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(l.Pos, OpAMD64ANDQconst, t)
+ v0.AuxInt = int32ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVQstore [off] {sym} ptr a:(ADDQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (ADDQconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64ADDQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstore [off] {sym} ptr a:(ANDQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (ANDQconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64ANDQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstore [off] {sym} ptr a:(ORQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (ORQconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64ORQconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64ORQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstore [off] {sym} ptr a:(XORQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (XORQconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64XORQconst {
+ break
+ }
+ c := auxIntToInt32(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64XORQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstore [off] {sym} ptr a:(BTCQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (BTCQconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64BTCQconst {
+ break
+ }
+ c := auxIntToInt8(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64BTCQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstore [off] {sym} ptr a:(BTRQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (BTRQconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64BTRQconst {
+ break
+ }
+ c := auxIntToInt8(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64BTRQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstore [off] {sym} ptr a:(BTSQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c),int64(off)) && clobber(l, a)
+ // result: (BTSQconstmodify {sym} [makeValAndOff32(int32(c),off)] ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ a := v_1
+ if a.Op != OpAMD64BTSQconst {
+ break
+ }
+ c := auxIntToInt8(a.AuxInt)
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
+ break
+ }
+ mem := l.Args[1]
+ ptr2 := l.Args[0]
+ if mem != v_2 || !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(int64(c), int64(off)) && clobber(l, a)) {
+ break
+ }
+ v.reset(OpAMD64BTSQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstore [off] {sym} ptr (MOVQf2i val) mem)
+ // result: (MOVSDstore [off] {sym} ptr val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVQf2i {
+ break
+ }
+ val := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64MOVSDstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVQstoreconst [sc] {s} (ADDQconst [off] ptr) mem)
+ // cond: ValAndOff(sc).canAdd32(off)
+ // result: (MOVQstoreconst [ValAndOff(sc).addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(sc).canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstoreconst)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstoreconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)
+ // result: (MOVQstoreconst [ValAndOff(sc).addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstoreconst)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstoreconst [c] {s} p x:(MOVQstoreconst [c2] {s} p mem))
+ // cond: config.useSSE && x.Uses == 1 && c2.Off() + 8 == c.Off() && c.Val() == 0 && c2.Val() == 0 && clobber(x)
+ // result: (MOVOstore [c2.Off32()] {s} p (MOVOconst [0]) mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != OpAMD64MOVQstoreconst {
+ break
+ }
+ c2 := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(config.useSSE && x.Uses == 1 && c2.Off()+8 == c.Off() && c.Val() == 0 && c2.Val() == 0 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVOstore)
+ v.AuxInt = int32ToAuxInt(c2.Off32())
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVOconst, types.TypeInt128)
+ v0.AuxInt = int128ToAuxInt(0)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVQstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off)
+ // result: (MOVQstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstoreconst [sc] {s} (ADDLconst [off] ptr) mem)
+ // cond: sc.canAdd32(off)
+ // result: (MOVQstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVQstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVSDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVSDload [off1] {sym} (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVSDload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVSDload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVSDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVSDload [off] {sym} ptr (MOVQstore [off] {sym} ptr val _))
+ // result: (MOVQi2f val)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVQstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ val := v_1.Args[1]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ v.reset(OpAMD64MOVQi2f)
+ v.AddArg(val)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVSDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVSDstore [off1] {sym} (ADDQconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVSDstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVSDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVSDstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVSDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVSDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVSDstore [off] {sym} ptr (MOVQi2f val) mem)
+ // result: (MOVQstore [off] {sym} ptr val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVQi2f {
+ break
+ }
+ val := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVSSload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVSSload [off1] {sym} (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVSSload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVSSload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVSSload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVSSload [off] {sym} ptr (MOVLstore [off] {sym} ptr val _))
+ // result: (MOVLi2f val)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ val := v_1.Args[1]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ v.reset(OpAMD64MOVLi2f)
+ v.AddArg(val)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVSSstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVSSstore [off1] {sym} (ADDQconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVSSstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVSSstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVSSstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVSSstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVSSstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVSSstore [off] {sym} ptr (MOVLi2f val) mem)
+ // result: (MOVLstore [off] {sym} ptr val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLi2f {
+ break
+ }
+ val := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVWQSX(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVWQSX x:(MOVWload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWQSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVWload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVWQSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWQSX x:(MOVLload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWQSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVLload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVWQSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWQSX x:(MOVQload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWQSXload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVQload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVWQSXload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWQSX (ANDLconst [c] x))
+ // cond: c & 0x8000 == 0
+ // result: (ANDLconst [c & 0x7fff] x)
+ for {
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c&0x8000 == 0) {
+ break
+ }
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & 0x7fff)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWQSX (MOVWQSX x))
+ // result: (MOVWQSX x)
+ for {
+ if v_0.Op != OpAMD64MOVWQSX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVWQSX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWQSX (MOVBQSX x))
+ // result: (MOVBQSX x)
+ for {
+ if v_0.Op != OpAMD64MOVBQSX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVBQSX)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVWQSXload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWQSXload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVWQSX x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVWstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpAMD64MOVWQSX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWQSXload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVWQSXload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVWQSXload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVWQZX(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVWQZX x:(MOVWload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVWload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVWload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWQZX x:(MOVLload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVLload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVWload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWQZX x:(MOVQload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWload <v.Type> [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpAMD64MOVQload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpAMD64MOVWload, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWQZX x)
+ // cond: zeroUpper48Bits(x,3)
+ // result: x
+ for {
+ x := v_0
+ if !(zeroUpper48Bits(x, 3)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWQZX (ANDLconst [c] x))
+ // result: (ANDLconst [c & 0xffff] x)
+ for {
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(c & 0xffff)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWQZX (MOVWQZX x))
+ // result: (MOVWQZX x)
+ for {
+ if v_0.Op != OpAMD64MOVWQZX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVWQZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWQZX (MOVBQZX x))
+ // result: (MOVBQZX x)
+ for {
+ if v_0.Op != OpAMD64MOVBQZX {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64MOVBQZX)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVWload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVWQZX x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVWstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpAMD64MOVWQZX)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWload [off1] {sym} (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
+ // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym} (ADDLconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVLconst [int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVWstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVWstore [off] {sym} ptr (MOVWQSX x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVWQSX {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWQZX x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVWQZX {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym} (ADDQconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVLconst [c]) mem)
+ // result: (MOVWstoreconst [makeValAndOff32(int32(int16(c)),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpAMD64MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(int16(c)), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVQconst [c]) mem)
+ // result: (MOVWstoreconst [makeValAndOff32(int32(int16(c)),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpAMD64MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(int16(c)), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVLstore [i-2] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRLconst || auxIntToInt8(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVWstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p (SHRQconst [16] w) x:(MOVWstore [i-2] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVLstore [i-2] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRQconst || auxIntToInt8(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVWstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p w0:(SHRLconst [j-16] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVLstore [i-2] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRLconst {
+ break
+ }
+ j := auxIntToInt8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVWstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != OpAMD64SHRLconst || auxIntToInt8(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p (SHRQconst [j] w) x:(MOVWstore [i-2] {s} p w0:(SHRQconst [j-16] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVLstore [i-2] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpAMD64SHRQconst {
+ break
+ }
+ j := auxIntToInt8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVWstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != OpAMD64SHRQconst || auxIntToInt8(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p1 (SHRLconst [16] w) x:(MOVWstore [i] {s} p0 w mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)
+ // result: (MOVLstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRLconst || auxIntToInt8(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVWstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p1 (SHRQconst [16] w) x:(MOVWstore [i] {s} p0 w mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)
+ // result: (MOVLstore [i] {s} p0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRQconst || auxIntToInt8(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVWstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p1 (SHRLconst [j] w) x:(MOVWstore [i] {s} p0 w0:(SHRLconst [j-16] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)
+ // result: (MOVLstore [i] {s} p0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRLconst {
+ break
+ }
+ j := auxIntToInt8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVWstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != OpAMD64SHRLconst || auxIntToInt8(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w0, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p1 (SHRQconst [j] w) x:(MOVWstore [i] {s} p0 w0:(SHRQconst [j-16] w) mem))
+ // cond: x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)
+ // result: (MOVLstore [i] {s} p0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpAMD64SHRQconst {
+ break
+ }
+ j := auxIntToInt8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpAMD64MOVWstore || auxIntToInt32(x.AuxInt) != i || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ p0 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != OpAMD64SHRQconst || auxIntToInt8(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && sequentialAddresses(p0, p1, 2) && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p0, w0, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p x1:(MOVWload [j] {s2} p2 mem) mem2:(MOVWstore [i-2] {s} p x2:(MOVWload [j-2] {s2} p2 mem) mem))
+ // cond: x1.Uses == 1 && x2.Uses == 1 && mem2.Uses == 1 && clobber(x1, x2, mem2)
+ // result: (MOVLstore [i-2] {s} p (MOVLload [j-2] {s2} p2 mem) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x1 := v_1
+ if x1.Op != OpAMD64MOVWload {
+ break
+ }
+ j := auxIntToInt32(x1.AuxInt)
+ s2 := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p2 := x1.Args[0]
+ mem2 := v_2
+ if mem2.Op != OpAMD64MOVWstore || auxIntToInt32(mem2.AuxInt) != i-2 || auxToSym(mem2.Aux) != s {
+ break
+ }
+ _ = mem2.Args[2]
+ if p != mem2.Args[0] {
+ break
+ }
+ x2 := mem2.Args[1]
+ if x2.Op != OpAMD64MOVWload || auxIntToInt32(x2.AuxInt) != j-2 || auxToSym(x2.Aux) != s2 {
+ break
+ }
+ _ = x2.Args[1]
+ if p2 != x2.Args[0] || mem != x2.Args[1] || mem != mem2.Args[2] || !(x1.Uses == 1 && x2.Uses == 1 && mem2.Uses == 1 && clobber(x1, x2, mem2)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x2.Pos, OpAMD64MOVLload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(j - 2)
+ v0.Aux = symToAux(s2)
+ v0.AddArg2(p2, mem)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
+ // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym} (ADDLconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVWstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstoreconst [sc] {s} (ADDQconst [off] ptr) mem)
+ // cond: ValAndOff(sc).canAdd32(off)
+ // result: (MOVWstoreconst [ValAndOff(sc).addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(sc).canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)
+ // result: (MOVWstoreconst [ValAndOff(sc).addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem))
+ // cond: x.Uses == 1 && a.Off() + 2 == c.Off() && clobber(x)
+ // result: (MOVLstoreconst [makeValAndOff64(a.Val()&0xffff | c.Val()<<16, a.Off())] {s} p mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != OpAMD64MOVWstoreconst {
+ break
+ }
+ a := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(x.Uses == 1 && a.Off()+2 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff64(a.Val()&0xffff|c.Val()<<16, a.Off()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [a] {s} p x:(MOVWstoreconst [c] {s} p mem))
+ // cond: x.Uses == 1 && a.Off() + 2 == c.Off() && clobber(x)
+ // result: (MOVLstoreconst [makeValAndOff64(a.Val()&0xffff | c.Val()<<16, a.Off())] {s} p mem)
+ for {
+ a := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != OpAMD64MOVWstoreconst {
+ break
+ }
+ c := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(x.Uses == 1 && a.Off()+2 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(OpAMD64MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff64(a.Val()&0xffff|c.Val()<<16, a.Off()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off)
+ // result: (MOVWstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAL {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [sc] {s} (ADDLconst [off] ptr) mem)
+ // cond: sc.canAdd32(off)
+ // result: (MOVWstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpAMD64MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MULL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULL x (MOVLconst [c]))
+ // result: (MULLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64MULLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MULLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MULLconst [c] (MULLconst [d] x))
+ // result: (MULLconst [c * d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MULLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64MULLconst)
+ v.AuxInt = int32ToAuxInt(c * d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MULLconst [-9] x)
+ // result: (NEGL (LEAL8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != -9 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64NEGL)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [-5] x)
+ // result: (NEGL (LEAL4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != -5 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64NEGL)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [-3] x)
+ // result: (NEGL (LEAL2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != -3 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64NEGL)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [-1] x)
+ // result: (NEGL x)
+ for {
+ if auxIntToInt32(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64NEGL)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MULLconst [ 0] _)
+ // result: (MOVLconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (MULLconst [ 1] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (MULLconst [ 3] x)
+ // result: (LEAL2 x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 3 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL2)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (MULLconst [ 5] x)
+ // result: (LEAL4 x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 5 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL4)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (MULLconst [ 7] x)
+ // result: (LEAL2 x (LEAL2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 7 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL2)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [ 9] x)
+ // result: (LEAL8 x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 9 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL8)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (MULLconst [11] x)
+ // result: (LEAL2 x (LEAL4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 11 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL2)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [13] x)
+ // result: (LEAL4 x (LEAL2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 13 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL4)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [19] x)
+ // result: (LEAL2 x (LEAL8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 19 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL2)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [21] x)
+ // result: (LEAL4 x (LEAL4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 21 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL4)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [25] x)
+ // result: (LEAL8 x (LEAL2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 25 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [27] x)
+ // result: (LEAL8 (LEAL2 <v.Type> x x) (LEAL2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 27 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, v0)
+ return true
+ }
+ // match: (MULLconst [37] x)
+ // result: (LEAL4 x (LEAL8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 37 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL4)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [41] x)
+ // result: (LEAL8 x (LEAL4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 41 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [45] x)
+ // result: (LEAL8 (LEAL4 <v.Type> x x) (LEAL4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 45 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, v0)
+ return true
+ }
+ // match: (MULLconst [73] x)
+ // result: (LEAL8 x (LEAL8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 73 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLconst [81] x)
+ // result: (LEAL8 (LEAL8 <v.Type> x x) (LEAL8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 81 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAL8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, v0)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: isPowerOfTwo64(int64(c)+1) && c >= 15
+ // result: (SUBL (SHLLconst <v.Type> [int8(log64(int64(c)+1))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo64(int64(c)+1) && c >= 15) {
+ break
+ }
+ v.reset(OpAMD64SUBL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type)
+ v0.AuxInt = int8ToAuxInt(int8(log64(int64(c) + 1)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: isPowerOfTwo32(c-1) && c >= 17
+ // result: (LEAL1 (SHLLconst <v.Type> [int8(log32(c-1))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-1) && c >= 17) {
+ break
+ }
+ v.reset(OpAMD64LEAL1)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c - 1)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: isPowerOfTwo32(c-2) && c >= 34
+ // result: (LEAL2 (SHLLconst <v.Type> [int8(log32(c-2))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-2) && c >= 34) {
+ break
+ }
+ v.reset(OpAMD64LEAL2)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c - 2)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: isPowerOfTwo32(c-4) && c >= 68
+ // result: (LEAL4 (SHLLconst <v.Type> [int8(log32(c-4))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-4) && c >= 68) {
+ break
+ }
+ v.reset(OpAMD64LEAL4)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c - 4)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: isPowerOfTwo32(c-8) && c >= 136
+ // result: (LEAL8 (SHLLconst <v.Type> [int8(log32(c-8))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-8) && c >= 136) {
+ break
+ }
+ v.reset(OpAMD64LEAL8)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c - 8)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: c%3 == 0 && isPowerOfTwo32(c/3)
+ // result: (SHLLconst [int8(log32(c/3))] (LEAL2 <v.Type> x x))
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c%3 == 0 && isPowerOfTwo32(c/3)) {
+ break
+ }
+ v.reset(OpAMD64SHLLconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c / 3)))
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: c%5 == 0 && isPowerOfTwo32(c/5)
+ // result: (SHLLconst [int8(log32(c/5))] (LEAL4 <v.Type> x x))
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c%5 == 0 && isPowerOfTwo32(c/5)) {
+ break
+ }
+ v.reset(OpAMD64SHLLconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c / 5)))
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [c] x)
+ // cond: c%9 == 0 && isPowerOfTwo32(c/9)
+ // result: (SHLLconst [int8(log32(c/9))] (LEAL8 <v.Type> x x))
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c%9 == 0 && isPowerOfTwo32(c/9)) {
+ break
+ }
+ v.reset(OpAMD64SHLLconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c / 9)))
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [c*d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(c * d)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MULQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULQ x (MOVQconst [c]))
+ // cond: is32Bit(c)
+ // result: (MULQconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpAMD64MULQconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MULQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MULQconst [c] (MULQconst [d] x))
+ // cond: is32Bit(int64(c)*int64(d))
+ // result: (MULQconst [c * d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MULQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) * int64(d))) {
+ break
+ }
+ v.reset(OpAMD64MULQconst)
+ v.AuxInt = int32ToAuxInt(c * d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MULQconst [-9] x)
+ // result: (NEGQ (LEAQ8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != -9 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64NEGQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULQconst [-5] x)
+ // result: (NEGQ (LEAQ4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != -5 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64NEGQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULQconst [-3] x)
+ // result: (NEGQ (LEAQ2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != -3 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64NEGQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULQconst [-1] x)
+ // result: (NEGQ x)
+ for {
+ if auxIntToInt32(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64NEGQ)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MULQconst [ 0] _)
+ // result: (MOVQconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (MULQconst [ 1] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (MULQconst [ 3] x)
+ // result: (LEAQ2 x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 3 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ2)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (MULQconst [ 5] x)
+ // result: (LEAQ4 x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 5 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ4)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (MULQconst [ 7] x)
+ // result: (LEAQ2 x (LEAQ2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 7 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ2)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULQconst [ 9] x)
+ // result: (LEAQ8 x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 9 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ8)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (MULQconst [11] x)
+ // result: (LEAQ2 x (LEAQ4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 11 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ2)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULQconst [13] x)
+ // result: (LEAQ4 x (LEAQ2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 13 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ4)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULQconst [19] x)
+ // result: (LEAQ2 x (LEAQ8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 19 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ2)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULQconst [21] x)
+ // result: (LEAQ4 x (LEAQ4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 21 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ4)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULQconst [25] x)
+ // result: (LEAQ8 x (LEAQ2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 25 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULQconst [27] x)
+ // result: (LEAQ8 (LEAQ2 <v.Type> x x) (LEAQ2 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 27 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, v0)
+ return true
+ }
+ // match: (MULQconst [37] x)
+ // result: (LEAQ4 x (LEAQ8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 37 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ4)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULQconst [41] x)
+ // result: (LEAQ8 x (LEAQ4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 41 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULQconst [45] x)
+ // result: (LEAQ8 (LEAQ4 <v.Type> x x) (LEAQ4 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 45 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, v0)
+ return true
+ }
+ // match: (MULQconst [73] x)
+ // result: (LEAQ8 x (LEAQ8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 73 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULQconst [81] x)
+ // result: (LEAQ8 (LEAQ8 <v.Type> x x) (LEAQ8 <v.Type> x x))
+ for {
+ if auxIntToInt32(v.AuxInt) != 81 {
+ break
+ }
+ x := v_0
+ v.reset(OpAMD64LEAQ8)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, v0)
+ return true
+ }
+ // match: (MULQconst [c] x)
+ // cond: isPowerOfTwo64(int64(c)+1) && c >= 15
+ // result: (SUBQ (SHLQconst <v.Type> [int8(log64(int64(c)+1))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo64(int64(c)+1) && c >= 15) {
+ break
+ }
+ v.reset(OpAMD64SUBQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type)
+ v0.AuxInt = int8ToAuxInt(int8(log64(int64(c) + 1)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULQconst [c] x)
+ // cond: isPowerOfTwo32(c-1) && c >= 17
+ // result: (LEAQ1 (SHLQconst <v.Type> [int8(log32(c-1))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-1) && c >= 17) {
+ break
+ }
+ v.reset(OpAMD64LEAQ1)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c - 1)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULQconst [c] x)
+ // cond: isPowerOfTwo32(c-2) && c >= 34
+ // result: (LEAQ2 (SHLQconst <v.Type> [int8(log32(c-2))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-2) && c >= 34) {
+ break
+ }
+ v.reset(OpAMD64LEAQ2)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c - 2)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULQconst [c] x)
+ // cond: isPowerOfTwo32(c-4) && c >= 68
+ // result: (LEAQ4 (SHLQconst <v.Type> [int8(log32(c-4))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-4) && c >= 68) {
+ break
+ }
+ v.reset(OpAMD64LEAQ4)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c - 4)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULQconst [c] x)
+ // cond: isPowerOfTwo32(c-8) && c >= 136
+ // result: (LEAQ8 (SHLQconst <v.Type> [int8(log32(c-8))] x) x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c-8) && c >= 136) {
+ break
+ }
+ v.reset(OpAMD64LEAQ8)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c - 8)))
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (MULQconst [c] x)
+ // cond: c%3 == 0 && isPowerOfTwo32(c/3)
+ // result: (SHLQconst [int8(log32(c/3))] (LEAQ2 <v.Type> x x))
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c%3 == 0 && isPowerOfTwo32(c/3)) {
+ break
+ }
+ v.reset(OpAMD64SHLQconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c / 3)))
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULQconst [c] x)
+ // cond: c%5 == 0 && isPowerOfTwo32(c/5)
+ // result: (SHLQconst [int8(log32(c/5))] (LEAQ4 <v.Type> x x))
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c%5 == 0 && isPowerOfTwo32(c/5)) {
+ break
+ }
+ v.reset(OpAMD64SHLQconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c / 5)))
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULQconst [c] x)
+ // cond: c%9 == 0 && isPowerOfTwo32(c/9)
+ // result: (SHLQconst [int8(log32(c/9))] (LEAQ8 <v.Type> x x))
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c%9 == 0 && isPowerOfTwo32(c/9)) {
+ break
+ }
+ v.reset(OpAMD64SHLQconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c / 9)))
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MULQconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [int64(c)*d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(c) * d)
+ return true
+ }
+ // match: (MULQconst [c] (NEGQ x))
+ // cond: c != -(1<<31)
+ // result: (MULQconst [-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64NEGQ {
+ break
+ }
+ x := v_0.Args[0]
+ if !(c != -(1 << 31)) {
+ break
+ }
+ v.reset(OpAMD64MULQconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MULSD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULSD x l:(MOVSDload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (MULSDload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVSDload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64MULSDload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MULSDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MULSDload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MULSDload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MULSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (MULSDload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MULSDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MULSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (MULSDload x [off] {sym} ptr (MOVQstore [off] {sym} ptr y _))
+ // result: (MULSD x (MOVQi2f y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVQstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64MULSD)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVQi2f, typ.Float64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MULSS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULSS x l:(MOVSSload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (MULSSload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVSSload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64MULSSload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MULSSload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MULSSload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (MULSSload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64MULSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (MULSSload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MULSSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64MULSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (MULSSload x [off] {sym} ptr (MOVLstore [off] {sym} ptr y _))
+ // result: (MULSS x (MOVLi2f y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVLstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64MULSS)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVLi2f, typ.Float32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64NEGL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEGL (NEGL x))
+ // result: x
+ for {
+ if v_0.Op != OpAMD64NEGL {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (NEGL s:(SUBL x y))
+ // cond: s.Uses == 1
+ // result: (SUBL y x)
+ for {
+ s := v_0
+ if s.Op != OpAMD64SUBL {
+ break
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ if !(s.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SUBL)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (NEGL (MOVLconst [c]))
+ // result: (MOVLconst [-c])
+ for {
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64NEGQ(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEGQ (NEGQ x))
+ // result: x
+ for {
+ if v_0.Op != OpAMD64NEGQ {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (NEGQ s:(SUBQ x y))
+ // cond: s.Uses == 1
+ // result: (SUBQ y x)
+ for {
+ s := v_0
+ if s.Op != OpAMD64SUBQ {
+ break
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ if !(s.Uses == 1) {
+ break
+ }
+ v.reset(OpAMD64SUBQ)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (NEGQ (MOVQconst [c]))
+ // result: (MOVQconst [-c])
+ for {
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(-c)
+ return true
+ }
+ // match: (NEGQ (ADDQconst [c] (NEGQ x)))
+ // cond: c != -(1<<31)
+ // result: (ADDQconst [-c] x)
+ for {
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64NEGQ {
+ break
+ }
+ x := v_0_0.Args[0]
+ if !(c != -(1 << 31)) {
+ break
+ }
+ v.reset(OpAMD64ADDQconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64NOTL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NOTL (MOVLconst [c]))
+ // result: (MOVLconst [^c])
+ for {
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(^c)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64NOTQ(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NOTQ (MOVQconst [c]))
+ // result: (MOVQconst [^c])
+ for {
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(^c)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ORL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ORL (SHLL (MOVLconst [1]) y) x)
+ // result: (BTSL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLL {
+ continue
+ }
+ y := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_0_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpAMD64BTSL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ORL (MOVLconst [c]) x)
+ // cond: isUint32PowerOfTwo(int64(c)) && uint64(c) >= 128
+ // result: (BTSLconst [int8(log32(c))] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ if !(isUint32PowerOfTwo(int64(c)) && uint64(c) >= 128) {
+ continue
+ }
+ v.reset(OpAMD64BTSLconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORL x (MOVLconst [c]))
+ // result: (ORLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ORLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORL (SHLLconst x [c]) (SHRLconst x [d]))
+ // cond: d==32-c
+ // result: (ROLLconst x [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRLconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 32-c) {
+ continue
+ }
+ v.reset(OpAMD64ROLLconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORL <t> (SHLLconst x [c]) (SHRWconst x [d]))
+ // cond: d==16-c && c < 16 && t.Size() == 2
+ // result: (ROLWconst x [c])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRWconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 16-c && c < 16 && t.Size() == 2) {
+ continue
+ }
+ v.reset(OpAMD64ROLWconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORL <t> (SHLLconst x [c]) (SHRBconst x [d]))
+ // cond: d==8-c && c < 8 && t.Size() == 1
+ // result: (ROLBconst x [c])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRBconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 8-c && c < 8 && t.Size() == 1) {
+ continue
+ }
+ v.reset(OpAMD64ROLBconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORL (SHLL x y) (ANDL (SHRL x (NEGQ y)) (SBBLcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [31]) [-32])) [32]))))
+ // result: (ROLL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLL {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64ANDL {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHRL {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGQ || y != v_1_0_1.Args[0] || v_1_1.Op != OpAMD64SBBLcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPQconst || auxIntToInt32(v_1_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGQ {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -32 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 31 || y != v_1_1_0_0_0_0.Args[0] {
+ continue
+ }
+ v.reset(OpAMD64ROLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL (SHLL x y) (ANDL (SHRL x (NEGL y)) (SBBLcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [31]) [-32])) [32]))))
+ // result: (ROLL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLL {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64ANDL {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHRL {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGL || y != v_1_0_1.Args[0] || v_1_1.Op != OpAMD64SBBLcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPLconst || auxIntToInt32(v_1_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGL {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDLconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -32 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDLconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 31 || y != v_1_1_0_0_0_0.Args[0] {
+ continue
+ }
+ v.reset(OpAMD64ROLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL (SHRL x y) (ANDL (SHLL x (NEGQ y)) (SBBLcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [31]) [-32])) [32]))))
+ // result: (RORL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHRL {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64ANDL {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHLL {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGQ || y != v_1_0_1.Args[0] || v_1_1.Op != OpAMD64SBBLcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPQconst || auxIntToInt32(v_1_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGQ {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -32 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 31 || y != v_1_1_0_0_0_0.Args[0] {
+ continue
+ }
+ v.reset(OpAMD64RORL)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL (SHRL x y) (ANDL (SHLL x (NEGL y)) (SBBLcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [31]) [-32])) [32]))))
+ // result: (RORL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHRL {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64ANDL {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHLL {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGL || y != v_1_0_1.Args[0] || v_1_1.Op != OpAMD64SBBLcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPLconst || auxIntToInt32(v_1_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGL {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDLconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -32 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDLconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 31 || y != v_1_1_0_0_0_0.Args[0] {
+ continue
+ }
+ v.reset(OpAMD64RORL)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL (SHLL x (ANDQconst y [15])) (ANDL (SHRW x (NEGQ (ADDQconst (ANDQconst y [15]) [-16]))) (SBBLcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [15]) [-16])) [16]))))
+ // cond: v.Type.Size() == 2
+ // result: (ROLW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLL {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64ANDQconst || auxIntToInt32(v_0_1.AuxInt) != 15 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpAMD64ANDL {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHRW {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGQ {
+ continue
+ }
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_1_0_1_0.AuxInt) != -16 {
+ continue
+ }
+ v_1_0_1_0_0 := v_1_0_1_0.Args[0]
+ if v_1_0_1_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_1_0_1_0_0.AuxInt) != 15 || y != v_1_0_1_0_0.Args[0] || v_1_1.Op != OpAMD64SBBLcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPQconst || auxIntToInt32(v_1_1_0.AuxInt) != 16 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGQ {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -16 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 15 || y != v_1_1_0_0_0_0.Args[0] || !(v.Type.Size() == 2) {
+ continue
+ }
+ v.reset(OpAMD64ROLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL (SHLL x (ANDLconst y [15])) (ANDL (SHRW x (NEGL (ADDLconst (ANDLconst y [15]) [-16]))) (SBBLcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [15]) [-16])) [16]))))
+ // cond: v.Type.Size() == 2
+ // result: (ROLW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLL {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64ANDLconst || auxIntToInt32(v_0_1.AuxInt) != 15 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpAMD64ANDL {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHRW {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGL {
+ continue
+ }
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpAMD64ADDLconst || auxIntToInt32(v_1_0_1_0.AuxInt) != -16 {
+ continue
+ }
+ v_1_0_1_0_0 := v_1_0_1_0.Args[0]
+ if v_1_0_1_0_0.Op != OpAMD64ANDLconst || auxIntToInt32(v_1_0_1_0_0.AuxInt) != 15 || y != v_1_0_1_0_0.Args[0] || v_1_1.Op != OpAMD64SBBLcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPLconst || auxIntToInt32(v_1_1_0.AuxInt) != 16 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGL {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDLconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -16 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDLconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 15 || y != v_1_1_0_0_0_0.Args[0] || !(v.Type.Size() == 2) {
+ continue
+ }
+ v.reset(OpAMD64ROLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL (SHRW x (ANDQconst y [15])) (SHLL x (NEGQ (ADDQconst (ANDQconst y [15]) [-16]))))
+ // cond: v.Type.Size() == 2
+ // result: (RORW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHRW {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64ANDQconst || auxIntToInt32(v_0_1.AuxInt) != 15 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpAMD64SHLL {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpAMD64NEGQ {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_1_1_0.AuxInt) != -16 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_1_1_0_0.AuxInt) != 15 || y != v_1_1_0_0.Args[0] || !(v.Type.Size() == 2) {
+ continue
+ }
+ v.reset(OpAMD64RORW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ORL (SHRW x (ANDLconst y [15])) (SHLL x (NEGL (ADDLconst (ANDLconst y [15]) [-16]))))
+ // cond: v.Type.Size() == 2
+ // result: (RORW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHRW {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64ANDLconst || auxIntToInt32(v_0_1.AuxInt) != 15 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpAMD64SHLL {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpAMD64NEGL {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64ADDLconst || auxIntToInt32(v_1_1_0.AuxInt) != -16 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64ANDLconst || auxIntToInt32(v_1_1_0_0.AuxInt) != 15 || y != v_1_1_0_0.Args[0] || !(v.Type.Size() == 2) {
+ continue
+ }
+ v.reset(OpAMD64RORW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ORL (SHLL x (ANDQconst y [ 7])) (ANDL (SHRB x (NEGQ (ADDQconst (ANDQconst y [ 7]) [ -8]))) (SBBLcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [ 7]) [ -8])) [ 8]))))
+ // cond: v.Type.Size() == 1
+ // result: (ROLB x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLL {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64ANDQconst || auxIntToInt32(v_0_1.AuxInt) != 7 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpAMD64ANDL {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHRB {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGQ {
+ continue
+ }
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_1_0_1_0.AuxInt) != -8 {
+ continue
+ }
+ v_1_0_1_0_0 := v_1_0_1_0.Args[0]
+ if v_1_0_1_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_1_0_1_0_0.AuxInt) != 7 || y != v_1_0_1_0_0.Args[0] || v_1_1.Op != OpAMD64SBBLcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPQconst || auxIntToInt32(v_1_1_0.AuxInt) != 8 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGQ {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -8 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 7 || y != v_1_1_0_0_0_0.Args[0] || !(v.Type.Size() == 1) {
+ continue
+ }
+ v.reset(OpAMD64ROLB)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL (SHLL x (ANDLconst y [ 7])) (ANDL (SHRB x (NEGL (ADDLconst (ANDLconst y [ 7]) [ -8]))) (SBBLcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [ 7]) [ -8])) [ 8]))))
+ // cond: v.Type.Size() == 1
+ // result: (ROLB x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLL {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64ANDLconst || auxIntToInt32(v_0_1.AuxInt) != 7 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpAMD64ANDL {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHRB {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGL {
+ continue
+ }
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpAMD64ADDLconst || auxIntToInt32(v_1_0_1_0.AuxInt) != -8 {
+ continue
+ }
+ v_1_0_1_0_0 := v_1_0_1_0.Args[0]
+ if v_1_0_1_0_0.Op != OpAMD64ANDLconst || auxIntToInt32(v_1_0_1_0_0.AuxInt) != 7 || y != v_1_0_1_0_0.Args[0] || v_1_1.Op != OpAMD64SBBLcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPLconst || auxIntToInt32(v_1_1_0.AuxInt) != 8 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGL {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDLconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -8 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDLconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 7 || y != v_1_1_0_0_0_0.Args[0] || !(v.Type.Size() == 1) {
+ continue
+ }
+ v.reset(OpAMD64ROLB)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL (SHRB x (ANDQconst y [ 7])) (SHLL x (NEGQ (ADDQconst (ANDQconst y [ 7]) [ -8]))))
+ // cond: v.Type.Size() == 1
+ // result: (RORB x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHRB {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64ANDQconst || auxIntToInt32(v_0_1.AuxInt) != 7 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpAMD64SHLL {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpAMD64NEGQ {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_1_1_0.AuxInt) != -8 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_1_1_0_0.AuxInt) != 7 || y != v_1_1_0_0.Args[0] || !(v.Type.Size() == 1) {
+ continue
+ }
+ v.reset(OpAMD64RORB)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ORL (SHRB x (ANDLconst y [ 7])) (SHLL x (NEGL (ADDLconst (ANDLconst y [ 7]) [ -8]))))
+ // cond: v.Type.Size() == 1
+ // result: (RORB x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHRB {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64ANDLconst || auxIntToInt32(v_0_1.AuxInt) != 7 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpAMD64SHLL {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpAMD64NEGL {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64ADDLconst || auxIntToInt32(v_1_1_0.AuxInt) != -8 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64ANDLconst || auxIntToInt32(v_1_1_0_0.AuxInt) != 7 || y != v_1_1_0_0.Args[0] || !(v.Type.Size() == 1) {
+ continue
+ }
+ v.reset(OpAMD64RORB)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ORL x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORL x0:(MOVBload [i0] {s} p mem) sh:(SHLLconst [8] x1:(MOVBload [i1] {s} p mem)))
+ // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLLconst || auxIntToInt8(sh.AuxInt) != 8 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpAMD64MOVWload, typ.UInt16)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORL x0:(MOVBload [i] {s} p0 mem) sh:(SHLLconst [8] x1:(MOVBload [i] {s} p1 mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVWload [i] {s} p0 mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p0 := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLLconst || auxIntToInt8(sh.AuxInt) != 8 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpAMD64MOVBload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if mem != x1.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpAMD64MOVWload, typ.UInt16)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p0, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORL x0:(MOVWload [i0] {s} p mem) sh:(SHLLconst [16] x1:(MOVWload [i1] {s} p mem)))
+ // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVLload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpAMD64MOVWload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLLconst || auxIntToInt8(sh.AuxInt) != 16 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpAMD64MOVWload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpAMD64MOVLload, typ.UInt32)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORL x0:(MOVWload [i] {s} p0 mem) sh:(SHLLconst [16] x1:(MOVWload [i] {s} p1 mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVLload [i] {s} p0 mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpAMD64MOVWload {
+ continue
+ }
+ i := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p0 := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLLconst || auxIntToInt8(sh.AuxInt) != 16 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpAMD64MOVWload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if mem != x1.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpAMD64MOVLload, typ.UInt32)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p0, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORL s1:(SHLLconst [j1] x1:(MOVBload [i1] {s} p mem)) or:(ORL s0:(SHLLconst [j0] x0:(MOVBload [i0] {s} p mem)) y))
+ // cond: i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORL <v.Type> (SHLLconst <v.Type> [j0] (MOVWload [i0] {s} p mem)) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpAMD64SHLLconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORL {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s0 := or_0
+ if s0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(i1 == i0+1 && j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ORL, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64SHLLconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j0)
+ v2 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16)
+ v2.AuxInt = int32ToAuxInt(i0)
+ v2.Aux = symToAux(s)
+ v2.AddArg2(p, mem)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL s1:(SHLLconst [j1] x1:(MOVBload [i] {s} p1 mem)) or:(ORL s0:(SHLLconst [j0] x0:(MOVBload [i] {s} p0 mem)) y))
+ // cond: j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORL <v.Type> (SHLLconst <v.Type> [j0] (MOVWload [i] {s} p0 mem)) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpAMD64SHLLconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p1 := x1.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORL {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s0 := or_0
+ if s0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpAMD64MOVBload || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ p0 := x0.Args[0]
+ if mem != x0.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ORL, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64SHLLconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j0)
+ v2 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16)
+ v2.AuxInt = int32ToAuxInt(i)
+ v2.Aux = symToAux(s)
+ v2.AddArg2(p0, mem)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL x1:(MOVBload [i1] {s} p mem) sh:(SHLLconst [8] x0:(MOVBload [i0] {s} p mem)))
+ // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (ROLWconst <v.Type> [8] (MOVWload [i0] {s} p mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x1 := v_0
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLLconst || auxIntToInt8(sh.AuxInt) != 8 {
+ continue
+ }
+ x0 := sh.Args[0]
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ROLWconst, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int8ToAuxInt(8)
+ v1 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORL x1:(MOVBload [i] {s} p1 mem) sh:(SHLLconst [8] x0:(MOVBload [i] {s} p0 mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (ROLWconst <v.Type> [8] (MOVWload [i] {s} p0 mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x1 := v_0
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p1 := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLLconst || auxIntToInt8(sh.AuxInt) != 8 {
+ continue
+ }
+ x0 := sh.Args[0]
+ if x0.Op != OpAMD64MOVBload || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ p0 := x0.Args[0]
+ if mem != x0.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ROLWconst, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int8ToAuxInt(8)
+ v1 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16)
+ v1.AuxInt = int32ToAuxInt(i)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p0, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORL r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem)) sh:(SHLLconst [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem))))
+ // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh)
+ // result: @mergePoint(b,x0,x1) (BSWAPL <v.Type> (MOVLload [i0] {s} p mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ r1 := v_0
+ if r1.Op != OpAMD64ROLWconst || auxIntToInt8(r1.AuxInt) != 8 {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpAMD64MOVWload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLLconst || auxIntToInt8(sh.AuxInt) != 16 {
+ continue
+ }
+ r0 := sh.Args[0]
+ if r0.Op != OpAMD64ROLWconst || auxIntToInt8(r0.AuxInt) != 8 {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpAMD64MOVWload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPL, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64MOVLload, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORL r1:(ROLWconst [8] x1:(MOVWload [i] {s} p1 mem)) sh:(SHLLconst [16] r0:(ROLWconst [8] x0:(MOVWload [i] {s} p0 mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh)
+ // result: @mergePoint(b,x0,x1) (BSWAPL <v.Type> (MOVLload [i] {s} p0 mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ r1 := v_0
+ if r1.Op != OpAMD64ROLWconst || auxIntToInt8(r1.AuxInt) != 8 {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpAMD64MOVWload {
+ continue
+ }
+ i := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p1 := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLLconst || auxIntToInt8(sh.AuxInt) != 16 {
+ continue
+ }
+ r0 := sh.Args[0]
+ if r0.Op != OpAMD64ROLWconst || auxIntToInt8(r0.AuxInt) != 8 {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpAMD64MOVWload || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ p0 := x0.Args[0]
+ if mem != x0.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPL, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64MOVLload, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(i)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p0, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORL s0:(SHLLconst [j0] x0:(MOVBload [i0] {s} p mem)) or:(ORL s1:(SHLLconst [j1] x1:(MOVBload [i1] {s} p mem)) y))
+ // cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORL <v.Type> (SHLLconst <v.Type> [j1] (ROLWconst <typ.UInt16> [8] (MOVWload [i0] {s} p mem))) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORL {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s1 := or_0
+ if s1.Op != OpAMD64SHLLconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(i1 == i0+1 && j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x1.Pos, OpAMD64ORL, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpAMD64SHLLconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j1)
+ v2 := b.NewValue0(x1.Pos, OpAMD64ROLWconst, typ.UInt16)
+ v2.AuxInt = int8ToAuxInt(8)
+ v3 := b.NewValue0(x1.Pos, OpAMD64MOVWload, typ.UInt16)
+ v3.AuxInt = int32ToAuxInt(i0)
+ v3.Aux = symToAux(s)
+ v3.AddArg2(p, mem)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL s0:(SHLLconst [j0] x0:(MOVBload [i] {s} p0 mem)) or:(ORL s1:(SHLLconst [j1] x1:(MOVBload [i] {s} p1 mem)) y))
+ // cond: j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORL <v.Type> (SHLLconst <v.Type> [j1] (ROLWconst <typ.UInt16> [8] (MOVWload [i] {s} p0 mem))) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p0 := x0.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORL {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s1 := or_0
+ if s1.Op != OpAMD64SHLLconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpAMD64MOVBload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if mem != x1.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x1.Pos, OpAMD64ORL, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpAMD64SHLLconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j1)
+ v2 := b.NewValue0(x1.Pos, OpAMD64ROLWconst, typ.UInt16)
+ v2.AuxInt = int8ToAuxInt(8)
+ v3 := b.NewValue0(x1.Pos, OpAMD64MOVWload, typ.UInt16)
+ v3.AuxInt = int32ToAuxInt(i)
+ v3.Aux = symToAux(s)
+ v3.AddArg2(p0, mem)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ORLload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVLload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64ORLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ORLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ORLconst [c] x)
+ // cond: isUint32PowerOfTwo(int64(c)) && uint64(c) >= 128
+ // result: (BTSLconst [int8(log32(c))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isUint32PowerOfTwo(int64(c)) && uint64(c) >= 128) {
+ break
+ }
+ v.reset(OpAMD64BTSLconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORLconst [c] (ORLconst [d] x))
+ // result: (ORLconst [c | d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ORLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORLconst)
+ v.AuxInt = int32ToAuxInt(c | d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORLconst [c] (BTSLconst [d] x))
+ // result: (ORLconst [c | 1<<uint32(d)] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64BTSLconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORLconst)
+ v.AuxInt = int32ToAuxInt(c | 1<<uint32(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORLconst [c] x)
+ // cond: c==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORLconst [c] _)
+ // cond: c==-1
+ // result: (MOVLconst [-1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if !(c == -1) {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ // match: (ORLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [c|d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(c | d)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ORLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ORLconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (ORLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64ORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (ORLconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (ORLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ORLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ORLload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ORLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ORLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ORLload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ORLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ORLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: ( ORLload x [off] {sym} ptr (MOVSSstore [off] {sym} ptr y _))
+ // result: ( ORL x (MOVLf2i y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVSSstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64ORL)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVLf2i, typ.UInt32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ORLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ORLmodify [off] {sym} ptr s:(SHLL (MOVLconst [1]) <t> x) mem)
+ // result: (BTSLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ s := v_1
+ if s.Op != OpAMD64SHLL {
+ break
+ }
+ t := s.Type
+ x := s.Args[1]
+ s_0 := s.Args[0]
+ if s_0.Op != OpAMD64MOVLconst || auxIntToInt32(s_0.AuxInt) != 1 {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64BTSLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64ANDLconst, t)
+ v0.AuxInt = int32ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (ORLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ORLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ORLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (ORLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ORLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ORLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ORQ (SHLQ (MOVQconst [1]) y) x)
+ // result: (BTSQ x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ y := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_0_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpAMD64BTSQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ORQ (MOVQconst [c]) x)
+ // cond: isUint64PowerOfTwo(c) && uint64(c) >= 128
+ // result: (BTSQconst [int8(log64(c))] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(isUint64PowerOfTwo(c) && uint64(c) >= 128) {
+ continue
+ }
+ v.reset(OpAMD64BTSQconst)
+ v.AuxInt = int8ToAuxInt(int8(log64(c)))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORQ x (MOVQconst [c]))
+ // cond: is32Bit(c)
+ // result: (ORQconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpAMD64ORQconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORQ x (MOVLconst [c]))
+ // result: (ORQconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ORQconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORQ (SHLQconst x [c]) (SHRQconst x [d]))
+ // cond: d==64-c
+ // result: (ROLQconst x [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRQconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 64-c) {
+ continue
+ }
+ v.reset(OpAMD64ROLQconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORQ (SHLQ x y) (ANDQ (SHRQ x (NEGQ y)) (SBBQcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [63]) [-64])) [64]))))
+ // result: (ROLQ x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64ANDQ {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHRQ {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGQ || y != v_1_0_1.Args[0] || v_1_1.Op != OpAMD64SBBQcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPQconst || auxIntToInt32(v_1_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGQ {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -64 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 63 || y != v_1_1_0_0_0_0.Args[0] {
+ continue
+ }
+ v.reset(OpAMD64ROLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ (SHLQ x y) (ANDQ (SHRQ x (NEGL y)) (SBBQcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [63]) [-64])) [64]))))
+ // result: (ROLQ x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64ANDQ {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHRQ {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGL || y != v_1_0_1.Args[0] || v_1_1.Op != OpAMD64SBBQcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPLconst || auxIntToInt32(v_1_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGL {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDLconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -64 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDLconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 63 || y != v_1_1_0_0_0_0.Args[0] {
+ continue
+ }
+ v.reset(OpAMD64ROLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ (SHRQ x y) (ANDQ (SHLQ x (NEGQ y)) (SBBQcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [63]) [-64])) [64]))))
+ // result: (RORQ x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHRQ {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64ANDQ {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGQ || y != v_1_0_1.Args[0] || v_1_1.Op != OpAMD64SBBQcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPQconst || auxIntToInt32(v_1_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGQ {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDQconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -64 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDQconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 63 || y != v_1_1_0_0_0_0.Args[0] {
+ continue
+ }
+ v.reset(OpAMD64RORQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ (SHRQ x y) (ANDQ (SHLQ x (NEGL y)) (SBBQcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [63]) [-64])) [64]))))
+ // result: (RORQ x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHRQ {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64ANDQ {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpAMD64NEGL || y != v_1_0_1.Args[0] || v_1_1.Op != OpAMD64SBBQcarrymask {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAMD64CMPLconst || auxIntToInt32(v_1_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAMD64NEGL {
+ continue
+ }
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpAMD64ADDLconst || auxIntToInt32(v_1_1_0_0_0.AuxInt) != -64 {
+ continue
+ }
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpAMD64ANDLconst || auxIntToInt32(v_1_1_0_0_0_0.AuxInt) != 63 || y != v_1_1_0_0_0_0.Args[0] {
+ continue
+ }
+ v.reset(OpAMD64RORQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ (MOVQconst [c]) (MOVQconst [d]))
+ // result: (MOVQconst [c|d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAMD64MOVQconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(c | d)
+ return true
+ }
+ break
+ }
+ // match: (ORQ x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORQ x0:(MOVBload [i0] {s} p mem) sh:(SHLQconst [8] x1:(MOVBload [i1] {s} p mem)))
+ // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 8 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpAMD64MOVWload, typ.UInt16)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORQ x0:(MOVBload [i] {s} p0 mem) sh:(SHLQconst [8] x1:(MOVBload [i] {s} p1 mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVWload [i] {s} p0 mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p0 := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 8 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpAMD64MOVBload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if mem != x1.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpAMD64MOVWload, typ.UInt16)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p0, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORQ x0:(MOVWload [i0] {s} p mem) sh:(SHLQconst [16] x1:(MOVWload [i1] {s} p mem)))
+ // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVLload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpAMD64MOVWload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 16 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpAMD64MOVWload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpAMD64MOVLload, typ.UInt32)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORQ x0:(MOVWload [i] {s} p0 mem) sh:(SHLQconst [16] x1:(MOVWload [i] {s} p1 mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVLload [i] {s} p0 mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpAMD64MOVWload {
+ continue
+ }
+ i := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p0 := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 16 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpAMD64MOVWload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if mem != x1.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpAMD64MOVLload, typ.UInt32)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p0, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORQ x0:(MOVLload [i0] {s} p mem) sh:(SHLQconst [32] x1:(MOVLload [i1] {s} p mem)))
+ // cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVQload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpAMD64MOVLload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 32 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpAMD64MOVLload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpAMD64MOVQload, typ.UInt64)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORQ x0:(MOVLload [i] {s} p0 mem) sh:(SHLQconst [32] x1:(MOVLload [i] {s} p1 mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 4) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVQload [i] {s} p0 mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpAMD64MOVLload {
+ continue
+ }
+ i := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p0 := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 32 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpAMD64MOVLload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if mem != x1.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 4) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpAMD64MOVQload, typ.UInt64)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p0, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORQ s1:(SHLQconst [j1] x1:(MOVBload [i1] {s} p mem)) or:(ORQ s0:(SHLQconst [j0] x0:(MOVBload [i0] {s} p mem)) y))
+ // cond: i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j0] (MOVWload [i0] {s} p mem)) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORQ {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s0 := or_0
+ if s0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(i1 == i0+1 && j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ORQ, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64SHLQconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j0)
+ v2 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16)
+ v2.AuxInt = int32ToAuxInt(i0)
+ v2.Aux = symToAux(s)
+ v2.AddArg2(p, mem)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ s1:(SHLQconst [j1] x1:(MOVBload [i] {s} p1 mem)) or:(ORQ s0:(SHLQconst [j0] x0:(MOVBload [i] {s} p0 mem)) y))
+ // cond: j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j0] (MOVWload [i] {s} p0 mem)) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p1 := x1.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORQ {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s0 := or_0
+ if s0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpAMD64MOVBload || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ p0 := x0.Args[0]
+ if mem != x0.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ORQ, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64SHLQconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j0)
+ v2 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16)
+ v2.AuxInt = int32ToAuxInt(i)
+ v2.Aux = symToAux(s)
+ v2.AddArg2(p0, mem)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ s1:(SHLQconst [j1] x1:(MOVWload [i1] {s} p mem)) or:(ORQ s0:(SHLQconst [j0] x0:(MOVWload [i0] {s} p mem)) y))
+ // cond: i1 == i0+2 && j1 == j0+16 && j0 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j0] (MOVLload [i0] {s} p mem)) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpAMD64MOVWload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORQ {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s0 := or_0
+ if s0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpAMD64MOVWload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(i1 == i0+2 && j1 == j0+16 && j0%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ORQ, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64SHLQconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j0)
+ v2 := b.NewValue0(x0.Pos, OpAMD64MOVLload, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(i0)
+ v2.Aux = symToAux(s)
+ v2.AddArg2(p, mem)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ s1:(SHLQconst [j1] x1:(MOVWload [i] {s} p1 mem)) or:(ORQ s0:(SHLQconst [j0] x0:(MOVWload [i] {s} p0 mem)) y))
+ // cond: j1 == j0+16 && j0 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j0] (MOVLload [i] {s} p0 mem)) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpAMD64MOVWload {
+ continue
+ }
+ i := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p1 := x1.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORQ {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s0 := or_0
+ if s0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpAMD64MOVWload || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ p0 := x0.Args[0]
+ if mem != x0.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(j1 == j0+16 && j0%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ORQ, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64SHLQconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j0)
+ v2 := b.NewValue0(x0.Pos, OpAMD64MOVLload, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(i)
+ v2.Aux = symToAux(s)
+ v2.AddArg2(p0, mem)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ x1:(MOVBload [i1] {s} p mem) sh:(SHLQconst [8] x0:(MOVBload [i0] {s} p mem)))
+ // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (ROLWconst <v.Type> [8] (MOVWload [i0] {s} p mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x1 := v_0
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 8 {
+ continue
+ }
+ x0 := sh.Args[0]
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ROLWconst, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int8ToAuxInt(8)
+ v1 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORQ x1:(MOVBload [i] {s} p1 mem) sh:(SHLQconst [8] x0:(MOVBload [i] {s} p0 mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (ROLWconst <v.Type> [8] (MOVWload [i] {s} p0 mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x1 := v_0
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p1 := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 8 {
+ continue
+ }
+ x0 := sh.Args[0]
+ if x0.Op != OpAMD64MOVBload || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ p0 := x0.Args[0]
+ if mem != x0.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpAMD64ROLWconst, v.Type)
+ v.copyOf(v0)
+ v0.AuxInt = int8ToAuxInt(8)
+ v1 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16)
+ v1.AuxInt = int32ToAuxInt(i)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p0, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORQ r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem)) sh:(SHLQconst [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem))))
+ // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh)
+ // result: @mergePoint(b,x0,x1) (BSWAPL <v.Type> (MOVLload [i0] {s} p mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ r1 := v_0
+ if r1.Op != OpAMD64ROLWconst || auxIntToInt8(r1.AuxInt) != 8 {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpAMD64MOVWload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 16 {
+ continue
+ }
+ r0 := sh.Args[0]
+ if r0.Op != OpAMD64ROLWconst || auxIntToInt8(r0.AuxInt) != 8 {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpAMD64MOVWload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPL, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64MOVLload, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORQ r1:(ROLWconst [8] x1:(MOVWload [i] {s} p1 mem)) sh:(SHLQconst [16] r0:(ROLWconst [8] x0:(MOVWload [i] {s} p0 mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh)
+ // result: @mergePoint(b,x0,x1) (BSWAPL <v.Type> (MOVLload [i] {s} p0 mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ r1 := v_0
+ if r1.Op != OpAMD64ROLWconst || auxIntToInt8(r1.AuxInt) != 8 {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpAMD64MOVWload {
+ continue
+ }
+ i := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p1 := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 16 {
+ continue
+ }
+ r0 := sh.Args[0]
+ if r0.Op != OpAMD64ROLWconst || auxIntToInt8(r0.AuxInt) != 8 {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpAMD64MOVWload || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ p0 := x0.Args[0]
+ if mem != x0.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPL, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64MOVLload, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(i)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p0, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORQ r1:(BSWAPL x1:(MOVLload [i1] {s} p mem)) sh:(SHLQconst [32] r0:(BSWAPL x0:(MOVLload [i0] {s} p mem))))
+ // cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh)
+ // result: @mergePoint(b,x0,x1) (BSWAPQ <v.Type> (MOVQload [i0] {s} p mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ r1 := v_0
+ if r1.Op != OpAMD64BSWAPL {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpAMD64MOVLload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 32 {
+ continue
+ }
+ r0 := sh.Args[0]
+ if r0.Op != OpAMD64BSWAPL {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpAMD64MOVLload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPQ, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64MOVQload, typ.UInt64)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORQ r1:(BSWAPL x1:(MOVLload [i] {s} p1 mem)) sh:(SHLQconst [32] r0:(BSWAPL x0:(MOVLload [i] {s} p0 mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 4) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh)
+ // result: @mergePoint(b,x0,x1) (BSWAPQ <v.Type> (MOVQload [i] {s} p0 mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ r1 := v_0
+ if r1.Op != OpAMD64BSWAPL {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpAMD64MOVLload {
+ continue
+ }
+ i := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p1 := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 32 {
+ continue
+ }
+ r0 := sh.Args[0]
+ if r0.Op != OpAMD64BSWAPL {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpAMD64MOVLload || auxIntToInt32(x0.AuxInt) != i || auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ p0 := x0.Args[0]
+ if mem != x0.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p0, p1, 4) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPQ, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpAMD64MOVQload, typ.UInt64)
+ v1.AuxInt = int32ToAuxInt(i)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p0, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORQ s0:(SHLQconst [j0] x0:(MOVBload [i0] {s} p mem)) or:(ORQ s1:(SHLQconst [j1] x1:(MOVBload [i1] {s} p mem)) y))
+ // cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j1] (ROLWconst <typ.UInt16> [8] (MOVWload [i0] {s} p mem))) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORQ {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s1 := or_0
+ if s1.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpAMD64MOVBload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(i1 == i0+1 && j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x1.Pos, OpAMD64ORQ, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpAMD64SHLQconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j1)
+ v2 := b.NewValue0(x1.Pos, OpAMD64ROLWconst, typ.UInt16)
+ v2.AuxInt = int8ToAuxInt(8)
+ v3 := b.NewValue0(x1.Pos, OpAMD64MOVWload, typ.UInt16)
+ v3.AuxInt = int32ToAuxInt(i0)
+ v3.Aux = symToAux(s)
+ v3.AddArg2(p, mem)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ s0:(SHLQconst [j0] x0:(MOVBload [i] {s} p0 mem)) or:(ORQ s1:(SHLQconst [j1] x1:(MOVBload [i] {s} p1 mem)) y))
+ // cond: j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j1] (ROLWconst <typ.UInt16> [8] (MOVWload [i] {s} p0 mem))) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpAMD64MOVBload {
+ continue
+ }
+ i := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p0 := x0.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORQ {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s1 := or_0
+ if s1.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpAMD64MOVBload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if mem != x1.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 1) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x1.Pos, OpAMD64ORQ, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpAMD64SHLQconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j1)
+ v2 := b.NewValue0(x1.Pos, OpAMD64ROLWconst, typ.UInt16)
+ v2.AuxInt = int8ToAuxInt(8)
+ v3 := b.NewValue0(x1.Pos, OpAMD64MOVWload, typ.UInt16)
+ v3.AuxInt = int32ToAuxInt(i)
+ v3.Aux = symToAux(s)
+ v3.AddArg2(p0, mem)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ s0:(SHLQconst [j0] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem))) or:(ORQ s1:(SHLQconst [j1] r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem))) y))
+ // cond: i1 == i0+2 && j1 == j0-16 && j1 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, r0, r1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j1] (BSWAPL <typ.UInt32> (MOVLload [i0] {s} p mem))) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ r0 := s0.Args[0]
+ if r0.Op != OpAMD64ROLWconst || auxIntToInt8(r0.AuxInt) != 8 {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpAMD64MOVWload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORQ {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s1 := or_0
+ if s1.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ r1 := s1.Args[0]
+ if r1.Op != OpAMD64ROLWconst || auxIntToInt8(r1.AuxInt) != 8 {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpAMD64MOVWload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(i1 == i0+2 && j1 == j0-16 && j1%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, r0, r1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x1.Pos, OpAMD64ORQ, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpAMD64SHLQconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j1)
+ v2 := b.NewValue0(x1.Pos, OpAMD64BSWAPL, typ.UInt32)
+ v3 := b.NewValue0(x1.Pos, OpAMD64MOVLload, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(i0)
+ v3.Aux = symToAux(s)
+ v3.AddArg2(p, mem)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ s0:(SHLQconst [j0] r0:(ROLWconst [8] x0:(MOVWload [i] {s} p0 mem))) or:(ORQ s1:(SHLQconst [j1] r1:(ROLWconst [8] x1:(MOVWload [i] {s} p1 mem))) y))
+ // cond: j1 == j0-16 && j1 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, r0, r1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORQ <v.Type> (SHLQconst <v.Type> [j1] (BSWAPL <typ.UInt32> (MOVLload [i] {s} p0 mem))) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j0 := auxIntToInt8(s0.AuxInt)
+ r0 := s0.Args[0]
+ if r0.Op != OpAMD64ROLWconst || auxIntToInt8(r0.AuxInt) != 8 {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpAMD64MOVWload {
+ continue
+ }
+ i := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p0 := x0.Args[0]
+ or := v_1
+ if or.Op != OpAMD64ORQ {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s1 := or_0
+ if s1.Op != OpAMD64SHLQconst {
+ continue
+ }
+ j1 := auxIntToInt8(s1.AuxInt)
+ r1 := s1.Args[0]
+ if r1.Op != OpAMD64ROLWconst || auxIntToInt8(r1.AuxInt) != 8 {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpAMD64MOVWload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if mem != x1.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(j1 == j0-16 && j1%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && sequentialAddresses(p0, p1, 2) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, r0, r1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x1.Pos, OpAMD64ORQ, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpAMD64SHLQconst, v.Type)
+ v1.AuxInt = int8ToAuxInt(j1)
+ v2 := b.NewValue0(x1.Pos, OpAMD64BSWAPL, typ.UInt32)
+ v3 := b.NewValue0(x1.Pos, OpAMD64MOVLload, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(i)
+ v3.Aux = symToAux(s)
+ v3.AddArg2(p0, mem)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORQ x l:(MOVQload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (ORQload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVQload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64ORQload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ORQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ORQconst [c] x)
+ // cond: isUint64PowerOfTwo(int64(c)) && uint64(c) >= 128
+ // result: (BTSQconst [int8(log32(c))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isUint64PowerOfTwo(int64(c)) && uint64(c) >= 128) {
+ break
+ }
+ v.reset(OpAMD64BTSQconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORQconst [c] (ORQconst [d] x))
+ // result: (ORQconst [c | d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64ORQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORQconst)
+ v.AuxInt = int32ToAuxInt(c | d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORQconst [c] (BTSQconst [d] x))
+ // cond: is32Bit(int64(c) | 1<<uint32(d))
+ // result: (ORQconst [c | 1<<uint32(d)] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64BTSQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) | 1<<uint32(d))) {
+ break
+ }
+ v.reset(OpAMD64ORQconst)
+ v.AuxInt = int32ToAuxInt(c | 1<<uint32(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORQconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORQconst [-1] _)
+ // result: (MOVQconst [-1])
+ for {
+ if auxIntToInt32(v.AuxInt) != -1 {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (ORQconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [int64(c)|d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(c) | d)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ORQconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ORQconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (ORQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64ORQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (ORQconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (ORQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ORQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ORQload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ORQload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ORQload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ORQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (ORQload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ORQload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ORQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: ( ORQload x [off] {sym} ptr (MOVSDstore [off] {sym} ptr y _))
+ // result: ( ORQ x (MOVQf2i y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVSDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64ORQ)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVQf2i, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ORQmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ORQmodify [off] {sym} ptr s:(SHLQ (MOVQconst [1]) <t> x) mem)
+ // result: (BTSQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ s := v_1
+ if s.Op != OpAMD64SHLQ {
+ break
+ }
+ t := s.Type
+ x := s.Args[1]
+ s_0 := s.Args[0]
+ if s_0.Op != OpAMD64MOVQconst || auxIntToInt64(s_0.AuxInt) != 1 {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64BTSQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64ANDQconst, t)
+ v0.AuxInt = int32ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (ORQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (ORQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64ORQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (ORQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (ORQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64ORQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ROLB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ROLB x (NEGQ y))
+ // result: (RORB x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64RORB)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ROLB x (NEGL y))
+ // result: (RORB x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64RORB)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ROLB x (MOVQconst [c]))
+ // result: (ROLBconst [int8(c&7) ] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64ROLBconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 7))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLB x (MOVLconst [c]))
+ // result: (ROLBconst [int8(c&7) ] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ROLBconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 7))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ROLBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ROLBconst [c] (ROLBconst [d] x))
+ // result: (ROLBconst [(c+d)& 7] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64ROLBconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ROLBconst)
+ v.AuxInt = int8ToAuxInt((c + d) & 7)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLBconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ROLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ROLL x (NEGQ y))
+ // result: (RORL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64RORL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ROLL x (NEGL y))
+ // result: (RORL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64RORL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ROLL x (MOVQconst [c]))
+ // result: (ROLLconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64ROLLconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLL x (MOVLconst [c]))
+ // result: (ROLLconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ROLLconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ROLLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ROLLconst [c] (ROLLconst [d] x))
+ // result: (ROLLconst [(c+d)&31] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64ROLLconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ROLLconst)
+ v.AuxInt = int8ToAuxInt((c + d) & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLLconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ROLQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ROLQ x (NEGQ y))
+ // result: (RORQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64RORQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ROLQ x (NEGL y))
+ // result: (RORQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64RORQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ROLQ x (MOVQconst [c]))
+ // result: (ROLQconst [int8(c&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64ROLQconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLQ x (MOVLconst [c]))
+ // result: (ROLQconst [int8(c&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ROLQconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ROLQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ROLQconst [c] (ROLQconst [d] x))
+ // result: (ROLQconst [(c+d)&63] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64ROLQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ROLQconst)
+ v.AuxInt = int8ToAuxInt((c + d) & 63)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLQconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ROLW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ROLW x (NEGQ y))
+ // result: (RORW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64RORW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ROLW x (NEGL y))
+ // result: (RORW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64RORW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ROLW x (MOVQconst [c]))
+ // result: (ROLWconst [int8(c&15)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64ROLWconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 15))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLW x (MOVLconst [c]))
+ // result: (ROLWconst [int8(c&15)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ROLWconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 15))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64ROLWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ROLWconst [c] (ROLWconst [d] x))
+ // result: (ROLWconst [(c+d)&15] x)
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64ROLWconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64ROLWconst)
+ v.AuxInt = int8ToAuxInt((c + d) & 15)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ROLWconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64RORB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RORB x (NEGQ y))
+ // result: (ROLB x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64ROLB)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RORB x (NEGL y))
+ // result: (ROLB x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64ROLB)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RORB x (MOVQconst [c]))
+ // result: (ROLBconst [int8((-c)&7) ] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64ROLBconst)
+ v.AuxInt = int8ToAuxInt(int8((-c) & 7))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RORB x (MOVLconst [c]))
+ // result: (ROLBconst [int8((-c)&7) ] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ROLBconst)
+ v.AuxInt = int8ToAuxInt(int8((-c) & 7))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64RORL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RORL x (NEGQ y))
+ // result: (ROLL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64ROLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RORL x (NEGL y))
+ // result: (ROLL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64ROLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RORL x (MOVQconst [c]))
+ // result: (ROLLconst [int8((-c)&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64ROLLconst)
+ v.AuxInt = int8ToAuxInt(int8((-c) & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RORL x (MOVLconst [c]))
+ // result: (ROLLconst [int8((-c)&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ROLLconst)
+ v.AuxInt = int8ToAuxInt(int8((-c) & 31))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64RORQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RORQ x (NEGQ y))
+ // result: (ROLQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64ROLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RORQ x (NEGL y))
+ // result: (ROLQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64ROLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RORQ x (MOVQconst [c]))
+ // result: (ROLQconst [int8((-c)&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64ROLQconst)
+ v.AuxInt = int8ToAuxInt(int8((-c) & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RORQ x (MOVLconst [c]))
+ // result: (ROLQconst [int8((-c)&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ROLQconst)
+ v.AuxInt = int8ToAuxInt(int8((-c) & 63))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64RORW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RORW x (NEGQ y))
+ // result: (ROLW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64ROLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RORW x (NEGL y))
+ // result: (ROLW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpAMD64ROLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RORW x (MOVQconst [c]))
+ // result: (ROLWconst [int8((-c)&15)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64ROLWconst)
+ v.AuxInt = int8ToAuxInt(int8((-c) & 15))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RORW x (MOVLconst [c]))
+ // result: (ROLWconst [int8((-c)&15)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64ROLWconst)
+ v.AuxInt = int8ToAuxInt(int8((-c) & 15))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SARB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SARB x (MOVQconst [c]))
+ // result: (SARBconst [int8(min(int64(c)&31,7))] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64SARBconst)
+ v.AuxInt = int8ToAuxInt(int8(min(int64(c)&31, 7)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SARB x (MOVLconst [c]))
+ // result: (SARBconst [int8(min(int64(c)&31,7))] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64SARBconst)
+ v.AuxInt = int8ToAuxInt(int8(min(int64(c)&31, 7)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SARBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SARBconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SARBconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [int64(int8(d))>>uint64(c)])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(int8(d)) >> uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SARL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SARL x (MOVQconst [c]))
+ // result: (SARLconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64SARLconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SARL x (MOVLconst [c]))
+ // result: (SARLconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64SARLconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SARL x (ADDQconst [c] y))
+ // cond: c & 31 == 0
+ // result: (SARL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SARL x (NEGQ <t> (ADDQconst [c] y)))
+ // cond: c & 31 == 0
+ // result: (SARL x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SARL x (ANDQconst [c] y))
+ // cond: c & 31 == 31
+ // result: (SARL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SARL x (NEGQ <t> (ANDQconst [c] y)))
+ // cond: c & 31 == 31
+ // result: (SARL x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SARL x (ADDLconst [c] y))
+ // cond: c & 31 == 0
+ // result: (SARL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SARL x (NEGL <t> (ADDLconst [c] y)))
+ // cond: c & 31 == 0
+ // result: (SARL x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SARL x (ANDLconst [c] y))
+ // cond: c & 31 == 31
+ // result: (SARL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SARL x (NEGL <t> (ANDLconst [c] y)))
+ // cond: c & 31 == 31
+ // result: (SARL x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SARLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SARLconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SARLconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [int64(int32(d))>>uint64(c)])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(d)) >> uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SARQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SARQ x (MOVQconst [c]))
+ // result: (SARQconst [int8(c&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64SARQconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SARQ x (MOVLconst [c]))
+ // result: (SARQconst [int8(c&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64SARQconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SARQ x (ADDQconst [c] y))
+ // cond: c & 63 == 0
+ // result: (SARQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SARQ x (NEGQ <t> (ADDQconst [c] y)))
+ // cond: c & 63 == 0
+ // result: (SARQ x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SARQ x (ANDQconst [c] y))
+ // cond: c & 63 == 63
+ // result: (SARQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SARQ x (NEGQ <t> (ANDQconst [c] y)))
+ // cond: c & 63 == 63
+ // result: (SARQ x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SARQ x (ADDLconst [c] y))
+ // cond: c & 63 == 0
+ // result: (SARQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SARQ x (NEGL <t> (ADDLconst [c] y)))
+ // cond: c & 63 == 0
+ // result: (SARQ x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SARQ x (ANDLconst [c] y))
+ // cond: c & 63 == 63
+ // result: (SARQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SARQ x (NEGL <t> (ANDLconst [c] y)))
+ // cond: c & 63 == 63
+ // result: (SARQ x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SARQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SARQconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SARQconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [d>>uint64(c)])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(d >> uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SARW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SARW x (MOVQconst [c]))
+ // result: (SARWconst [int8(min(int64(c)&31,15))] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64SARWconst)
+ v.AuxInt = int8ToAuxInt(int8(min(int64(c)&31, 15)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SARW x (MOVLconst [c]))
+ // result: (SARWconst [int8(min(int64(c)&31,15))] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64SARWconst)
+ v.AuxInt = int8ToAuxInt(int8(min(int64(c)&31, 15)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SARWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SARWconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SARWconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [int64(int16(d))>>uint64(c)])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(int16(d)) >> uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SBBLcarrymask(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SBBLcarrymask (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SBBLcarrymask (FlagLT_ULT))
+ // result: (MOVLconst [-1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ // match: (SBBLcarrymask (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SBBLcarrymask (FlagGT_ULT))
+ // result: (MOVLconst [-1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ // match: (SBBLcarrymask (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SBBQ(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SBBQ x (MOVQconst [c]) borrow)
+ // cond: is32Bit(c)
+ // result: (SBBQconst x [int32(c)] borrow)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ borrow := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpAMD64SBBQconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(x, borrow)
+ return true
+ }
+ // match: (SBBQ x y (FlagEQ))
+ // result: (SUBQborrow x y)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64SUBQborrow)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SBBQcarrymask(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SBBQcarrymask (FlagEQ))
+ // result: (MOVQconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SBBQcarrymask (FlagLT_ULT))
+ // result: (MOVQconst [-1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (SBBQcarrymask (FlagLT_UGT))
+ // result: (MOVQconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SBBQcarrymask (FlagGT_ULT))
+ // result: (MOVQconst [-1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (SBBQcarrymask (FlagGT_UGT))
+ // result: (MOVQconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SBBQconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SBBQconst x [c] (FlagEQ))
+ // result: (SUBQconstborrow x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64SUBQconstborrow)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETA(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETA (InvertFlags x))
+ // result: (SETB x)
+ for {
+ if v_0.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETB)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETA (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETA (FlagLT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETA (FlagLT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETA (FlagGT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETA (FlagGT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETAE(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETAE (TESTQ x x))
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (SETAE (TESTL x x))
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAMD64TESTL {
+ break
+ }
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (SETAE (TESTW x x))
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAMD64TESTW {
+ break
+ }
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (SETAE (TESTB x x))
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAMD64TESTB {
+ break
+ }
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (SETAE (InvertFlags x))
+ // result: (SETBE x)
+ for {
+ if v_0.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETBE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETAE (FlagEQ))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETAE (FlagLT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETAE (FlagLT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETAE (FlagGT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETAE (FlagGT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETAEstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SETAEstore [off] {sym} ptr (InvertFlags x) mem)
+ // result: (SETBEstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64SETBEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (SETAEstore [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SETAEstore [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETAEstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SETAEstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETAEstore [off] {sym} ptr (FlagEQ) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETAEstore [off] {sym} ptr (FlagLT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETAEstore [off] {sym} ptr (FlagLT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETAEstore [off] {sym} ptr (FlagGT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETAEstore [off] {sym} ptr (FlagGT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETAstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SETAstore [off] {sym} ptr (InvertFlags x) mem)
+ // result: (SETBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (SETAstore [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SETAstore [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SETAstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETAstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SETAstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SETAstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETAstore [off] {sym} ptr (FlagEQ) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETAstore [off] {sym} ptr (FlagLT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETAstore [off] {sym} ptr (FlagLT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETAstore [off] {sym} ptr (FlagGT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETAstore [off] {sym} ptr (FlagGT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETB(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETB (TESTQ x x))
+ // result: (ConstBool [false])
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (SETB (TESTL x x))
+ // result: (ConstBool [false])
+ for {
+ if v_0.Op != OpAMD64TESTL {
+ break
+ }
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (SETB (TESTW x x))
+ // result: (ConstBool [false])
+ for {
+ if v_0.Op != OpAMD64TESTW {
+ break
+ }
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (SETB (TESTB x x))
+ // result: (ConstBool [false])
+ for {
+ if v_0.Op != OpAMD64TESTB {
+ break
+ }
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (SETB (BTLconst [0] x))
+ // result: (ANDLconst [1] x)
+ for {
+ if v_0.Op != OpAMD64BTLconst || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETB (BTQconst [0] x))
+ // result: (ANDQconst [1] x)
+ for {
+ if v_0.Op != OpAMD64BTQconst || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDQconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETB (InvertFlags x))
+ // result: (SETA x)
+ for {
+ if v_0.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETA)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETB (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETB (FlagLT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETB (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETB (FlagGT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETB (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETBE(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETBE (InvertFlags x))
+ // result: (SETAE x)
+ for {
+ if v_0.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETAE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETBE (FlagEQ))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETBE (FlagLT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETBE (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETBE (FlagGT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETBE (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETBEstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SETBEstore [off] {sym} ptr (InvertFlags x) mem)
+ // result: (SETAEstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (SETBEstore [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SETBEstore [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SETBEstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETBEstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SETBEstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SETBEstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETBEstore [off] {sym} ptr (FlagEQ) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETBEstore [off] {sym} ptr (FlagLT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETBEstore [off] {sym} ptr (FlagLT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETBEstore [off] {sym} ptr (FlagGT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETBEstore [off] {sym} ptr (FlagGT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETBstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SETBstore [off] {sym} ptr (InvertFlags x) mem)
+ // result: (SETAstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64SETAstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (SETBstore [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SETBstore [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETBstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SETBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETBstore [off] {sym} ptr (FlagEQ) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETBstore [off] {sym} ptr (FlagLT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETBstore [off] {sym} ptr (FlagLT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETBstore [off] {sym} ptr (FlagGT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETBstore [off] {sym} ptr (FlagGT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETEQ(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SETEQ (TESTL (SHLL (MOVLconst [1]) x) y))
+ // result: (SETAE (BTL x y))
+ for {
+ if v_0.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64SHLL {
+ continue
+ }
+ x := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_0_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_0_1
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETEQ (TESTQ (SHLQ (MOVQconst [1]) x) y))
+ // result: (SETAE (BTQ x y))
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ x := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_0_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_0_1
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETEQ (TESTLconst [c] x))
+ // cond: isUint32PowerOfTwo(int64(c))
+ // result: (SETAE (BTLconst [int8(log32(c))] x))
+ for {
+ if v_0.Op != OpAMD64TESTLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isUint32PowerOfTwo(int64(c))) {
+ break
+ }
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SETEQ (TESTQconst [c] x))
+ // cond: isUint64PowerOfTwo(int64(c))
+ // result: (SETAE (BTQconst [int8(log32(c))] x))
+ for {
+ if v_0.Op != OpAMD64TESTQconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isUint64PowerOfTwo(int64(c))) {
+ break
+ }
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SETEQ (TESTQ (MOVQconst [c]) x))
+ // cond: isUint64PowerOfTwo(c)
+ // result: (SETAE (BTQconst [int8(log64(c))] x))
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_1
+ if !(isUint64PowerOfTwo(c)) {
+ continue
+ }
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log64(c)))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETEQ (CMPLconst [1] s:(ANDLconst [1] _)))
+ // result: (SETNE (CMPLconst [0] s))
+ for {
+ if v_0.Op != OpAMD64CMPLconst || auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ s := v_0.Args[0]
+ if s.Op != OpAMD64ANDLconst || auxIntToInt32(s.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpAMD64SETNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(s)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SETEQ (CMPQconst [1] s:(ANDQconst [1] _)))
+ // result: (SETNE (CMPQconst [0] s))
+ for {
+ if v_0.Op != OpAMD64CMPQconst || auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ s := v_0.Args[0]
+ if s.Op != OpAMD64ANDQconst || auxIntToInt32(s.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpAMD64SETNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(s)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SETEQ (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2))
+ // cond: z1==z2
+ // result: (SETAE (BTQconst [63] x))
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHLQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETEQ (TESTL z1:(SHLLconst [31] (SHRQconst [31] x)) z2))
+ // cond: z1==z2
+ // result: (SETAE (BTQconst [31] x))
+ for {
+ if v_0.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHLLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRQconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETEQ (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2))
+ // cond: z1==z2
+ // result: (SETAE (BTQconst [0] x))
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETEQ (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2))
+ // cond: z1==z2
+ // result: (SETAE (BTLconst [0] x))
+ for {
+ if v_0.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLLconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETEQ (TESTQ z1:(SHRQconst [63] x) z2))
+ // cond: z1==z2
+ // result: (SETAE (BTQconst [63] x))
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETEQ (TESTL z1:(SHRLconst [31] x) z2))
+ // cond: z1==z2
+ // result: (SETAE (BTLconst [31] x))
+ for {
+ if v_0.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAE)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETEQ (InvertFlags x))
+ // result: (SETEQ x)
+ for {
+ if v_0.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETEQ)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETEQ (FlagEQ))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETEQ (FlagLT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETEQ (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETEQ (FlagGT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETEQ (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETEQstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SETEQstore [off] {sym} ptr (TESTL (SHLL (MOVLconst [1]) x) y) mem)
+ // result: (SETAEstore [off] {sym} ptr (BTL x y) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHLL {
+ continue
+ }
+ x := v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_1_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_1_1
+ mem := v_2
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETEQstore [off] {sym} ptr (TESTQ (SHLQ (MOVQconst [1]) x) y) mem)
+ // result: (SETAEstore [off] {sym} ptr (BTQ x y) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ x := v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_1_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_1_1
+ mem := v_2
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETEQstore [off] {sym} ptr (TESTLconst [c] x) mem)
+ // cond: isUint32PowerOfTwo(int64(c))
+ // result: (SETAEstore [off] {sym} ptr (BTLconst [int8(log32(c))] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ x := v_1.Args[0]
+ mem := v_2
+ if !(isUint32PowerOfTwo(int64(c))) {
+ break
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETEQstore [off] {sym} ptr (TESTQconst [c] x) mem)
+ // cond: isUint64PowerOfTwo(int64(c))
+ // result: (SETAEstore [off] {sym} ptr (BTQconst [int8(log32(c))] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ x := v_1.Args[0]
+ mem := v_2
+ if !(isUint64PowerOfTwo(int64(c))) {
+ break
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETEQstore [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem)
+ // cond: isUint64PowerOfTwo(c)
+ // result: (SETAEstore [off] {sym} ptr (BTQconst [int8(log64(c))] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ mem := v_2
+ if !(isUint64PowerOfTwo(c)) {
+ continue
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log64(c)))
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETEQstore [off] {sym} ptr (CMPLconst [1] s:(ANDLconst [1] _)) mem)
+ // result: (SETNEstore [off] {sym} ptr (CMPLconst [0] s) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64CMPLconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ break
+ }
+ s := v_1.Args[0]
+ if s.Op != OpAMD64ANDLconst || auxIntToInt32(s.AuxInt) != 1 {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64SETNEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(s)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETEQstore [off] {sym} ptr (CMPQconst [1] s:(ANDQconst [1] _)) mem)
+ // result: (SETNEstore [off] {sym} ptr (CMPQconst [0] s) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64CMPQconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ break
+ }
+ s := v_1.Args[0]
+ if s.Op != OpAMD64ANDQconst || auxIntToInt32(s.AuxInt) != 1 {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64SETNEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(s)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETEQstore [off] {sym} ptr (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2) mem)
+ // cond: z1==z2
+ // result: (SETAEstore [off] {sym} ptr (BTQconst [63] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHLQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETEQstore [off] {sym} ptr (TESTL z1:(SHLLconst [31] (SHRLconst [31] x)) z2) mem)
+ // cond: z1==z2
+ // result: (SETAEstore [off] {sym} ptr (BTLconst [31] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHLLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRLconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETEQstore [off] {sym} ptr (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2) mem)
+ // cond: z1==z2
+ // result: (SETAEstore [off] {sym} ptr (BTQconst [0] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETEQstore [off] {sym} ptr (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2) mem)
+ // cond: z1==z2
+ // result: (SETAEstore [off] {sym} ptr (BTLconst [0] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLLconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETEQstore [off] {sym} ptr (TESTQ z1:(SHRQconst [63] x) z2) mem)
+ // cond: z1==z2
+ // result: (SETAEstore [off] {sym} ptr (BTQconst [63] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETEQstore [off] {sym} ptr (TESTL z1:(SHRLconst [31] x) z2) mem)
+ // cond: z1==z2
+ // result: (SETAEstore [off] {sym} ptr (BTLconst [31] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETAEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETEQstore [off] {sym} ptr (InvertFlags x) mem)
+ // result: (SETEQstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64SETEQstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (SETEQstore [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SETEQstore [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SETEQstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETEQstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SETEQstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SETEQstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETEQstore [off] {sym} ptr (FlagEQ) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETEQstore [off] {sym} ptr (FlagLT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETEQstore [off] {sym} ptr (FlagLT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETEQstore [off] {sym} ptr (FlagGT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETEQstore [off] {sym} ptr (FlagGT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETG(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETG (InvertFlags x))
+ // result: (SETL x)
+ for {
+ if v_0.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETL)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETG (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETG (FlagLT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETG (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETG (FlagGT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETG (FlagGT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETGE(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETGE (InvertFlags x))
+ // result: (SETLE x)
+ for {
+ if v_0.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETLE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETGE (FlagEQ))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETGE (FlagLT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETGE (FlagLT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETGE (FlagGT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETGE (FlagGT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETGEstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SETGEstore [off] {sym} ptr (InvertFlags x) mem)
+ // result: (SETLEstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64SETLEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (SETGEstore [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SETGEstore [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SETGEstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETGEstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SETGEstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SETGEstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETGEstore [off] {sym} ptr (FlagEQ) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETGEstore [off] {sym} ptr (FlagLT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETGEstore [off] {sym} ptr (FlagLT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETGEstore [off] {sym} ptr (FlagGT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETGEstore [off] {sym} ptr (FlagGT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETGstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SETGstore [off] {sym} ptr (InvertFlags x) mem)
+ // result: (SETLstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64SETLstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (SETGstore [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SETGstore [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SETGstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETGstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SETGstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SETGstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETGstore [off] {sym} ptr (FlagEQ) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETGstore [off] {sym} ptr (FlagLT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETGstore [off] {sym} ptr (FlagLT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETGstore [off] {sym} ptr (FlagGT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETGstore [off] {sym} ptr (FlagGT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETL (InvertFlags x))
+ // result: (SETG x)
+ for {
+ if v_0.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETG)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETL (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETL (FlagLT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETL (FlagLT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETL (FlagGT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETL (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETLE(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SETLE (InvertFlags x))
+ // result: (SETGE x)
+ for {
+ if v_0.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETGE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETLE (FlagEQ))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETLE (FlagLT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETLE (FlagLT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETLE (FlagGT_ULT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETLE (FlagGT_UGT))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETLEstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SETLEstore [off] {sym} ptr (InvertFlags x) mem)
+ // result: (SETGEstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64SETGEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (SETLEstore [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SETLEstore [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SETLEstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETLEstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SETLEstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SETLEstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETLEstore [off] {sym} ptr (FlagEQ) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETLEstore [off] {sym} ptr (FlagLT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETLEstore [off] {sym} ptr (FlagLT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETLEstore [off] {sym} ptr (FlagGT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETLEstore [off] {sym} ptr (FlagGT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETLstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SETLstore [off] {sym} ptr (InvertFlags x) mem)
+ // result: (SETGstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64SETGstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (SETLstore [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SETLstore [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SETLstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETLstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SETLstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SETLstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETLstore [off] {sym} ptr (FlagEQ) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETLstore [off] {sym} ptr (FlagLT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETLstore [off] {sym} ptr (FlagLT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETLstore [off] {sym} ptr (FlagGT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETLstore [off] {sym} ptr (FlagGT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETNE(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SETNE (TESTBconst [1] x))
+ // result: (ANDLconst [1] x)
+ for {
+ if v_0.Op != OpAMD64TESTBconst || auxIntToInt8(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETNE (TESTWconst [1] x))
+ // result: (ANDLconst [1] x)
+ for {
+ if v_0.Op != OpAMD64TESTWconst || auxIntToInt16(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETNE (TESTL (SHLL (MOVLconst [1]) x) y))
+ // result: (SETB (BTL x y))
+ for {
+ if v_0.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64SHLL {
+ continue
+ }
+ x := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_0_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_0_1
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETNE (TESTQ (SHLQ (MOVQconst [1]) x) y))
+ // result: (SETB (BTQ x y))
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ x := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_0_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_0_1
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETNE (TESTLconst [c] x))
+ // cond: isUint32PowerOfTwo(int64(c))
+ // result: (SETB (BTLconst [int8(log32(c))] x))
+ for {
+ if v_0.Op != OpAMD64TESTLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isUint32PowerOfTwo(int64(c))) {
+ break
+ }
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SETNE (TESTQconst [c] x))
+ // cond: isUint64PowerOfTwo(int64(c))
+ // result: (SETB (BTQconst [int8(log32(c))] x))
+ for {
+ if v_0.Op != OpAMD64TESTQconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isUint64PowerOfTwo(int64(c))) {
+ break
+ }
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SETNE (TESTQ (MOVQconst [c]) x))
+ // cond: isUint64PowerOfTwo(c)
+ // result: (SETB (BTQconst [int8(log64(c))] x))
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_1
+ if !(isUint64PowerOfTwo(c)) {
+ continue
+ }
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log64(c)))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETNE (CMPLconst [1] s:(ANDLconst [1] _)))
+ // result: (SETEQ (CMPLconst [0] s))
+ for {
+ if v_0.Op != OpAMD64CMPLconst || auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ s := v_0.Args[0]
+ if s.Op != OpAMD64ANDLconst || auxIntToInt32(s.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpAMD64SETEQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(s)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SETNE (CMPQconst [1] s:(ANDQconst [1] _)))
+ // result: (SETEQ (CMPQconst [0] s))
+ for {
+ if v_0.Op != OpAMD64CMPQconst || auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ s := v_0.Args[0]
+ if s.Op != OpAMD64ANDQconst || auxIntToInt32(s.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpAMD64SETEQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(s)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SETNE (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2))
+ // cond: z1==z2
+ // result: (SETB (BTQconst [63] x))
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHLQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETNE (TESTL z1:(SHLLconst [31] (SHRQconst [31] x)) z2))
+ // cond: z1==z2
+ // result: (SETB (BTQconst [31] x))
+ for {
+ if v_0.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHLLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRQconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETNE (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2))
+ // cond: z1==z2
+ // result: (SETB (BTQconst [0] x))
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETNE (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2))
+ // cond: z1==z2
+ // result: (SETB (BTLconst [0] x))
+ for {
+ if v_0.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLLconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETNE (TESTQ z1:(SHRQconst [63] x) z2))
+ // cond: z1==z2
+ // result: (SETB (BTQconst [63] x))
+ for {
+ if v_0.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETNE (TESTL z1:(SHRLconst [31] x) z2))
+ // cond: z1==z2
+ // result: (SETB (BTLconst [31] x))
+ for {
+ if v_0.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (SETNE (InvertFlags x))
+ // result: (SETNE x)
+ for {
+ if v_0.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETNE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SETNE (FlagEQ))
+ // result: (MOVLconst [0])
+ for {
+ if v_0.Op != OpAMD64FlagEQ {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SETNE (FlagLT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETNE (FlagLT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETNE (FlagGT_ULT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SETNE (FlagGT_UGT))
+ // result: (MOVLconst [1])
+ for {
+ if v_0.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SETNEstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SETNEstore [off] {sym} ptr (TESTL (SHLL (MOVLconst [1]) x) y) mem)
+ // result: (SETBstore [off] {sym} ptr (BTL x y) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHLL {
+ continue
+ }
+ x := v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_1_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_1_1
+ mem := v_2
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETNEstore [off] {sym} ptr (TESTQ (SHLQ (MOVQconst [1]) x) y) mem)
+ // result: (SETBstore [off] {sym} ptr (BTQ x y) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ x := v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_1_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_1_1
+ mem := v_2
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETNEstore [off] {sym} ptr (TESTLconst [c] x) mem)
+ // cond: isUint32PowerOfTwo(int64(c))
+ // result: (SETBstore [off] {sym} ptr (BTLconst [int8(log32(c))] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ x := v_1.Args[0]
+ mem := v_2
+ if !(isUint32PowerOfTwo(int64(c))) {
+ break
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETNEstore [off] {sym} ptr (TESTQconst [c] x) mem)
+ // cond: isUint64PowerOfTwo(int64(c))
+ // result: (SETBstore [off] {sym} ptr (BTQconst [int8(log32(c))] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ x := v_1.Args[0]
+ mem := v_2
+ if !(isUint64PowerOfTwo(int64(c))) {
+ break
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETNEstore [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem)
+ // cond: isUint64PowerOfTwo(c)
+ // result: (SETBstore [off] {sym} ptr (BTQconst [int8(log64(c))] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ mem := v_2
+ if !(isUint64PowerOfTwo(c)) {
+ continue
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log64(c)))
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETNEstore [off] {sym} ptr (CMPLconst [1] s:(ANDLconst [1] _)) mem)
+ // result: (SETEQstore [off] {sym} ptr (CMPLconst [0] s) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64CMPLconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ break
+ }
+ s := v_1.Args[0]
+ if s.Op != OpAMD64ANDLconst || auxIntToInt32(s.AuxInt) != 1 {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64SETEQstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(s)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETNEstore [off] {sym} ptr (CMPQconst [1] s:(ANDQconst [1] _)) mem)
+ // result: (SETEQstore [off] {sym} ptr (CMPQconst [0] s) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64CMPQconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ break
+ }
+ s := v_1.Args[0]
+ if s.Op != OpAMD64ANDQconst || auxIntToInt32(s.AuxInt) != 1 {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64SETEQstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(s)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETNEstore [off] {sym} ptr (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2) mem)
+ // cond: z1==z2
+ // result: (SETBstore [off] {sym} ptr (BTQconst [63] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHLQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETNEstore [off] {sym} ptr (TESTL z1:(SHLLconst [31] (SHRLconst [31] x)) z2) mem)
+ // cond: z1==z2
+ // result: (SETBstore [off] {sym} ptr (BTLconst [31] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHLLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRLconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETNEstore [off] {sym} ptr (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2) mem)
+ // cond: z1==z2
+ // result: (SETBstore [off] {sym} ptr (BTQconst [0] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETNEstore [off] {sym} ptr (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2) mem)
+ // cond: z1==z2
+ // result: (SETBstore [off] {sym} ptr (BTLconst [0] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLLconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETNEstore [off] {sym} ptr (TESTQ z1:(SHRQconst [63] x) z2) mem)
+ // cond: z1==z2
+ // result: (SETBstore [off] {sym} ptr (BTQconst [63] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTQ {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETNEstore [off] {sym} ptr (TESTL z1:(SHRLconst [31] x) z2) mem)
+ // cond: z1==z2
+ // result: (SETBstore [off] {sym} ptr (BTLconst [31] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64TESTL {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z1 := v_1_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_1_1
+ mem := v_2
+ if !(z1 == z2) {
+ continue
+ }
+ v.reset(OpAMD64SETBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (SETNEstore [off] {sym} ptr (InvertFlags x) mem)
+ // result: (SETNEstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64InvertFlags {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpAMD64SETNEstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (SETNEstore [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SETNEstore [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SETNEstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETNEstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SETNEstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SETNEstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SETNEstore [off] {sym} ptr (FlagEQ) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [0]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagEQ {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETNEstore [off] {sym} ptr (FlagLT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETNEstore [off] {sym} ptr (FlagLT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagLT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETNEstore [off] {sym} ptr (FlagGT_ULT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_ULT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (SETNEstore [off] {sym} ptr (FlagGT_UGT) mem)
+ // result: (MOVBstore [off] {sym} ptr (MOVLconst <typ.UInt8> [1]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpAMD64FlagGT_UGT {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLconst, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SHLL x (MOVQconst [c]))
+ // result: (SHLLconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64SHLLconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHLL x (MOVLconst [c]))
+ // result: (SHLLconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64SHLLconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHLL x (ADDQconst [c] y))
+ // cond: c & 31 == 0
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHLL x (NEGQ <t> (ADDQconst [c] y)))
+ // cond: c & 31 == 0
+ // result: (SHLL x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHLL x (ANDQconst [c] y))
+ // cond: c & 31 == 31
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHLL x (NEGQ <t> (ANDQconst [c] y)))
+ // cond: c & 31 == 31
+ // result: (SHLL x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHLL x (ADDLconst [c] y))
+ // cond: c & 31 == 0
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHLL x (NEGL <t> (ADDLconst [c] y)))
+ // cond: c & 31 == 0
+ // result: (SHLL x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHLL x (ANDLconst [c] y))
+ // cond: c & 31 == 31
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHLL x (NEGL <t> (ANDLconst [c] y)))
+ // cond: c & 31 == 31
+ // result: (SHLL x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHLLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SHLLconst [1] (SHRLconst [1] x))
+ // result: (BTRLconst [0] x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpAMD64SHRLconst || auxIntToInt8(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTRLconst)
+ v.AuxInt = int8ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHLLconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SHLLconst [d] (MOVLconst [c]))
+ // result: (MOVLconst [c << uint64(d)])
+ for {
+ d := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHLQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SHLQ x (MOVQconst [c]))
+ // result: (SHLQconst [int8(c&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64SHLQconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHLQ x (MOVLconst [c]))
+ // result: (SHLQconst [int8(c&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64SHLQconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHLQ x (ADDQconst [c] y))
+ // cond: c & 63 == 0
+ // result: (SHLQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHLQ x (NEGQ <t> (ADDQconst [c] y)))
+ // cond: c & 63 == 0
+ // result: (SHLQ x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHLQ x (ANDQconst [c] y))
+ // cond: c & 63 == 63
+ // result: (SHLQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHLQ x (NEGQ <t> (ANDQconst [c] y)))
+ // cond: c & 63 == 63
+ // result: (SHLQ x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHLQ x (ADDLconst [c] y))
+ // cond: c & 63 == 0
+ // result: (SHLQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHLQ x (NEGL <t> (ADDLconst [c] y)))
+ // cond: c & 63 == 0
+ // result: (SHLQ x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHLQ x (ANDLconst [c] y))
+ // cond: c & 63 == 63
+ // result: (SHLQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHLQ x (NEGL <t> (ANDLconst [c] y)))
+ // cond: c & 63 == 63
+ // result: (SHLQ x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHLQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SHLQconst [1] (SHRQconst [1] x))
+ // result: (BTRQconst [0] x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpAMD64SHRQconst || auxIntToInt8(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTRQconst)
+ v.AuxInt = int8ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHLQconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SHLQconst [d] (MOVQconst [c]))
+ // result: (MOVQconst [c << uint64(d)])
+ for {
+ d := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(c << uint64(d))
+ return true
+ }
+ // match: (SHLQconst [d] (MOVLconst [c]))
+ // result: (MOVQconst [int64(c) << uint64(d)])
+ for {
+ d := auxIntToInt8(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(c) << uint64(d))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHRB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SHRB x (MOVQconst [c]))
+ // cond: c&31 < 8
+ // result: (SHRBconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c&31 < 8) {
+ break
+ }
+ v.reset(OpAMD64SHRBconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRB x (MOVLconst [c]))
+ // cond: c&31 < 8
+ // result: (SHRBconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c&31 < 8) {
+ break
+ }
+ v.reset(OpAMD64SHRBconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRB _ (MOVQconst [c]))
+ // cond: c&31 >= 8
+ // result: (MOVLconst [0])
+ for {
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c&31 >= 8) {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SHRB _ (MOVLconst [c]))
+ // cond: c&31 >= 8
+ // result: (MOVLconst [0])
+ for {
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c&31 >= 8) {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHRBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SHRBconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SHRL x (MOVQconst [c]))
+ // result: (SHRLconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64SHRLconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRL x (MOVLconst [c]))
+ // result: (SHRLconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64SHRLconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRL x (ADDQconst [c] y))
+ // cond: c & 31 == 0
+ // result: (SHRL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHRL x (NEGQ <t> (ADDQconst [c] y)))
+ // cond: c & 31 == 0
+ // result: (SHRL x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHRL x (ANDQconst [c] y))
+ // cond: c & 31 == 31
+ // result: (SHRL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHRL x (NEGQ <t> (ANDQconst [c] y)))
+ // cond: c & 31 == 31
+ // result: (SHRL x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHRL x (ADDLconst [c] y))
+ // cond: c & 31 == 0
+ // result: (SHRL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHRL x (NEGL <t> (ADDLconst [c] y)))
+ // cond: c & 31 == 0
+ // result: (SHRL x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHRL x (ANDLconst [c] y))
+ // cond: c & 31 == 31
+ // result: (SHRL x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHRL x (NEGL <t> (ANDLconst [c] y)))
+ // cond: c & 31 == 31
+ // result: (SHRL x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&31 == 31) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHRLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SHRLconst [1] (SHLLconst [1] x))
+ // result: (BTRLconst [31] x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpAMD64SHLLconst || auxIntToInt8(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTRLconst)
+ v.AuxInt = int8ToAuxInt(31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRLconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHRQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SHRQ x (MOVQconst [c]))
+ // result: (SHRQconst [int8(c&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpAMD64SHRQconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRQ x (MOVLconst [c]))
+ // result: (SHRQconst [int8(c&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64SHRQconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRQ x (ADDQconst [c] y))
+ // cond: c & 63 == 0
+ // result: (SHRQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHRQ x (NEGQ <t> (ADDQconst [c] y)))
+ // cond: c & 63 == 0
+ // result: (SHRQ x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHRQ x (ANDQconst [c] y))
+ // cond: c & 63 == 63
+ // result: (SHRQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHRQ x (NEGQ <t> (ANDQconst [c] y)))
+ // cond: c & 63 == 63
+ // result: (SHRQ x (NEGQ <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGQ {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDQconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHRQ x (ADDLconst [c] y))
+ // cond: c & 63 == 0
+ // result: (SHRQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHRQ x (NEGL <t> (ADDLconst [c] y)))
+ // cond: c & 63 == 0
+ // result: (SHRQ x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ADDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 0) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SHRQ x (ANDLconst [c] y))
+ // cond: c & 63 == 63
+ // result: (SHRQ x y)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SHRQ x (NEGL <t> (ANDLconst [c] y)))
+ // cond: c & 63 == 63
+ // result: (SHRQ x (NEGL <t> y))
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64NEGL {
+ break
+ }
+ t := v_1.Type
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ y := v_1_0.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGL, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHRQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SHRQconst [1] (SHLQconst [1] x))
+ // result: (BTRQconst [63] x)
+ for {
+ if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpAMD64SHLQconst || auxIntToInt8(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64BTRQconst)
+ v.AuxInt = int8ToAuxInt(63)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRQconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHRW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SHRW x (MOVQconst [c]))
+ // cond: c&31 < 16
+ // result: (SHRWconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c&31 < 16) {
+ break
+ }
+ v.reset(OpAMD64SHRWconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRW x (MOVLconst [c]))
+ // cond: c&31 < 16
+ // result: (SHRWconst [int8(c&31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c&31 < 16) {
+ break
+ }
+ v.reset(OpAMD64SHRWconst)
+ v.AuxInt = int8ToAuxInt(int8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SHRW _ (MOVQconst [c]))
+ // cond: c&31 >= 16
+ // result: (MOVLconst [0])
+ for {
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c&31 >= 16) {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SHRW _ (MOVLconst [c]))
+ // cond: c&31 >= 16
+ // result: (MOVLconst [0])
+ for {
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c&31 >= 16) {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SHRWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SHRWconst x [0])
+ // result: x
+ for {
+ if auxIntToInt8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBL x (MOVLconst [c]))
+ // result: (SUBLconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64SUBLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBL (MOVLconst [c]) x)
+ // result: (NEGL (SUBLconst <v.Type> x [c]))
+ for {
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpAMD64NEGL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SUBLconst, v.Type)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBL x x)
+ // result: (MOVLconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SUBL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (SUBLload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVLload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64SUBLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SUBLconst [c] x)
+ // cond: c==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUBLconst [c] x)
+ // result: (ADDLconst [-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ v.reset(OpAMD64ADDLconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAMD64SUBLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SUBLload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SUBLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SUBLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBLload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SUBLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SUBLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBLload x [off] {sym} ptr (MOVSSstore [off] {sym} ptr y _))
+ // result: (SUBL x (MOVLf2i y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVSSstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64SUBL)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVLf2i, typ.UInt32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SUBLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SUBLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SUBLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SUBLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SUBLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBQ x (MOVQconst [c]))
+ // cond: is32Bit(c)
+ // result: (SUBQconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpAMD64SUBQconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBQ (MOVQconst [c]) x)
+ // cond: is32Bit(c)
+ // result: (NEGQ (SUBQconst <v.Type> x [int32(c)]))
+ for {
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpAMD64NEGQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64SUBQconst, v.Type)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBQ x x)
+ // result: (MOVQconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SUBQ x l:(MOVQload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (SUBQload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVQload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64SUBQload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBQborrow(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBQborrow x (MOVQconst [c]))
+ // cond: is32Bit(c)
+ // result: (SUBQconstborrow x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpAMD64SUBQconstborrow)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SUBQconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUBQconst [c] x)
+ // cond: c != -(1<<31)
+ // result: (ADDQconst [-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c != -(1 << 31)) {
+ break
+ }
+ v.reset(OpAMD64ADDQconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBQconst (MOVQconst [d]) [c])
+ // result: (MOVQconst [d-int64(c)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(d - int64(c))
+ return true
+ }
+ // match: (SUBQconst (SUBQconst x [d]) [c])
+ // cond: is32Bit(int64(-c)-int64(d))
+ // result: (ADDQconst [-c-d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64SUBQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(-c) - int64(d))) {
+ break
+ }
+ v.reset(OpAMD64ADDQconst)
+ v.AuxInt = int32ToAuxInt(-c - d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBQload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SUBQload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SUBQload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SUBQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBQload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SUBQload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SUBQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBQload x [off] {sym} ptr (MOVSDstore [off] {sym} ptr y _))
+ // result: (SUBQ x (MOVQf2i y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVSDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64SUBQ)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVQf2i, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBQmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SUBQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SUBQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (SUBQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SUBQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SUBQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBSD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBSD x l:(MOVSDload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (SUBSDload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVSDload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64SUBSDload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBSDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SUBSDload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SUBSDload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SUBSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBSDload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SUBSDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SUBSDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBSDload x [off] {sym} ptr (MOVQstore [off] {sym} ptr y _))
+ // result: (SUBSD x (MOVQi2f y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVQstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64SUBSD)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVQi2f, typ.Float64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBSS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBSS x l:(MOVSSload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (SUBSSload x [off] {sym} ptr mem)
+ for {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVSSload {
+ break
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64SUBSSload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64SUBSSload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SUBSSload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (SUBSSload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64SUBSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBSSload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (SUBSSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64SUBSSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (SUBSSload x [off] {sym} ptr (MOVLstore [off] {sym} ptr y _))
+ // result: (SUBSS x (MOVLi2f y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVLstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64SUBSS)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVLi2f, typ.Float32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64TESTB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TESTB (MOVLconst [c]) x)
+ // result: (TESTBconst [int8(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpAMD64TESTBconst)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (TESTB l:(MOVBload {sym} [off] ptr mem) l2)
+ // cond: l == l2 && l.Uses == 2 && validValAndOff(0, int64(off)) && clobber(l)
+ // result: @l.Block (CMPBconstload {sym} [makeValAndOff64(0, int64(off))] ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ l := v_0
+ if l.Op != OpAMD64MOVBload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ l2 := v_1
+ if !(l == l2 && l.Uses == 2 && validValAndOff(0, int64(off)) && clobber(l)) {
+ continue
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPBconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff64(0, int64(off)))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64TESTBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (TESTBconst [-1] x)
+ // cond: x.Op != OpAMD64MOVLconst
+ // result: (TESTB x x)
+ for {
+ if auxIntToInt8(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ if !(x.Op != OpAMD64MOVLconst) {
+ break
+ }
+ v.reset(OpAMD64TESTB)
+ v.AddArg2(x, x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64TESTL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TESTL (MOVLconst [c]) x)
+ // result: (TESTLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpAMD64TESTLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (TESTL l:(MOVLload {sym} [off] ptr mem) l2)
+ // cond: l == l2 && l.Uses == 2 && validValAndOff(0, int64(off)) && clobber(l)
+ // result: @l.Block (CMPLconstload {sym} [makeValAndOff64(0, int64(off))] ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ l := v_0
+ if l.Op != OpAMD64MOVLload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ l2 := v_1
+ if !(l == l2 && l.Uses == 2 && validValAndOff(0, int64(off)) && clobber(l)) {
+ continue
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPLconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff64(0, int64(off)))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64TESTLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (TESTLconst [c] (MOVLconst [c]))
+ // cond: c == 0
+ // result: (FlagEQ)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_0.AuxInt) != c || !(c == 0) {
+ break
+ }
+ v.reset(OpAMD64FlagEQ)
+ return true
+ }
+ // match: (TESTLconst [c] (MOVLconst [c]))
+ // cond: c < 0
+ // result: (FlagLT_UGT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_0.AuxInt) != c || !(c < 0) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_UGT)
+ return true
+ }
+ // match: (TESTLconst [c] (MOVLconst [c]))
+ // cond: c > 0
+ // result: (FlagGT_UGT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_0.AuxInt) != c || !(c > 0) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_UGT)
+ return true
+ }
+ // match: (TESTLconst [-1] x)
+ // cond: x.Op != OpAMD64MOVLconst
+ // result: (TESTL x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ if !(x.Op != OpAMD64MOVLconst) {
+ break
+ }
+ v.reset(OpAMD64TESTL)
+ v.AddArg2(x, x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64TESTQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TESTQ (MOVQconst [c]) x)
+ // cond: is32Bit(c)
+ // result: (TESTQconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpAMD64TESTQconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (TESTQ l:(MOVQload {sym} [off] ptr mem) l2)
+ // cond: l == l2 && l.Uses == 2 && validValAndOff(0, int64(off)) && clobber(l)
+ // result: @l.Block (CMPQconstload {sym} [makeValAndOff64(0, int64(off))] ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ l := v_0
+ if l.Op != OpAMD64MOVQload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ l2 := v_1
+ if !(l == l2 && l.Uses == 2 && validValAndOff(0, int64(off)) && clobber(l)) {
+ continue
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPQconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff64(0, int64(off)))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64TESTQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (TESTQconst [c] (MOVQconst [d]))
+ // cond: int64(c) == d && c == 0
+ // result: (FlagEQ)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ if !(int64(c) == d && c == 0) {
+ break
+ }
+ v.reset(OpAMD64FlagEQ)
+ return true
+ }
+ // match: (TESTQconst [c] (MOVQconst [d]))
+ // cond: int64(c) == d && c < 0
+ // result: (FlagLT_UGT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ if !(int64(c) == d && c < 0) {
+ break
+ }
+ v.reset(OpAMD64FlagLT_UGT)
+ return true
+ }
+ // match: (TESTQconst [c] (MOVQconst [d]))
+ // cond: int64(c) == d && c > 0
+ // result: (FlagGT_UGT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ if !(int64(c) == d && c > 0) {
+ break
+ }
+ v.reset(OpAMD64FlagGT_UGT)
+ return true
+ }
+ // match: (TESTQconst [-1] x)
+ // cond: x.Op != OpAMD64MOVQconst
+ // result: (TESTQ x x)
+ for {
+ if auxIntToInt32(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ if !(x.Op != OpAMD64MOVQconst) {
+ break
+ }
+ v.reset(OpAMD64TESTQ)
+ v.AddArg2(x, x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64TESTW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TESTW (MOVLconst [c]) x)
+ // result: (TESTWconst [int16(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpAMD64TESTWconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (TESTW l:(MOVWload {sym} [off] ptr mem) l2)
+ // cond: l == l2 && l.Uses == 2 && validValAndOff(0, int64(off)) && clobber(l)
+ // result: @l.Block (CMPWconstload {sym} [makeValAndOff64(0, int64(off))] ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ l := v_0
+ if l.Op != OpAMD64MOVWload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ l2 := v_1
+ if !(l == l2 && l.Uses == 2 && validValAndOff(0, int64(off)) && clobber(l)) {
+ continue
+ }
+ b = l.Block
+ v0 := b.NewValue0(l.Pos, OpAMD64CMPWconstload, types.TypeFlags)
+ v.copyOf(v0)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff64(0, int64(off)))
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64TESTWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (TESTWconst [-1] x)
+ // cond: x.Op != OpAMD64MOVLconst
+ // result: (TESTW x x)
+ for {
+ if auxIntToInt16(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ if !(x.Op != OpAMD64MOVLconst) {
+ break
+ }
+ v.reset(OpAMD64TESTW)
+ v.AddArg2(x, x)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XADDLlock(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XADDLlock [off1] {sym} val (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (XADDLlock [off1+off2] {sym} val ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64XADDLlock)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XADDQlock(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XADDQlock [off1] {sym} val (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (XADDQlock [off1+off2] {sym} val ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64XADDQlock)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XCHGL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XCHGL [off1] {sym} val (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (XCHGL [off1+off2] {sym} val ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64XCHGL)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, ptr, mem)
+ return true
+ }
+ // match: (XCHGL [off1] {sym1} val (LEAQ [off2] {sym2} ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && ptr.Op != OpSB
+ // result: (XCHGL [off1+off2] {mergeSym(sym1,sym2)} val ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && ptr.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64XCHGL)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XCHGQ(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XCHGQ [off1] {sym} val (ADDQconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (XCHGQ [off1+off2] {sym} val ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64XCHGQ)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, ptr, mem)
+ return true
+ }
+ // match: (XCHGQ [off1] {sym1} val (LEAQ [off2] {sym2} ptr) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && ptr.Op != OpSB
+ // result: (XCHGQ [off1+off2] {mergeSym(sym1,sym2)} val ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && ptr.Op != OpSB) {
+ break
+ }
+ v.reset(OpAMD64XCHGQ)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XORL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XORL (SHLL (MOVLconst [1]) y) x)
+ // result: (BTCL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLL {
+ continue
+ }
+ y := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_0_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpAMD64BTCL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XORL (MOVLconst [c]) x)
+ // cond: isUint32PowerOfTwo(int64(c)) && uint64(c) >= 128
+ // result: (BTCLconst [int8(log32(c))] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ if !(isUint32PowerOfTwo(int64(c)) && uint64(c) >= 128) {
+ continue
+ }
+ v.reset(OpAMD64BTCLconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORL x (MOVLconst [c]))
+ // result: (XORLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORL (SHLLconst x [c]) (SHRLconst x [d]))
+ // cond: d==32-c
+ // result: (ROLLconst x [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRLconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 32-c) {
+ continue
+ }
+ v.reset(OpAMD64ROLLconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORL <t> (SHLLconst x [c]) (SHRWconst x [d]))
+ // cond: d==16-c && c < 16 && t.Size() == 2
+ // result: (ROLWconst x [c])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRWconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 16-c && c < 16 && t.Size() == 2) {
+ continue
+ }
+ v.reset(OpAMD64ROLWconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORL <t> (SHLLconst x [c]) (SHRBconst x [d]))
+ // cond: d==8-c && c < 8 && t.Size() == 1
+ // result: (ROLBconst x [c])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLLconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRBconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 8-c && c < 8 && t.Size() == 1) {
+ continue
+ }
+ v.reset(OpAMD64ROLBconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORL x x)
+ // result: (MOVLconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (XORL x l:(MOVLload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (XORLload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVLload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64XORLload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XORLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (XORLconst [c] x)
+ // cond: isUint32PowerOfTwo(int64(c)) && uint64(c) >= 128
+ // result: (BTCLconst [int8(log32(c))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isUint32PowerOfTwo(int64(c)) && uint64(c) >= 128) {
+ break
+ }
+ v.reset(OpAMD64BTCLconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [1] (SETNE x))
+ // result: (SETEQ x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_0.Op != OpAMD64SETNE {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETEQ)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [1] (SETEQ x))
+ // result: (SETNE x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_0.Op != OpAMD64SETEQ {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETNE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [1] (SETL x))
+ // result: (SETGE x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_0.Op != OpAMD64SETL {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETGE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [1] (SETGE x))
+ // result: (SETL x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_0.Op != OpAMD64SETGE {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETL)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [1] (SETLE x))
+ // result: (SETG x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_0.Op != OpAMD64SETLE {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETG)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [1] (SETG x))
+ // result: (SETLE x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_0.Op != OpAMD64SETG {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETLE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [1] (SETB x))
+ // result: (SETAE x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_0.Op != OpAMD64SETB {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETAE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [1] (SETAE x))
+ // result: (SETB x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_0.Op != OpAMD64SETAE {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETB)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [1] (SETBE x))
+ // result: (SETA x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_0.Op != OpAMD64SETBE {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETA)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [1] (SETA x))
+ // result: (SETBE x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_0.Op != OpAMD64SETA {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETBE)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [c] (XORLconst [d] x))
+ // result: (XORLconst [c ^ d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64XORLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = int32ToAuxInt(c ^ d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [c] (BTCLconst [d] x))
+ // result: (XORLconst [c ^ 1<<uint32(d)] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64BTCLconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = int32ToAuxInt(c ^ 1<<uint32(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORLconst [c] x)
+ // cond: c==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (XORLconst [c] (MOVLconst [d]))
+ // result: (MOVLconst [c^d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(c ^ d)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XORLconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XORLconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (XORLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64XORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (XORLconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (XORLconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64XORLconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XORLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (XORLload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (XORLload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64XORLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (XORLload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (XORLload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64XORLload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (XORLload x [off] {sym} ptr (MOVSSstore [off] {sym} ptr y _))
+ // result: (XORL x (MOVLf2i y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVSSstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64XORL)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVLf2i, typ.UInt32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XORLmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORLmodify [off] {sym} ptr s:(SHLL (MOVLconst [1]) <t> x) mem)
+ // result: (BTCLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ s := v_1
+ if s.Op != OpAMD64SHLL {
+ break
+ }
+ t := s.Type
+ x := s.Args[1]
+ s_0 := s.Args[0]
+ if s_0.Op != OpAMD64MOVLconst || auxIntToInt32(s_0.AuxInt) != 1 {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64BTCLmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64ANDLconst, t)
+ v0.AuxInt = int32ToAuxInt(31)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (XORLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (XORLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64XORLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (XORLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (XORLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64XORLmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XORQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XORQ (SHLQ (MOVQconst [1]) y) x)
+ // result: (BTCQ x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ y := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_0_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpAMD64BTCQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XORQ (MOVQconst [c]) x)
+ // cond: isUint64PowerOfTwo(c) && uint64(c) >= 128
+ // result: (BTCQconst [int8(log64(c))] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(isUint64PowerOfTwo(c) && uint64(c) >= 128) {
+ continue
+ }
+ v.reset(OpAMD64BTCQconst)
+ v.AuxInt = int8ToAuxInt(int8(log64(c)))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORQ x (MOVQconst [c]))
+ // cond: is32Bit(c)
+ // result: (XORQconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpAMD64XORQconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORQ (SHLQconst x [c]) (SHRQconst x [d]))
+ // cond: d==64-c
+ // result: (ROLQconst x [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAMD64SHLQconst {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpAMD64SHRQconst {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 64-c) {
+ continue
+ }
+ v.reset(OpAMD64ROLQconst)
+ v.AuxInt = int8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORQ x x)
+ // result: (MOVQconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (XORQ x l:(MOVQload [off] {sym} ptr mem))
+ // cond: canMergeLoadClobber(v, l, x) && clobber(l)
+ // result: (XORQload x [off] {sym} ptr mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ l := v_1
+ if l.Op != OpAMD64MOVQload {
+ continue
+ }
+ off := auxIntToInt32(l.AuxInt)
+ sym := auxToSym(l.Aux)
+ mem := l.Args[1]
+ ptr := l.Args[0]
+ if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
+ continue
+ }
+ v.reset(OpAMD64XORQload)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XORQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (XORQconst [c] x)
+ // cond: isUint64PowerOfTwo(int64(c)) && uint64(c) >= 128
+ // result: (BTCQconst [int8(log32(c))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isUint64PowerOfTwo(int64(c)) && uint64(c) >= 128) {
+ break
+ }
+ v.reset(OpAMD64BTCQconst)
+ v.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORQconst [c] (XORQconst [d] x))
+ // result: (XORQconst [c ^ d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64XORQconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORQconst)
+ v.AuxInt = int32ToAuxInt(c ^ d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORQconst [c] (BTCQconst [d] x))
+ // cond: is32Bit(int64(c) ^ 1<<uint32(d))
+ // result: (XORQconst [c ^ 1<<uint32(d)] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64BTCQconst {
+ break
+ }
+ d := auxIntToInt8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) ^ 1<<uint32(d))) {
+ break
+ }
+ v.reset(OpAMD64XORQconst)
+ v.AuxInt = int32ToAuxInt(c ^ 1<<uint32(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORQconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (XORQconst [c] (MOVQconst [d]))
+ // result: (MOVQconst [int64(c)^d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(int64(c) ^ d)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XORQconstmodify(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XORQconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2)
+ // result: (XORQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {sym} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2)) {
+ break
+ }
+ v.reset(OpAMD64XORQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (XORQconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)
+ // result: (XORQconstmodify [ValAndOff(valoff1).addOffset32(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(ValAndOff(valoff1).canAdd32(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64XORQconstmodify)
+ v.AuxInt = valAndOffToAuxInt(ValAndOff(valoff1).addOffset32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XORQload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (XORQload [off1] {sym} val (ADDQconst [off2] base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (XORQload [off1+off2] {sym} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64XORQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (XORQload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (XORQload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ val := v_0
+ if v_1.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ base := v_1.Args[0]
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64XORQload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(val, base, mem)
+ return true
+ }
+ // match: (XORQload x [off] {sym} ptr (MOVSDstore [off] {sym} ptr y _))
+ // result: (XORQ x (MOVQf2i y))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr := v_1
+ if v_2.Op != OpAMD64MOVSDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ if ptr != v_2.Args[0] {
+ break
+ }
+ v.reset(OpAMD64XORQ)
+ v0 := b.NewValue0(v_2.Pos, OpAMD64MOVQf2i, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64XORQmodify(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORQmodify [off] {sym} ptr s:(SHLQ (MOVQconst [1]) <t> x) mem)
+ // result: (BTCQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ s := v_1
+ if s.Op != OpAMD64SHLQ {
+ break
+ }
+ t := s.Type
+ x := s.Args[1]
+ s_0 := s.Args[0]
+ if s_0.Op != OpAMD64MOVQconst || auxIntToInt64(s_0.AuxInt) != 1 {
+ break
+ }
+ mem := v_2
+ v.reset(OpAMD64BTCQmodify)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpAMD64ANDQconst, t)
+ v0.AuxInt = int32ToAuxInt(63)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (XORQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2))
+ // result: (XORQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpAMD64XORQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (XORQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (XORQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64XORQmodify)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Addr {sym} base)
+ // result: (LEAQ {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpAMD64LEAQ)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicAdd32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicAdd32 ptr val mem)
+ // result: (AddTupleFirst32 val (XADDLlock val ptr mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpAMD64AddTupleFirst32)
+ v0 := b.NewValue0(v.Pos, OpAMD64XADDLlock, types.NewTuple(typ.UInt32, types.TypeMem))
+ v0.AddArg3(val, ptr, mem)
+ v.AddArg2(val, v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicAdd64(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicAdd64 ptr val mem)
+ // result: (AddTupleFirst64 val (XADDQlock val ptr mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpAMD64AddTupleFirst64)
+ v0 := b.NewValue0(v.Pos, OpAMD64XADDQlock, types.NewTuple(typ.UInt64, types.TypeMem))
+ v0.AddArg3(val, ptr, mem)
+ v.AddArg2(val, v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicAnd32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicAnd32 ptr val mem)
+ // result: (ANDLlock ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpAMD64ANDLlock)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicAnd8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicAnd8 ptr val mem)
+ // result: (ANDBlock ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpAMD64ANDBlock)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicCompareAndSwap32(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicCompareAndSwap32 ptr old new_ mem)
+ // result: (CMPXCHGLlock ptr old new_ mem)
+ for {
+ ptr := v_0
+ old := v_1
+ new_ := v_2
+ mem := v_3
+ v.reset(OpAMD64CMPXCHGLlock)
+ v.AddArg4(ptr, old, new_, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicCompareAndSwap64(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicCompareAndSwap64 ptr old new_ mem)
+ // result: (CMPXCHGQlock ptr old new_ mem)
+ for {
+ ptr := v_0
+ old := v_1
+ new_ := v_2
+ mem := v_3
+ v.reset(OpAMD64CMPXCHGQlock)
+ v.AddArg4(ptr, old, new_, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicExchange32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicExchange32 ptr val mem)
+ // result: (XCHGL val ptr mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpAMD64XCHGL)
+ v.AddArg3(val, ptr, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicExchange64(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicExchange64 ptr val mem)
+ // result: (XCHGQ val ptr mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpAMD64XCHGQ)
+ v.AddArg3(val, ptr, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicLoad32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoad32 ptr mem)
+ // result: (MOVLatomicload ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVLatomicload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicLoad64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoad64 ptr mem)
+ // result: (MOVQatomicload ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVQatomicload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicLoad8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoad8 ptr mem)
+ // result: (MOVBatomicload ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVBatomicload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicLoadPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoadPtr ptr mem)
+ // result: (MOVQatomicload ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVQatomicload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicOr32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicOr32 ptr val mem)
+ // result: (ORLlock ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpAMD64ORLlock)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicOr8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicOr8 ptr val mem)
+ // result: (ORBlock ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpAMD64ORBlock)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicStore32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicStore32 ptr val mem)
+ // result: (Select1 (XCHGL <types.NewTuple(typ.UInt32,types.TypeMem)> val ptr mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64XCHGL, types.NewTuple(typ.UInt32, types.TypeMem))
+ v0.AddArg3(val, ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicStore64(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicStore64 ptr val mem)
+ // result: (Select1 (XCHGQ <types.NewTuple(typ.UInt64,types.TypeMem)> val ptr mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64XCHGQ, types.NewTuple(typ.UInt64, types.TypeMem))
+ v0.AddArg3(val, ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicStore8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicStore8 ptr val mem)
+ // result: (Select1 (XCHGB <types.NewTuple(typ.UInt8,types.TypeMem)> val ptr mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64XCHGB, types.NewTuple(typ.UInt8, types.TypeMem))
+ v0.AddArg3(val, ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpAtomicStorePtrNoWB(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicStorePtrNoWB ptr val mem)
+ // result: (Select1 (XCHGQ <types.NewTuple(typ.BytePtr,types.TypeMem)> val ptr mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64XCHGQ, types.NewTuple(typ.BytePtr, types.TypeMem))
+ v0.AddArg3(val, ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpBitLen16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen16 x)
+ // result: (BSRL (LEAL1 <typ.UInt32> [1] (MOVWQZX <typ.UInt32> x) (MOVWQZX <typ.UInt32> x)))
+ for {
+ x := v_0
+ v.reset(OpAMD64BSRL)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL1, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVWQZX, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpBitLen32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen32 x)
+ // result: (Select0 (BSRQ (LEAQ1 <typ.UInt64> [1] (MOVLQZX <typ.UInt64> x) (MOVLQZX <typ.UInt64> x))))
+ for {
+ x := v_0
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64BSRQ, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1 := b.NewValue0(v.Pos, OpAMD64LEAQ1, typ.UInt64)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVLQZX, typ.UInt64)
+ v2.AddArg(x)
+ v1.AddArg2(v2, v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpBitLen64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen64 <t> x)
+ // result: (ADDQconst [1] (CMOVQEQ <t> (Select0 <t> (BSRQ x)) (MOVQconst <t> [-1]) (Select1 <types.TypeFlags> (BSRQ x))))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpAMD64ADDQconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMOVQEQ, t)
+ v1 := b.NewValue0(v.Pos, OpSelect0, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64BSRQ, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v2.AddArg(x)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpAMD64MOVQconst, t)
+ v3.AuxInt = int64ToAuxInt(-1)
+ v4 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v4.AddArg(v2)
+ v0.AddArg3(v1, v3, v4)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpBitLen8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen8 x)
+ // result: (BSRL (LEAL1 <typ.UInt32> [1] (MOVBQZX <typ.UInt32> x) (MOVBQZX <typ.UInt32> x)))
+ for {
+ x := v_0
+ v.reset(OpAMD64BSRL)
+ v0 := b.NewValue0(v.Pos, OpAMD64LEAL1, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVBQZX, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpCeil(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Ceil x)
+ // result: (ROUNDSD [2] x)
+ for {
+ x := v_0
+ v.reset(OpAMD64ROUNDSD)
+ v.AuxInt = int8ToAuxInt(2)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueAMD64_OpCondSelect(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CondSelect <t> x y (SETEQ cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQEQ y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETEQ {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQEQ)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETNE cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQNE y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETNE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQNE)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETL cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQLT y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETL {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQLT)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETG cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQGT y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETG {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQGT)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETLE cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQLE y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETLE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQLE)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETGE cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQGE y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETGE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQGE)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETA cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQHI y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETA {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQHI)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETB cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQCS y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETB {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQCS)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETAE cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQCC y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETAE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQCC)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETBE cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQLS y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETBE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQLS)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETEQF cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQEQF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETEQF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQEQF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETNEF cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQNEF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETNEF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQNEF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETGF cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQGTF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETGF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQGTF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETGEF cond))
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQGEF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETGEF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVQGEF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETEQ cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLEQ y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETEQ {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLEQ)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETNE cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLNE y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETNE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLNE)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETL cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLLT y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETL {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLLT)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETG cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLGT y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETG {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLGT)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETLE cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLLE y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETLE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLLE)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETGE cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLGE y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETGE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLGE)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETA cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLHI y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETA {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLHI)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETB cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLCS y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETB {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLCS)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETAE cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLCC y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETAE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLCC)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETBE cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLLS y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETBE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLLS)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETEQF cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLEQF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETEQF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLEQF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETNEF cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLNEF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETNEF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLNEF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETGF cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLGTF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETGF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLGTF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETGEF cond))
+ // cond: is32BitInt(t)
+ // result: (CMOVLGEF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETGEF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLGEF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETEQ cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWEQ y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETEQ {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWEQ)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETNE cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWNE y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETNE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWNE)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETL cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWLT y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETL {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWLT)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETG cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWGT y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETG {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWGT)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETLE cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWLE y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETLE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWLE)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETGE cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWGE y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETGE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWGE)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETA cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWHI y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETA {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWHI)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETB cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWCS y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETB {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWCS)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETAE cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWCC y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETAE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWCC)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETBE cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWLS y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETBE {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWLS)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETEQF cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWEQF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETEQF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWEQF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETNEF cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWNEF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETNEF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWNEF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETGF cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWGTF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETGF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWGTF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y (SETGEF cond))
+ // cond: is16BitInt(t)
+ // result: (CMOVWGEF y x cond)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if v_2.Op != OpAMD64SETGEF {
+ break
+ }
+ cond := v_2.Args[0]
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWGEF)
+ v.AddArg3(y, x, cond)
+ return true
+ }
+ // match: (CondSelect <t> x y check)
+ // cond: !check.Type.IsFlags() && check.Type.Size() == 1
+ // result: (CondSelect <t> x y (MOVBQZX <typ.UInt64> check))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ check := v_2
+ if !(!check.Type.IsFlags() && check.Type.Size() == 1) {
+ break
+ }
+ v.reset(OpCondSelect)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVBQZX, typ.UInt64)
+ v0.AddArg(check)
+ v.AddArg3(x, y, v0)
+ return true
+ }
+ // match: (CondSelect <t> x y check)
+ // cond: !check.Type.IsFlags() && check.Type.Size() == 2
+ // result: (CondSelect <t> x y (MOVWQZX <typ.UInt64> check))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ check := v_2
+ if !(!check.Type.IsFlags() && check.Type.Size() == 2) {
+ break
+ }
+ v.reset(OpCondSelect)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWQZX, typ.UInt64)
+ v0.AddArg(check)
+ v.AddArg3(x, y, v0)
+ return true
+ }
+ // match: (CondSelect <t> x y check)
+ // cond: !check.Type.IsFlags() && check.Type.Size() == 4
+ // result: (CondSelect <t> x y (MOVLQZX <typ.UInt64> check))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ check := v_2
+ if !(!check.Type.IsFlags() && check.Type.Size() == 4) {
+ break
+ }
+ v.reset(OpCondSelect)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLQZX, typ.UInt64)
+ v0.AddArg(check)
+ v.AddArg3(x, y, v0)
+ return true
+ }
+ // match: (CondSelect <t> x y check)
+ // cond: !check.Type.IsFlags() && check.Type.Size() == 8 && (is64BitInt(t) || isPtr(t))
+ // result: (CMOVQNE y x (CMPQconst [0] check))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ check := v_2
+ if !(!check.Type.IsFlags() && check.Type.Size() == 8 && (is64BitInt(t) || isPtr(t))) {
+ break
+ }
+ v.reset(OpAMD64CMOVQNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(check)
+ v.AddArg3(y, x, v0)
+ return true
+ }
+ // match: (CondSelect <t> x y check)
+ // cond: !check.Type.IsFlags() && check.Type.Size() == 8 && is32BitInt(t)
+ // result: (CMOVLNE y x (CMPQconst [0] check))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ check := v_2
+ if !(!check.Type.IsFlags() && check.Type.Size() == 8 && is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVLNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(check)
+ v.AddArg3(y, x, v0)
+ return true
+ }
+ // match: (CondSelect <t> x y check)
+ // cond: !check.Type.IsFlags() && check.Type.Size() == 8 && is16BitInt(t)
+ // result: (CMOVWNE y x (CMPQconst [0] check))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ check := v_2
+ if !(!check.Type.IsFlags() && check.Type.Size() == 8 && is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64CMOVWNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(check)
+ v.AddArg3(y, x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpConst16(v *Value) bool {
+ // match: (Const16 [c])
+ // result: (MOVLconst [int32(c)])
+ for {
+ c := auxIntToInt16(v.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ return true
+ }
+}
+func rewriteValueAMD64_OpConst8(v *Value) bool {
+ // match: (Const8 [c])
+ // result: (MOVLconst [int32(c)])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ return true
+ }
+}
+func rewriteValueAMD64_OpConstBool(v *Value) bool {
+ // match: (ConstBool [c])
+ // result: (MOVLconst [b2i32(c)])
+ for {
+ c := auxIntToBool(v.AuxInt)
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = int32ToAuxInt(b2i32(c))
+ return true
+ }
+}
+func rewriteValueAMD64_OpConstNil(v *Value) bool {
+ // match: (ConstNil )
+ // result: (MOVQconst [0])
+ for {
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpCtz16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz16 x)
+ // result: (BSFL (BTSLconst <typ.UInt32> [16] x))
+ for {
+ x := v_0
+ v.reset(OpAMD64BSFL)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTSLconst, typ.UInt32)
+ v0.AuxInt = int8ToAuxInt(16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpCtz32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz32 x)
+ // result: (Select0 (BSFQ (BTSQconst <typ.UInt64> [32] x)))
+ for {
+ x := v_0
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64BSFQ, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1 := b.NewValue0(v.Pos, OpAMD64BTSQconst, typ.UInt64)
+ v1.AuxInt = int8ToAuxInt(32)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpCtz64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz64 <t> x)
+ // result: (CMOVQEQ (Select0 <t> (BSFQ x)) (MOVQconst <t> [64]) (Select1 <types.TypeFlags> (BSFQ x)))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpAMD64CMOVQEQ)
+ v0 := b.NewValue0(v.Pos, OpSelect0, t)
+ v1 := b.NewValue0(v.Pos, OpAMD64BSFQ, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVQconst, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueAMD64_OpCtz64NonZero(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz64NonZero x)
+ // result: (Select0 (BSFQ x))
+ for {
+ x := v_0
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64BSFQ, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpCtz8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz8 x)
+ // result: (BSFL (BTSLconst <typ.UInt32> [ 8] x))
+ for {
+ x := v_0
+ v.reset(OpAMD64BSFL)
+ v0 := b.NewValue0(v.Pos, OpAMD64BTSLconst, typ.UInt32)
+ v0.AuxInt = int8ToAuxInt(8)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpDiv16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16 [a] x y)
+ // result: (Select0 (DIVW [a] x y))
+ for {
+ a := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVW, types.NewTuple(typ.Int16, typ.Int16))
+ v0.AuxInt = boolToAuxInt(a)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpDiv16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16u x y)
+ // result: (Select0 (DIVWU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVWU, types.NewTuple(typ.UInt16, typ.UInt16))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpDiv32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32 [a] x y)
+ // result: (Select0 (DIVL [a] x y))
+ for {
+ a := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVL, types.NewTuple(typ.Int32, typ.Int32))
+ v0.AuxInt = boolToAuxInt(a)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpDiv32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32u x y)
+ // result: (Select0 (DIVLU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVLU, types.NewTuple(typ.UInt32, typ.UInt32))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpDiv64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div64 [a] x y)
+ // result: (Select0 (DIVQ [a] x y))
+ for {
+ a := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVQ, types.NewTuple(typ.Int64, typ.Int64))
+ v0.AuxInt = boolToAuxInt(a)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpDiv64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div64u x y)
+ // result: (Select0 (DIVQU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVQU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 x y)
+ // result: (Select0 (DIVW (SignExt8to16 x) (SignExt8to16 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVW, types.NewTuple(typ.Int16, typ.Int16))
+ v1 := b.NewValue0(v.Pos, OpSignExt8to16, typ.Int16)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to16, typ.Int16)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u x y)
+ // result: (Select0 (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVWU, types.NewTuple(typ.UInt16, typ.UInt16))
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to16, typ.UInt16)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to16, typ.UInt16)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq16 x y)
+ // result: (SETEQ (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETEQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32 x y)
+ // result: (SETEQ (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETEQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpEq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32F x y)
+ // result: (SETEQF (UCOMISS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETEQF)
+ v0 := b.NewValue0(v.Pos, OpAMD64UCOMISS, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpEq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64 x y)
+ // result: (SETEQ (CMPQ x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETEQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpEq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64F x y)
+ // result: (SETEQF (UCOMISD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETEQF)
+ v0 := b.NewValue0(v.Pos, OpAMD64UCOMISD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq8 x y)
+ // result: (SETEQ (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETEQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpEqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (EqB x y)
+ // result: (SETEQ (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETEQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpEqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (EqPtr x y)
+ // result: (SETEQ (CMPQ x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETEQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpFMA(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMA x y z)
+ // result: (VFMADD231SD z x y)
+ for {
+ x := v_0
+ y := v_1
+ z := v_2
+ v.reset(OpAMD64VFMADD231SD)
+ v.AddArg3(z, x, y)
+ return true
+ }
+}
+func rewriteValueAMD64_OpFloor(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Floor x)
+ // result: (ROUNDSD [1] x)
+ for {
+ x := v_0
+ v.reset(OpAMD64ROUNDSD)
+ v.AuxInt = int8ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueAMD64_OpHasCPUFeature(v *Value) bool {
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (HasCPUFeature {s})
+ // result: (SETNE (CMPQconst [0] (LoweredHasCPUFeature {s})))
+ for {
+ s := auxToSym(v.Aux)
+ v.reset(OpAMD64SETNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpAMD64LoweredHasCPUFeature, typ.UInt64)
+ v1.Aux = symToAux(s)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpIsInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsInBounds idx len)
+ // result: (SETB (CMPQ idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsNonNil p)
+ // result: (SETNE (TESTQ p p))
+ for {
+ p := v_0
+ v.reset(OpAMD64SETNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64TESTQ, types.TypeFlags)
+ v0.AddArg2(p, p)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpIsSliceInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsSliceInBounds idx len)
+ // result: (SETBE (CMPQ idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpAMD64SETBE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq16 x y)
+ // result: (SETLE (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETLE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq16U x y)
+ // result: (SETBE (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETBE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32 x y)
+ // result: (SETLE (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETLE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32F x y)
+ // result: (SETGEF (UCOMISS y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETGEF)
+ v0 := b.NewValue0(v.Pos, OpAMD64UCOMISS, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32U x y)
+ // result: (SETBE (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETBE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64 x y)
+ // result: (SETLE (CMPQ x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETLE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64F x y)
+ // result: (SETGEF (UCOMISD y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETGEF)
+ v0 := b.NewValue0(v.Pos, OpAMD64UCOMISD, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLeq64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64U x y)
+ // result: (SETBE (CMPQ x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETBE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq8 x y)
+ // result: (SETLE (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETLE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq8U x y)
+ // result: (SETBE (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETBE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less16 x y)
+ // result: (SETL (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETL)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less16U x y)
+ // result: (SETB (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32 x y)
+ // result: (SETL (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETL)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLess32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32F x y)
+ // result: (SETGF (UCOMISS y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETGF)
+ v0 := b.NewValue0(v.Pos, OpAMD64UCOMISS, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32U x y)
+ // result: (SETB (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLess64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64 x y)
+ // result: (SETL (CMPQ x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETL)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLess64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64F x y)
+ // result: (SETGF (UCOMISD y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETGF)
+ v0 := b.NewValue0(v.Pos, OpAMD64UCOMISD, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLess64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64U x y)
+ // result: (SETB (CMPQ x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less8 x y)
+ // result: (SETL (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETL)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less8U x y)
+ // result: (SETB (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETB)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Load <t> ptr mem)
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (MOVQload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpAMD64MOVQload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitInt(t)
+ // result: (MOVLload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64MOVLload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is16BitInt(t)
+ // result: (MOVWload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64MOVWload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (t.IsBoolean() || is8BitInt(t))
+ // result: (MOVBload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsBoolean() || is8BitInt(t)) {
+ break
+ }
+ v.reset(OpAMD64MOVBload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitFloat(t)
+ // result: (MOVSSload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(OpAMD64MOVSSload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitFloat(t)
+ // result: (MOVSDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(OpAMD64MOVSDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLocalAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LocalAddr {sym} base _)
+ // result: (LEAQ {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpAMD64LEAQ)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueAMD64_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh16x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh16x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPQconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh16x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh16x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh32x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh32x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPQconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh32x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh32x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh64x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDQ (SHLQ <t> x y) (SBBQcarrymask <t> (CMPWconst y [64])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLQ, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh64x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh64x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDQ (SHLQ <t> x y) (SBBQcarrymask <t> (CMPLconst y [64])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLQ, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh64x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh64x64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDQ (SHLQ <t> x y) (SBBQcarrymask <t> (CMPQconst y [64])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLQ, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh64x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh64x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDQ (SHLQ <t> x y) (SBBQcarrymask <t> (CMPBconst y [64])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLQ, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh64x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh8x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh8x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPQconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh8x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Lsh8x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHLL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHLL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpMod16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16 [a] x y)
+ // result: (Select1 (DIVW [a] x y))
+ for {
+ a := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVW, types.NewTuple(typ.Int16, typ.Int16))
+ v0.AuxInt = boolToAuxInt(a)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpMod16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16u x y)
+ // result: (Select1 (DIVWU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVWU, types.NewTuple(typ.UInt16, typ.UInt16))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpMod32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32 [a] x y)
+ // result: (Select1 (DIVL [a] x y))
+ for {
+ a := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVL, types.NewTuple(typ.Int32, typ.Int32))
+ v0.AuxInt = boolToAuxInt(a)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpMod32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32u x y)
+ // result: (Select1 (DIVLU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVLU, types.NewTuple(typ.UInt32, typ.UInt32))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpMod64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod64 [a] x y)
+ // result: (Select1 (DIVQ [a] x y))
+ for {
+ a := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVQ, types.NewTuple(typ.Int64, typ.Int64))
+ v0.AuxInt = boolToAuxInt(a)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpMod64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod64u x y)
+ // result: (Select1 (DIVQU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVQU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8 x y)
+ // result: (Select1 (DIVW (SignExt8to16 x) (SignExt8to16 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVW, types.NewTuple(typ.Int16, typ.Int16))
+ v1 := b.NewValue0(v.Pos, OpSignExt8to16, typ.Int16)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to16, typ.Int16)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8u x y)
+ // result: (Select1 (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpAMD64DIVWU, types.NewTuple(typ.UInt16, typ.UInt16))
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to16, typ.UInt16)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to16, typ.UInt16)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Move [0] _ _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Move [1] dst src mem)
+ // result: (MOVBstore dst (MOVBload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVBload, typ.UInt8)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] dst src mem)
+ // result: (MOVWstore dst (MOVWload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVWstore)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWload, typ.UInt16)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [4] dst src mem)
+ // result: (MOVLstore dst (MOVLload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVLstore)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLload, typ.UInt32)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [8] dst src mem)
+ // result: (MOVQstore dst (MOVQload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVQstore)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [16] dst src mem)
+ // cond: config.useSSE
+ // result: (MOVOstore dst (MOVOload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(config.useSSE) {
+ break
+ }
+ v.reset(OpAMD64MOVOstore)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVOload, types.TypeInt128)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [16] dst src mem)
+ // cond: !config.useSSE
+ // result: (MOVQstore [8] dst (MOVQload [8] src mem) (MOVQstore dst (MOVQload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(!config.useSSE) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVQstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [32] dst src mem)
+ // result: (Move [16] (OffPtr <dst.Type> dst [16]) (OffPtr <src.Type> src [16]) (Move [16] dst src mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 32 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
+ v0.AuxInt = int64ToAuxInt(16)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
+ v1.AuxInt = int64ToAuxInt(16)
+ v1.AddArg(src)
+ v2 := b.NewValue0(v.Pos, OpMove, types.TypeMem)
+ v2.AuxInt = int64ToAuxInt(16)
+ v2.AddArg3(dst, src, mem)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Move [48] dst src mem)
+ // cond: config.useSSE
+ // result: (Move [32] (OffPtr <dst.Type> dst [16]) (OffPtr <src.Type> src [16]) (Move [16] dst src mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 48 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(config.useSSE) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
+ v0.AuxInt = int64ToAuxInt(16)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
+ v1.AuxInt = int64ToAuxInt(16)
+ v1.AddArg(src)
+ v2 := b.NewValue0(v.Pos, OpMove, types.TypeMem)
+ v2.AuxInt = int64ToAuxInt(16)
+ v2.AddArg3(dst, src, mem)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Move [64] dst src mem)
+ // cond: config.useSSE
+ // result: (Move [32] (OffPtr <dst.Type> dst [32]) (OffPtr <src.Type> src [32]) (Move [32] dst src mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 64 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(config.useSSE) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
+ v0.AuxInt = int64ToAuxInt(32)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
+ v1.AuxInt = int64ToAuxInt(32)
+ v1.AddArg(src)
+ v2 := b.NewValue0(v.Pos, OpMove, types.TypeMem)
+ v2.AuxInt = int64ToAuxInt(32)
+ v2.AddArg3(dst, src, mem)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Move [3] dst src mem)
+ // result: (MOVBstore [2] dst (MOVBload [2] src mem) (MOVWstore dst (MOVWload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVBload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVWload, typ.UInt16)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [5] dst src mem)
+ // result: (MOVBstore [4] dst (MOVBload [4] src mem) (MOVLstore dst (MOVLload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVBload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVLstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVLload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [6] dst src mem)
+ // result: (MOVWstore [4] dst (MOVWload [4] src mem) (MOVLstore dst (MOVLload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVLstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVLload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [7] dst src mem)
+ // result: (MOVLstore [3] dst (MOVLload [3] src mem) (MOVLstore dst (MOVLload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(3)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVLstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVLload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [9] dst src mem)
+ // result: (MOVBstore [8] dst (MOVBload [8] src mem) (MOVQstore dst (MOVQload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 9 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVBstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVBload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVQstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [10] dst src mem)
+ // result: (MOVWstore [8] dst (MOVWload [8] src mem) (MOVQstore dst (MOVQload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 10 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVWstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVQstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [12] dst src mem)
+ // result: (MOVLstore [8] dst (MOVLload [8] src mem) (MOVQstore dst (MOVQload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpAMD64MOVLstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVQstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s == 11 || s >= 13 && s <= 15
+ // result: (MOVQstore [int32(s-8)] dst (MOVQload [int32(s-8)] src mem) (MOVQstore dst (MOVQload src mem) mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s == 11 || s >= 13 && s <= 15) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AuxInt = int32ToAuxInt(int32(s - 8))
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(int32(s - 8))
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVQstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 16 && s%16 != 0 && s%16 <= 8
+ // result: (Move [s-s%16] (OffPtr <dst.Type> dst [s%16]) (OffPtr <src.Type> src [s%16]) (MOVQstore dst (MOVQload src mem) mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 16 && s%16 != 0 && s%16 <= 8) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(s - s%16)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
+ v0.AuxInt = int64ToAuxInt(s % 16)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
+ v1.AuxInt = int64ToAuxInt(s % 16)
+ v1.AddArg(src)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVQstore, types.TypeMem)
+ v3 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v3.AddArg2(src, mem)
+ v2.AddArg3(dst, v3, mem)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 16 && s%16 != 0 && s%16 > 8 && config.useSSE
+ // result: (Move [s-s%16] (OffPtr <dst.Type> dst [s%16]) (OffPtr <src.Type> src [s%16]) (MOVOstore dst (MOVOload src mem) mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 16 && s%16 != 0 && s%16 > 8 && config.useSSE) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(s - s%16)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
+ v0.AuxInt = int64ToAuxInt(s % 16)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
+ v1.AuxInt = int64ToAuxInt(s % 16)
+ v1.AddArg(src)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVOstore, types.TypeMem)
+ v3 := b.NewValue0(v.Pos, OpAMD64MOVOload, types.TypeInt128)
+ v3.AddArg2(src, mem)
+ v2.AddArg3(dst, v3, mem)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 16 && s%16 != 0 && s%16 > 8 && !config.useSSE
+ // result: (Move [s-s%16] (OffPtr <dst.Type> dst [s%16]) (OffPtr <src.Type> src [s%16]) (MOVQstore [8] dst (MOVQload [8] src mem) (MOVQstore dst (MOVQload src mem) mem)))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 16 && s%16 != 0 && s%16 > 8 && !config.useSSE) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(s - s%16)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
+ v0.AuxInt = int64ToAuxInt(s % 16)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
+ v1.AuxInt = int64ToAuxInt(s % 16)
+ v1.AddArg(src)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVQstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(8)
+ v3 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v3.AuxInt = int32ToAuxInt(8)
+ v3.AddArg2(src, mem)
+ v4 := b.NewValue0(v.Pos, OpAMD64MOVQstore, types.TypeMem)
+ v5 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v5.AddArg2(src, mem)
+ v4.AddArg3(dst, v5, mem)
+ v2.AddArg3(dst, v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 64 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
+ // result: (DUFFCOPY [s] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 64 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpAMD64DUFFCOPY)
+ v.AuxInt = int64ToAuxInt(s)
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: (s > 16*64 || config.noDuffDevice) && s%8 == 0 && logLargeCopy(v, s)
+ // result: (REPMOVSQ dst src (MOVQconst [s/8]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !((s > 16*64 || config.noDuffDevice) && s%8 == 0 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpAMD64REPMOVSQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(s / 8)
+ v.AddArg4(dst, src, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpNeg32F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neg32F x)
+ // result: (PXOR x (MOVSSconst <typ.Float32> [float32(math.Copysign(0, -1))]))
+ for {
+ x := v_0
+ v.reset(OpAMD64PXOR)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVSSconst, typ.Float32)
+ v0.AuxInt = float32ToAuxInt(float32(math.Copysign(0, -1)))
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpNeg64F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neg64F x)
+ // result: (PXOR x (MOVSDconst <typ.Float64> [math.Copysign(0, -1)]))
+ for {
+ x := v_0
+ v.reset(OpAMD64PXOR)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVSDconst, typ.Float64)
+ v0.AuxInt = float64ToAuxInt(math.Copysign(0, -1))
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq16 x y)
+ // result: (SETNE (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32 x y)
+ // result: (SETNE (CMPL x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpNeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32F x y)
+ // result: (SETNEF (UCOMISS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETNEF)
+ v0 := b.NewValue0(v.Pos, OpAMD64UCOMISS, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpNeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64 x y)
+ // result: (SETNE (CMPQ x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpNeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64F x y)
+ // result: (SETNEF (UCOMISD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETNEF)
+ v0 := b.NewValue0(v.Pos, OpAMD64UCOMISD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq8 x y)
+ // result: (SETNE (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpNeqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (NeqB x y)
+ // result: (SETNE (CMPB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPB, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpNeqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (NeqPtr x y)
+ // result: (SETNE (CMPQ x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64SETNE)
+ v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpNot(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Not x)
+ // result: (XORLconst [1] x)
+ for {
+ x := v_0
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueAMD64_OpOffPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (OffPtr [off] ptr)
+ // cond: is32Bit(off)
+ // result: (ADDQconst [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ if !(is32Bit(off)) {
+ break
+ }
+ v.reset(OpAMD64ADDQconst)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (OffPtr [off] ptr)
+ // result: (ADDQ (MOVQconst [off]) ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ v.reset(OpAMD64ADDQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(off)
+ v.AddArg2(v0, ptr)
+ return true
+ }
+}
+func rewriteValueAMD64_OpPanicBounds(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicBoundsA [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(OpAMD64LoweredPanicBoundsA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicBoundsB [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(OpAMD64LoweredPanicBoundsB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicBoundsC [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(OpAMD64LoweredPanicBoundsC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpPopCount16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount16 x)
+ // result: (POPCNTL (MOVWQZX <typ.UInt32> x))
+ for {
+ x := v_0
+ v.reset(OpAMD64POPCNTL)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWQZX, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpPopCount8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount8 x)
+ // result: (POPCNTL (MOVBQZX <typ.UInt32> x))
+ for {
+ x := v_0
+ v.reset(OpAMD64POPCNTL)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVBQZX, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpRoundToEven(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (RoundToEven x)
+ // result: (ROUNDSD [0] x)
+ for {
+ x := v_0
+ v.reset(OpAMD64ROUNDSD)
+ v.AuxInt = int8ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueAMD64_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16Ux16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPWconst y [16])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(16)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh16Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16Ux32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPLconst y [16])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(16)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh16Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16Ux64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPQconst y [16])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(16)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh16Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16Ux8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPBconst y [16])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(16)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh16Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARW <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [16])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARW)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v3.AuxInt = int16ToAuxInt(16)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARW <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [16])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARW)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(16)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16x64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARW <t> x (ORQ <y.Type> y (NOTQ <y.Type> (SBBQcarrymask <y.Type> (CMPQconst y [16])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARW)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORQ, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTQ, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(16)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARW <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [16])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARW)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v3.AuxInt = int8ToAuxInt(16)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh32Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh32Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPQconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh32Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh32Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARL <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [32])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v3.AuxInt = int16ToAuxInt(32)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARL <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [32])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARL <t> x (ORQ <y.Type> y (NOTQ <y.Type> (SBBQcarrymask <y.Type> (CMPQconst y [32])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORQ, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTQ, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARL <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [32])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v3.AuxInt = int8ToAuxInt(32)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARL x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh64Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64Ux16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDQ (SHRQ <t> x y) (SBBQcarrymask <t> (CMPWconst y [64])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRQ, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh64Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh64Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64Ux32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDQ (SHRQ <t> x y) (SBBQcarrymask <t> (CMPLconst y [64])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRQ, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh64Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh64Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64Ux64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDQ (SHRQ <t> x y) (SBBQcarrymask <t> (CMPQconst y [64])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRQ, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh64Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh64Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64Ux8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDQ (SHRQ <t> x y) (SBBQcarrymask <t> (CMPBconst y [64])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRQ, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh64Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARQ <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [64])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v3.AuxInt = int16ToAuxInt(64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARQ <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [64])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARQ <t> x (ORQ <y.Type> y (NOTQ <y.Type> (SBBQcarrymask <y.Type> (CMPQconst y [64])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORQ, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTQ, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARQ <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [64])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v3.AuxInt = int8ToAuxInt(64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARQ x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARQ)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8Ux16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPWconst y [8])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRB, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v2.AuxInt = int16ToAuxInt(8)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh8Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8Ux32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPLconst y [8])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRB, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(8)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh8Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8Ux64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPQconst y [8])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRB, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(8)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh8Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8Ux8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPBconst y [8])))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64ANDL)
+ v0 := b.NewValue0(v.Pos, OpAMD64SHRB, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, t)
+ v2 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v2.AuxInt = int8ToAuxInt(8)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Rsh8Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SHRB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SHRB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x16 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARB <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [8])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARB)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPWconst, types.TypeFlags)
+ v3.AuxInt = int16ToAuxInt(8)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x32 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARB <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [8])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARB)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(8)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x64 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARB <t> x (ORQ <y.Type> y (NOTQ <y.Type> (SBBQcarrymask <y.Type> (CMPQconst y [8])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARB)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORQ, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTQ, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(8)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x8 <t> x y)
+ // cond: !shiftIsBounded(v)
+ // result: (SARB <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [8])))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ if !(!shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARB)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpAMD64ORL, y.Type)
+ v1 := b.NewValue0(v.Pos, OpAMD64NOTL, y.Type)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBLcarrymask, y.Type)
+ v3 := b.NewValue0(v.Pos, OpAMD64CMPBconst, types.TypeFlags)
+ v3.AuxInt = int8ToAuxInt(8)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SARB x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpAMD64SARB)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpSelect0(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select0 (Mul64uover x y))
+ // result: (Select0 <typ.UInt64> (MULQU x y))
+ for {
+ if v_0.Op != OpMul64uover {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpSelect0)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpAMD64MULQU, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select0 (Mul32uover x y))
+ // result: (Select0 <typ.UInt32> (MULLU x y))
+ for {
+ if v_0.Op != OpMul32uover {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpSelect0)
+ v.Type = typ.UInt32
+ v0 := b.NewValue0(v.Pos, OpAMD64MULLU, types.NewTuple(typ.UInt32, types.TypeFlags))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select0 (Add64carry x y c))
+ // result: (Select0 <typ.UInt64> (ADCQ x y (Select1 <types.TypeFlags> (NEGLflags c))))
+ for {
+ if v_0.Op != OpAdd64carry {
+ break
+ }
+ c := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpSelect0)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpAMD64ADCQ, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v2 := b.NewValue0(v.Pos, OpAMD64NEGLflags, types.NewTuple(typ.UInt32, types.TypeFlags))
+ v2.AddArg(c)
+ v1.AddArg(v2)
+ v0.AddArg3(x, y, v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select0 (Sub64borrow x y c))
+ // result: (Select0 <typ.UInt64> (SBBQ x y (Select1 <types.TypeFlags> (NEGLflags c))))
+ for {
+ if v_0.Op != OpSub64borrow {
+ break
+ }
+ c := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpSelect0)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpAMD64SBBQ, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v2 := b.NewValue0(v.Pos, OpAMD64NEGLflags, types.NewTuple(typ.UInt32, types.TypeFlags))
+ v2.AddArg(c)
+ v1.AddArg(v2)
+ v0.AddArg3(x, y, v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select0 <t> (AddTupleFirst32 val tuple))
+ // result: (ADDL val (Select0 <t> tuple))
+ for {
+ t := v.Type
+ if v_0.Op != OpAMD64AddTupleFirst32 {
+ break
+ }
+ tuple := v_0.Args[1]
+ val := v_0.Args[0]
+ v.reset(OpAMD64ADDL)
+ v0 := b.NewValue0(v.Pos, OpSelect0, t)
+ v0.AddArg(tuple)
+ v.AddArg2(val, v0)
+ return true
+ }
+ // match: (Select0 <t> (AddTupleFirst64 val tuple))
+ // result: (ADDQ val (Select0 <t> tuple))
+ for {
+ t := v.Type
+ if v_0.Op != OpAMD64AddTupleFirst64 {
+ break
+ }
+ tuple := v_0.Args[1]
+ val := v_0.Args[0]
+ v.reset(OpAMD64ADDQ)
+ v0 := b.NewValue0(v.Pos, OpSelect0, t)
+ v0.AddArg(tuple)
+ v.AddArg2(val, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpSelect1(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select1 (Mul64uover x y))
+ // result: (SETO (Select1 <types.TypeFlags> (MULQU x y)))
+ for {
+ if v_0.Op != OpMul64uover {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETO)
+ v0 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpAMD64MULQU, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select1 (Mul32uover x y))
+ // result: (SETO (Select1 <types.TypeFlags> (MULLU x y)))
+ for {
+ if v_0.Op != OpMul32uover {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpAMD64SETO)
+ v0 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpAMD64MULLU, types.NewTuple(typ.UInt32, types.TypeFlags))
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select1 (Add64carry x y c))
+ // result: (NEGQ <typ.UInt64> (SBBQcarrymask <typ.UInt64> (Select1 <types.TypeFlags> (ADCQ x y (Select1 <types.TypeFlags> (NEGLflags c))))))
+ for {
+ if v_0.Op != OpAdd64carry {
+ break
+ }
+ c := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpAMD64NEGQ)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v2 := b.NewValue0(v.Pos, OpAMD64ADCQ, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v3 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpAMD64NEGLflags, types.NewTuple(typ.UInt32, types.TypeFlags))
+ v4.AddArg(c)
+ v3.AddArg(v4)
+ v2.AddArg3(x, y, v3)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select1 (Sub64borrow x y c))
+ // result: (NEGQ <typ.UInt64> (SBBQcarrymask <typ.UInt64> (Select1 <types.TypeFlags> (SBBQ x y (Select1 <types.TypeFlags> (NEGLflags c))))))
+ for {
+ if v_0.Op != OpSub64borrow {
+ break
+ }
+ c := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpAMD64NEGQ)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpAMD64SBBQcarrymask, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v2 := b.NewValue0(v.Pos, OpAMD64SBBQ, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v3 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpAMD64NEGLflags, types.NewTuple(typ.UInt32, types.TypeFlags))
+ v4.AddArg(c)
+ v3.AddArg(v4)
+ v2.AddArg3(x, y, v3)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select1 (NEGLflags (MOVQconst [0])))
+ // result: (FlagEQ)
+ for {
+ if v_0.Op != OpAMD64NEGLflags {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_0_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpAMD64FlagEQ)
+ return true
+ }
+ // match: (Select1 (NEGLflags (NEGQ (SBBQcarrymask x))))
+ // result: x
+ for {
+ if v_0.Op != OpAMD64NEGLflags {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64NEGQ {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64SBBQcarrymask {
+ break
+ }
+ x := v_0_0_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Select1 (AddTupleFirst32 _ tuple))
+ // result: (Select1 tuple)
+ for {
+ if v_0.Op != OpAMD64AddTupleFirst32 {
+ break
+ }
+ tuple := v_0.Args[1]
+ v.reset(OpSelect1)
+ v.AddArg(tuple)
+ return true
+ }
+ // match: (Select1 (AddTupleFirst64 _ tuple))
+ // result: (Select1 tuple)
+ for {
+ if v_0.Op != OpAMD64AddTupleFirst64 {
+ break
+ }
+ tuple := v_0.Args[1]
+ v.reset(OpSelect1)
+ v.AddArg(tuple)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Slicemask <t> x)
+ // result: (SARQconst (NEGQ <t> x) [63])
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpAMD64SARQconst)
+ v.AuxInt = int8ToAuxInt(63)
+ v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueAMD64_OpSpectreIndex(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SpectreIndex <t> x y)
+ // result: (CMOVQCC x (MOVQconst [0]) (CMPQ x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64CMOVQCC)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v1.AddArg2(x, y)
+ v.AddArg3(x, v0, v1)
+ return true
+ }
+}
+func rewriteValueAMD64_OpSpectreSliceIndex(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SpectreSliceIndex <t> x y)
+ // result: (CMOVQHI x (MOVQconst [0]) (CMPQ x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAMD64CMOVQHI)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
+ v1.AddArg2(x, y)
+ v.AddArg3(x, v0, v1)
+ return true
+ }
+}
+func rewriteValueAMD64_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && is64BitFloat(val.Type)
+ // result: (MOVSDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpAMD64MOVSDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && is32BitFloat(val.Type)
+ // result: (MOVSSstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpAMD64MOVSSstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8
+ // result: (MOVQstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8) {
+ break
+ }
+ v.reset(OpAMD64MOVQstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4
+ // result: (MOVLstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4) {
+ break
+ }
+ v.reset(OpAMD64MOVLstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 2
+ // result: (MOVWstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 2) {
+ break
+ }
+ v.reset(OpAMD64MOVWstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 1
+ // result: (MOVBstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 1) {
+ break
+ }
+ v.reset(OpAMD64MOVBstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpTrunc(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc x)
+ // result: (ROUNDSD [3] x)
+ for {
+ x := v_0
+ v.reset(OpAMD64ROUNDSD)
+ v.AuxInt = int8ToAuxInt(3)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueAMD64_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Zero [0] _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_1
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero [1] destptr mem)
+ // result: (MOVBstoreconst [makeValAndOff32(0,0)] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [2] destptr mem)
+ // result: (MOVWstoreconst [makeValAndOff32(0,0)] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [4] destptr mem)
+ // result: (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [8] destptr mem)
+ // result: (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVQstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [3] destptr mem)
+ // result: (MOVBstoreconst [makeValAndOff32(0,2)] destptr (MOVWstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 2))
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [5] destptr mem)
+ // result: (MOVBstoreconst [makeValAndOff32(0,4)] destptr (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 4))
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [6] destptr mem)
+ // result: (MOVWstoreconst [makeValAndOff32(0,4)] destptr (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 4))
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [7] destptr mem)
+ // result: (MOVLstoreconst [makeValAndOff32(0,3)] destptr (MOVLstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpAMD64MOVLstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 3))
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s%8 != 0 && s > 8 && !config.useSSE
+ // result: (Zero [s-s%8] (OffPtr <destptr.Type> destptr [s%8]) (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s%8 != 0 && s > 8 && !config.useSSE) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(s - s%8)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type)
+ v0.AuxInt = int64ToAuxInt(s % 8)
+ v0.AddArg(destptr)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVQstoreconst, types.TypeMem)
+ v1.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v1.AddArg2(destptr, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Zero [16] destptr mem)
+ // cond: !config.useSSE
+ // result: (MOVQstoreconst [makeValAndOff32(0,8)] destptr (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ if !(!config.useSSE) {
+ break
+ }
+ v.reset(OpAMD64MOVQstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 8))
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [24] destptr mem)
+ // cond: !config.useSSE
+ // result: (MOVQstoreconst [makeValAndOff32(0,16)] destptr (MOVQstoreconst [makeValAndOff32(0,8)] destptr (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ if !(!config.useSSE) {
+ break
+ }
+ v.reset(OpAMD64MOVQstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 16))
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 8))
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVQstoreconst, types.TypeMem)
+ v1.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v1.AddArg2(destptr, mem)
+ v0.AddArg2(destptr, v1)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [32] destptr mem)
+ // cond: !config.useSSE
+ // result: (MOVQstoreconst [makeValAndOff32(0,24)] destptr (MOVQstoreconst [makeValAndOff32(0,16)] destptr (MOVQstoreconst [makeValAndOff32(0,8)] destptr (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 32 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ if !(!config.useSSE) {
+ break
+ }
+ v.reset(OpAMD64MOVQstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 24))
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 16))
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVQstoreconst, types.TypeMem)
+ v1.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 8))
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVQstoreconst, types.TypeMem)
+ v2.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v2.AddArg2(destptr, mem)
+ v1.AddArg2(destptr, v2)
+ v0.AddArg2(destptr, v1)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s > 8 && s < 16 && config.useSSE
+ // result: (MOVQstoreconst [makeValAndOff32(0,int32(s-8))] destptr (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s > 8 && s < 16 && config.useSSE) {
+ break
+ }
+ v.reset(OpAMD64MOVQstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, int32(s-8)))
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s%16 != 0 && s > 16 && s%16 > 8 && config.useSSE
+ // result: (Zero [s-s%16] (OffPtr <destptr.Type> destptr [s%16]) (MOVOstore destptr (MOVOconst [0]) mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s%16 != 0 && s > 16 && s%16 > 8 && config.useSSE) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(s - s%16)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type)
+ v0.AuxInt = int64ToAuxInt(s % 16)
+ v0.AddArg(destptr)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVOstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVOconst, types.TypeInt128)
+ v2.AuxInt = int128ToAuxInt(0)
+ v1.AddArg3(destptr, v2, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s%16 != 0 && s > 16 && s%16 <= 8 && config.useSSE
+ // result: (Zero [s-s%16] (OffPtr <destptr.Type> destptr [s%16]) (MOVQstoreconst [makeValAndOff32(0,0)] destptr mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s%16 != 0 && s > 16 && s%16 <= 8 && config.useSSE) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(s - s%16)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type)
+ v0.AuxInt = int64ToAuxInt(s % 16)
+ v0.AddArg(destptr)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVQstoreconst, types.TypeMem)
+ v1.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 0))
+ v1.AddArg2(destptr, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Zero [16] destptr mem)
+ // cond: config.useSSE
+ // result: (MOVOstore destptr (MOVOconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ if !(config.useSSE) {
+ break
+ }
+ v.reset(OpAMD64MOVOstore)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVOconst, types.TypeInt128)
+ v0.AuxInt = int128ToAuxInt(0)
+ v.AddArg3(destptr, v0, mem)
+ return true
+ }
+ // match: (Zero [32] destptr mem)
+ // cond: config.useSSE
+ // result: (MOVOstore (OffPtr <destptr.Type> destptr [16]) (MOVOconst [0]) (MOVOstore destptr (MOVOconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 32 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ if !(config.useSSE) {
+ break
+ }
+ v.reset(OpAMD64MOVOstore)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type)
+ v0.AuxInt = int64ToAuxInt(16)
+ v0.AddArg(destptr)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVOconst, types.TypeInt128)
+ v1.AuxInt = int128ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVOstore, types.TypeMem)
+ v2.AddArg3(destptr, v1, mem)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Zero [48] destptr mem)
+ // cond: config.useSSE
+ // result: (MOVOstore (OffPtr <destptr.Type> destptr [32]) (MOVOconst [0]) (MOVOstore (OffPtr <destptr.Type> destptr [16]) (MOVOconst [0]) (MOVOstore destptr (MOVOconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 48 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ if !(config.useSSE) {
+ break
+ }
+ v.reset(OpAMD64MOVOstore)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type)
+ v0.AuxInt = int64ToAuxInt(32)
+ v0.AddArg(destptr)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVOconst, types.TypeInt128)
+ v1.AuxInt = int128ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVOstore, types.TypeMem)
+ v3 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type)
+ v3.AuxInt = int64ToAuxInt(16)
+ v3.AddArg(destptr)
+ v4 := b.NewValue0(v.Pos, OpAMD64MOVOstore, types.TypeMem)
+ v4.AddArg3(destptr, v1, mem)
+ v2.AddArg3(v3, v1, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Zero [64] destptr mem)
+ // cond: config.useSSE
+ // result: (MOVOstore (OffPtr <destptr.Type> destptr [48]) (MOVOconst [0]) (MOVOstore (OffPtr <destptr.Type> destptr [32]) (MOVOconst [0]) (MOVOstore (OffPtr <destptr.Type> destptr [16]) (MOVOconst [0]) (MOVOstore destptr (MOVOconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 64 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ if !(config.useSSE) {
+ break
+ }
+ v.reset(OpAMD64MOVOstore)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type)
+ v0.AuxInt = int64ToAuxInt(48)
+ v0.AddArg(destptr)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVOconst, types.TypeInt128)
+ v1.AuxInt = int128ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpAMD64MOVOstore, types.TypeMem)
+ v3 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type)
+ v3.AuxInt = int64ToAuxInt(32)
+ v3.AddArg(destptr)
+ v4 := b.NewValue0(v.Pos, OpAMD64MOVOstore, types.TypeMem)
+ v5 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type)
+ v5.AuxInt = int64ToAuxInt(16)
+ v5.AddArg(destptr)
+ v6 := b.NewValue0(v.Pos, OpAMD64MOVOstore, types.TypeMem)
+ v6.AddArg3(destptr, v1, mem)
+ v4.AddArg3(v5, v1, v6)
+ v2.AddArg3(v3, v1, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s > 64 && s <= 1024 && s%16 == 0 && !config.noDuffDevice
+ // result: (DUFFZERO [s] destptr (MOVOconst [0]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s > 64 && s <= 1024 && s%16 == 0 && !config.noDuffDevice) {
+ break
+ }
+ v.reset(OpAMD64DUFFZERO)
+ v.AuxInt = int64ToAuxInt(s)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVOconst, types.TypeInt128)
+ v0.AuxInt = int128ToAuxInt(0)
+ v.AddArg3(destptr, v0, mem)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: (s > 1024 || (config.noDuffDevice && s > 64 || !config.useSSE && s > 32)) && s%8 == 0
+ // result: (REPSTOSQ destptr (MOVQconst [s/8]) (MOVQconst [0]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !((s > 1024 || (config.noDuffDevice && s > 64 || !config.useSSE && s > 32)) && s%8 == 0) {
+ break
+ }
+ v.reset(OpAMD64REPSTOSQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(s / 8)
+ v1 := b.NewValue0(v.Pos, OpAMD64MOVQconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v.AddArg4(destptr, v0, v1, mem)
+ return true
+ }
+ return false
+}
+func rewriteBlockAMD64(b *Block) bool {
+ switch b.Kind {
+ case BlockAMD64EQ:
+ // match: (EQ (TESTL (SHLL (MOVLconst [1]) x) y))
+ // result: (UGE (BTL x y))
+ for b.Controls[0].Op == OpAMD64TESTL {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64SHLL {
+ continue
+ }
+ x := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_0_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_0_1
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (TESTQ (SHLQ (MOVQconst [1]) x) y))
+ // result: (UGE (BTQ x y))
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ x := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_0_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_0_1
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (TESTLconst [c] x))
+ // cond: isUint32PowerOfTwo(int64(c))
+ // result: (UGE (BTLconst [int8(log32(c))] x))
+ for b.Controls[0].Op == OpAMD64TESTLconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isUint32PowerOfTwo(int64(c))) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ // match: (EQ (TESTQconst [c] x))
+ // cond: isUint64PowerOfTwo(int64(c))
+ // result: (UGE (BTQconst [int8(log32(c))] x))
+ for b.Controls[0].Op == OpAMD64TESTQconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isUint64PowerOfTwo(int64(c))) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ // match: (EQ (TESTQ (MOVQconst [c]) x))
+ // cond: isUint64PowerOfTwo(c)
+ // result: (UGE (BTQconst [int8(log64(c))] x))
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_1
+ if !(isUint64PowerOfTwo(c)) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log64(c)))
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2))
+ // cond: z1==z2
+ // result: (UGE (BTQconst [63] x))
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHLQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (TESTL z1:(SHLLconst [31] (SHRQconst [31] x)) z2))
+ // cond: z1==z2
+ // result: (UGE (BTQconst [31] x))
+ for b.Controls[0].Op == OpAMD64TESTL {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHLLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRQconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2))
+ // cond: z1==z2
+ // result: (UGE (BTQconst [0] x))
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2))
+ // cond: z1==z2
+ // result: (UGE (BTLconst [0] x))
+ for b.Controls[0].Op == OpAMD64TESTL {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLLconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (TESTQ z1:(SHRQconst [63] x) z2))
+ // cond: z1==z2
+ // result: (UGE (BTQconst [63] x))
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (TESTL z1:(SHRLconst [31] x) z2))
+ // cond: z1==z2
+ // result: (UGE (BTLconst [31] x))
+ for b.Controls[0].Op == OpAMD64TESTL {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64UGE, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (InvertFlags cmp) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpAMD64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64EQ, cmp)
+ return true
+ }
+ // match: (EQ (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (EQ (FlagLT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagLT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (EQ (FlagLT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagLT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (EQ (FlagGT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagGT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (EQ (FlagGT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagGT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockAMD64GE:
+ // match: (GE (InvertFlags cmp) yes no)
+ // result: (LE cmp yes no)
+ for b.Controls[0].Op == OpAMD64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64LE, cmp)
+ return true
+ }
+ // match: (GE (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GE (FlagLT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagLT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GE (FlagLT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagLT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GE (FlagGT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagGT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GE (FlagGT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagGT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ case BlockAMD64GT:
+ // match: (GT (InvertFlags cmp) yes no)
+ // result: (LT cmp yes no)
+ for b.Controls[0].Op == OpAMD64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64LT, cmp)
+ return true
+ }
+ // match: (GT (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GT (FlagLT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagLT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GT (FlagLT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagLT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GT (FlagGT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagGT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GT (FlagGT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagGT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ case BlockIf:
+ // match: (If (SETL cmp) yes no)
+ // result: (LT cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETL {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64LT, cmp)
+ return true
+ }
+ // match: (If (SETLE cmp) yes no)
+ // result: (LE cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETLE {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64LE, cmp)
+ return true
+ }
+ // match: (If (SETG cmp) yes no)
+ // result: (GT cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETG {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64GT, cmp)
+ return true
+ }
+ // match: (If (SETGE cmp) yes no)
+ // result: (GE cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETGE {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64GE, cmp)
+ return true
+ }
+ // match: (If (SETEQ cmp) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETEQ {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64EQ, cmp)
+ return true
+ }
+ // match: (If (SETNE cmp) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETNE {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64NE, cmp)
+ return true
+ }
+ // match: (If (SETB cmp) yes no)
+ // result: (ULT cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETB {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64ULT, cmp)
+ return true
+ }
+ // match: (If (SETBE cmp) yes no)
+ // result: (ULE cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETBE {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64ULE, cmp)
+ return true
+ }
+ // match: (If (SETA cmp) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETA {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64UGT, cmp)
+ return true
+ }
+ // match: (If (SETAE cmp) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETAE {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64UGE, cmp)
+ return true
+ }
+ // match: (If (SETO cmp) yes no)
+ // result: (OS cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETO {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64OS, cmp)
+ return true
+ }
+ // match: (If (SETGF cmp) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETGF {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64UGT, cmp)
+ return true
+ }
+ // match: (If (SETGEF cmp) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETGEF {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64UGE, cmp)
+ return true
+ }
+ // match: (If (SETEQF cmp) yes no)
+ // result: (EQF cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETEQF {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64EQF, cmp)
+ return true
+ }
+ // match: (If (SETNEF cmp) yes no)
+ // result: (NEF cmp yes no)
+ for b.Controls[0].Op == OpAMD64SETNEF {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64NEF, cmp)
+ return true
+ }
+ // match: (If cond yes no)
+ // result: (NE (TESTB cond cond) yes no)
+ for {
+ cond := b.Controls[0]
+ v0 := b.NewValue0(cond.Pos, OpAMD64TESTB, types.TypeFlags)
+ v0.AddArg2(cond, cond)
+ b.resetWithControl(BlockAMD64NE, v0)
+ return true
+ }
+ case BlockAMD64LE:
+ // match: (LE (InvertFlags cmp) yes no)
+ // result: (GE cmp yes no)
+ for b.Controls[0].Op == OpAMD64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64GE, cmp)
+ return true
+ }
+ // match: (LE (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LE (FlagLT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagLT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LE (FlagLT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagLT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LE (FlagGT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagGT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LE (FlagGT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagGT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockAMD64LT:
+ // match: (LT (InvertFlags cmp) yes no)
+ // result: (GT cmp yes no)
+ for b.Controls[0].Op == OpAMD64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64GT, cmp)
+ return true
+ }
+ // match: (LT (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LT (FlagLT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagLT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LT (FlagLT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagLT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LT (FlagGT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagGT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LT (FlagGT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagGT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockAMD64NE:
+ // match: (NE (TESTB (SETL cmp) (SETL cmp)) yes no)
+ // result: (LT cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETL {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETL || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64LT, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETLE cmp) (SETLE cmp)) yes no)
+ // result: (LE cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETLE {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETLE || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64LE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETG cmp) (SETG cmp)) yes no)
+ // result: (GT cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETG {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETG || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64GT, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETGE cmp) (SETGE cmp)) yes no)
+ // result: (GE cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETGE {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETGE || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64GE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETEQ cmp) (SETEQ cmp)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETEQ {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETEQ || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64EQ, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETNE cmp) (SETNE cmp)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETNE {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETNE || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64NE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETB cmp) (SETB cmp)) yes no)
+ // result: (ULT cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETB {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETB || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64ULT, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETBE cmp) (SETBE cmp)) yes no)
+ // result: (ULE cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETBE {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETBE || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64ULE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETA cmp) (SETA cmp)) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETA {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETA || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64UGT, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETAE cmp) (SETAE cmp)) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETAE {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETAE || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64UGE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETO cmp) (SETO cmp)) yes no)
+ // result: (OS cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETO {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETO || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64OS, cmp)
+ return true
+ }
+ // match: (NE (TESTL (SHLL (MOVLconst [1]) x) y))
+ // result: (ULT (BTL x y))
+ for b.Controls[0].Op == OpAMD64TESTL {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64SHLL {
+ continue
+ }
+ x := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_0_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_0_1
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTL, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (TESTQ (SHLQ (MOVQconst [1]) x) y))
+ // result: (ULT (BTQ x y))
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64SHLQ {
+ continue
+ }
+ x := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_0_0_0.AuxInt) != 1 {
+ continue
+ }
+ y := v_0_1
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (TESTLconst [c] x))
+ // cond: isUint32PowerOfTwo(int64(c))
+ // result: (ULT (BTLconst [int8(log32(c))] x))
+ for b.Controls[0].Op == OpAMD64TESTLconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isUint32PowerOfTwo(int64(c))) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ // match: (NE (TESTQconst [c] x))
+ // cond: isUint64PowerOfTwo(int64(c))
+ // result: (ULT (BTQconst [int8(log32(c))] x))
+ for b.Controls[0].Op == OpAMD64TESTQconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isUint64PowerOfTwo(int64(c))) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log32(c)))
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ // match: (NE (TESTQ (MOVQconst [c]) x))
+ // cond: isUint64PowerOfTwo(c)
+ // result: (ULT (BTQconst [int8(log64(c))] x))
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpAMD64MOVQconst {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_1
+ if !(isUint64PowerOfTwo(c)) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(int8(log64(c)))
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2))
+ // cond: z1==z2
+ // result: (ULT (BTQconst [63] x))
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHLQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (TESTL z1:(SHLLconst [31] (SHRQconst [31] x)) z2))
+ // cond: z1==z2
+ // result: (ULT (BTQconst [31] x))
+ for b.Controls[0].Op == OpAMD64TESTL {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHLLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHRQconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2))
+ // cond: z1==z2
+ // result: (ULT (BTQconst [0] x))
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLQconst || auxIntToInt8(z1_0.AuxInt) != 63 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2))
+ // cond: z1==z2
+ // result: (ULT (BTLconst [0] x))
+ for b.Controls[0].Op == OpAMD64TESTL {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ z1_0 := z1.Args[0]
+ if z1_0.Op != OpAMD64SHLLconst || auxIntToInt8(z1_0.AuxInt) != 31 {
+ continue
+ }
+ x := z1_0.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(0)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (TESTQ z1:(SHRQconst [63] x) z2))
+ // cond: z1==z2
+ // result: (ULT (BTQconst [63] x))
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRQconst || auxIntToInt8(z1.AuxInt) != 63 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(63)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (TESTL z1:(SHRLconst [31] x) z2))
+ // cond: z1==z2
+ // result: (ULT (BTLconst [31] x))
+ for b.Controls[0].Op == OpAMD64TESTL {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z1 := v_0_0
+ if z1.Op != OpAMD64SHRLconst || auxIntToInt8(z1.AuxInt) != 31 {
+ continue
+ }
+ x := z1.Args[0]
+ z2 := v_0_1
+ if !(z1 == z2) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpAMD64BTLconst, types.TypeFlags)
+ v0.AuxInt = int8ToAuxInt(31)
+ v0.AddArg(x)
+ b.resetWithControl(BlockAMD64ULT, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (TESTB (SETGF cmp) (SETGF cmp)) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETGF {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETGF || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64UGT, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETGEF cmp) (SETGEF cmp)) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETGEF {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETGEF || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64UGE, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETEQF cmp) (SETEQF cmp)) yes no)
+ // result: (EQF cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETEQF {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETEQF || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64EQF, cmp)
+ return true
+ }
+ // match: (NE (TESTB (SETNEF cmp) (SETNEF cmp)) yes no)
+ // result: (NEF cmp yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAMD64SETNEF {
+ break
+ }
+ cmp := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpAMD64SETNEF || cmp != v_0_1.Args[0] {
+ break
+ }
+ b.resetWithControl(BlockAMD64NEF, cmp)
+ return true
+ }
+ // match: (NE (InvertFlags cmp) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpAMD64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64NE, cmp)
+ return true
+ }
+ // match: (NE (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (NE (FlagLT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagLT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (NE (FlagLT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagLT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (NE (FlagGT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagGT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (NE (FlagGT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagGT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ case BlockAMD64UGE:
+ // match: (UGE (TESTQ x x) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGE (TESTL x x) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64TESTL {
+ v_0 := b.Controls[0]
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGE (TESTW x x) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64TESTW {
+ v_0 := b.Controls[0]
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGE (TESTB x x) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGE (InvertFlags cmp) yes no)
+ // result: (ULE cmp yes no)
+ for b.Controls[0].Op == OpAMD64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64ULE, cmp)
+ return true
+ }
+ // match: (UGE (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGE (FlagLT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagLT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGE (FlagLT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagLT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGE (FlagGT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagGT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGE (FlagGT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagGT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ case BlockAMD64UGT:
+ // match: (UGT (InvertFlags cmp) yes no)
+ // result: (ULT cmp yes no)
+ for b.Controls[0].Op == OpAMD64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64ULT, cmp)
+ return true
+ }
+ // match: (UGT (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGT (FlagLT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagLT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGT (FlagLT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagLT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGT (FlagGT_ULT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagGT_ULT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGT (FlagGT_UGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagGT_UGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ case BlockAMD64ULE:
+ // match: (ULE (InvertFlags cmp) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == OpAMD64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64UGE, cmp)
+ return true
+ }
+ // match: (ULE (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULE (FlagLT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagLT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULE (FlagLT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagLT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULE (FlagGT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagGT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULE (FlagGT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagGT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockAMD64ULT:
+ // match: (ULT (TESTQ x x) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64TESTQ {
+ v_0 := b.Controls[0]
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULT (TESTL x x) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64TESTL {
+ v_0 := b.Controls[0]
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULT (TESTW x x) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64TESTW {
+ v_0 := b.Controls[0]
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULT (TESTB x x) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64TESTB {
+ v_0 := b.Controls[0]
+ x := v_0.Args[1]
+ if x != v_0.Args[0] {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULT (InvertFlags cmp) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == OpAMD64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockAMD64UGT, cmp)
+ return true
+ }
+ // match: (ULT (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULT (FlagLT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagLT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULT (FlagLT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagLT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULT (FlagGT_ULT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpAMD64FlagGT_ULT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULT (FlagGT_UGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpAMD64FlagGT_UGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64splitload.go b/src/cmd/compile/internal/ssa/rewriteAMD64splitload.go
new file mode 100644
index 0000000..65bfec0
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewriteAMD64splitload.go
@@ -0,0 +1,853 @@
+// Code generated from gen/AMD64splitload.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+func rewriteValueAMD64splitload(v *Value) bool {
+ switch v.Op {
+ case OpAMD64CMPBconstload:
+ return rewriteValueAMD64splitload_OpAMD64CMPBconstload(v)
+ case OpAMD64CMPBconstloadidx1:
+ return rewriteValueAMD64splitload_OpAMD64CMPBconstloadidx1(v)
+ case OpAMD64CMPBload:
+ return rewriteValueAMD64splitload_OpAMD64CMPBload(v)
+ case OpAMD64CMPBloadidx1:
+ return rewriteValueAMD64splitload_OpAMD64CMPBloadidx1(v)
+ case OpAMD64CMPLconstload:
+ return rewriteValueAMD64splitload_OpAMD64CMPLconstload(v)
+ case OpAMD64CMPLconstloadidx1:
+ return rewriteValueAMD64splitload_OpAMD64CMPLconstloadidx1(v)
+ case OpAMD64CMPLconstloadidx4:
+ return rewriteValueAMD64splitload_OpAMD64CMPLconstloadidx4(v)
+ case OpAMD64CMPLload:
+ return rewriteValueAMD64splitload_OpAMD64CMPLload(v)
+ case OpAMD64CMPLloadidx1:
+ return rewriteValueAMD64splitload_OpAMD64CMPLloadidx1(v)
+ case OpAMD64CMPLloadidx4:
+ return rewriteValueAMD64splitload_OpAMD64CMPLloadidx4(v)
+ case OpAMD64CMPQconstload:
+ return rewriteValueAMD64splitload_OpAMD64CMPQconstload(v)
+ case OpAMD64CMPQconstloadidx1:
+ return rewriteValueAMD64splitload_OpAMD64CMPQconstloadidx1(v)
+ case OpAMD64CMPQconstloadidx8:
+ return rewriteValueAMD64splitload_OpAMD64CMPQconstloadidx8(v)
+ case OpAMD64CMPQload:
+ return rewriteValueAMD64splitload_OpAMD64CMPQload(v)
+ case OpAMD64CMPQloadidx1:
+ return rewriteValueAMD64splitload_OpAMD64CMPQloadidx1(v)
+ case OpAMD64CMPQloadidx8:
+ return rewriteValueAMD64splitload_OpAMD64CMPQloadidx8(v)
+ case OpAMD64CMPWconstload:
+ return rewriteValueAMD64splitload_OpAMD64CMPWconstload(v)
+ case OpAMD64CMPWconstloadidx1:
+ return rewriteValueAMD64splitload_OpAMD64CMPWconstloadidx1(v)
+ case OpAMD64CMPWconstloadidx2:
+ return rewriteValueAMD64splitload_OpAMD64CMPWconstloadidx2(v)
+ case OpAMD64CMPWload:
+ return rewriteValueAMD64splitload_OpAMD64CMPWload(v)
+ case OpAMD64CMPWloadidx1:
+ return rewriteValueAMD64splitload_OpAMD64CMPWloadidx1(v)
+ case OpAMD64CMPWloadidx2:
+ return rewriteValueAMD64splitload_OpAMD64CMPWloadidx2(v)
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPBconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPBconstload {sym} [vo] ptr mem)
+ // cond: vo.Val() == 0
+ // result: (TESTB x:(MOVBload {sym} [vo.Off32()] ptr mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTB)
+ x := b.NewValue0(v.Pos, OpAMD64MOVBload, typ.UInt8)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg2(ptr, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPBconstload {sym} [vo] ptr mem)
+ // cond: vo.Val() != 0
+ // result: (CMPBconst (MOVBload {sym} [vo.Off32()] ptr mem) [vo.Val8()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPBconst)
+ v.AuxInt = int8ToAuxInt(vo.Val8())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVBload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPBconstloadidx1(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPBconstloadidx1 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() == 0
+ // result: (TESTB x:(MOVBloadidx1 {sym} [vo.Off32()] ptr idx mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTB)
+ x := b.NewValue0(v.Pos, OpAMD64MOVBloadidx1, typ.UInt8)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg3(ptr, idx, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPBconstloadidx1 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() != 0
+ // result: (CMPBconst (MOVBloadidx1 {sym} [vo.Off32()] ptr idx mem) [vo.Val8()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPBconst)
+ v.AuxInt = int8ToAuxInt(vo.Val8())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVBloadidx1, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPBload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPBload {sym} [off] ptr x mem)
+ // result: (CMPB (MOVBload {sym} [off] ptr mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ x := v_1
+ mem := v_2
+ v.reset(OpAMD64CMPB)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVBload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueAMD64splitload_OpAMD64CMPBloadidx1(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPBloadidx1 {sym} [off] ptr idx x mem)
+ // result: (CMPB (MOVBloadidx1 {sym} [off] ptr idx mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ x := v_2
+ mem := v_3
+ v.reset(OpAMD64CMPB)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVBloadidx1, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueAMD64splitload_OpAMD64CMPLconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPLconstload {sym} [vo] ptr mem)
+ // cond: vo.Val() == 0
+ // result: (TESTL x:(MOVLload {sym} [vo.Off32()] ptr mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTL)
+ x := b.NewValue0(v.Pos, OpAMD64MOVLload, typ.UInt32)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg2(ptr, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPLconstload {sym} [vo] ptr mem)
+ // cond: vo.Val() != 0
+ // result: (CMPLconst (MOVLload {sym} [vo.Off32()] ptr mem) [vo.Val32()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPLconst)
+ v.AuxInt = int32ToAuxInt(vo.Val32())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPLconstloadidx1(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPLconstloadidx1 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() == 0
+ // result: (TESTL x:(MOVLloadidx1 {sym} [vo.Off32()] ptr idx mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTL)
+ x := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, typ.UInt32)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg3(ptr, idx, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPLconstloadidx1 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() != 0
+ // result: (CMPLconst (MOVLloadidx1 {sym} [vo.Off32()] ptr idx mem) [vo.Val32()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPLconst)
+ v.AuxInt = int32ToAuxInt(vo.Val32())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPLconstloadidx4(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPLconstloadidx4 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() == 0
+ // result: (TESTL x:(MOVLloadidx4 {sym} [vo.Off32()] ptr idx mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTL)
+ x := b.NewValue0(v.Pos, OpAMD64MOVLloadidx4, typ.UInt32)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg3(ptr, idx, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPLconstloadidx4 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() != 0
+ // result: (CMPLconst (MOVLloadidx4 {sym} [vo.Off32()] ptr idx mem) [vo.Val32()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPLconst)
+ v.AuxInt = int32ToAuxInt(vo.Val32())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx4, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPLload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPLload {sym} [off] ptr x mem)
+ // result: (CMPL (MOVLload {sym} [off] ptr mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ x := v_1
+ mem := v_2
+ v.reset(OpAMD64CMPL)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueAMD64splitload_OpAMD64CMPLloadidx1(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPLloadidx1 {sym} [off] ptr idx x mem)
+ // result: (CMPL (MOVLloadidx1 {sym} [off] ptr idx mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ x := v_2
+ mem := v_3
+ v.reset(OpAMD64CMPL)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueAMD64splitload_OpAMD64CMPLloadidx4(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPLloadidx4 {sym} [off] ptr idx x mem)
+ // result: (CMPL (MOVLloadidx4 {sym} [off] ptr idx mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ x := v_2
+ mem := v_3
+ v.reset(OpAMD64CMPL)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx4, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueAMD64splitload_OpAMD64CMPQconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPQconstload {sym} [vo] ptr mem)
+ // cond: vo.Val() == 0
+ // result: (TESTQ x:(MOVQload {sym} [vo.Off32()] ptr mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTQ)
+ x := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg2(ptr, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPQconstload {sym} [vo] ptr mem)
+ // cond: vo.Val() != 0
+ // result: (CMPQconst (MOVQload {sym} [vo.Off32()] ptr mem) [vo.Val32()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPQconst)
+ v.AuxInt = int32ToAuxInt(vo.Val32())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPQconstloadidx1(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPQconstloadidx1 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() == 0
+ // result: (TESTQ x:(MOVQloadidx1 {sym} [vo.Off32()] ptr idx mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTQ)
+ x := b.NewValue0(v.Pos, OpAMD64MOVQloadidx1, typ.UInt64)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg3(ptr, idx, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPQconstloadidx1 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() != 0
+ // result: (CMPQconst (MOVQloadidx1 {sym} [vo.Off32()] ptr idx mem) [vo.Val32()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPQconst)
+ v.AuxInt = int32ToAuxInt(vo.Val32())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQloadidx1, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPQconstloadidx8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPQconstloadidx8 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() == 0
+ // result: (TESTQ x:(MOVQloadidx8 {sym} [vo.Off32()] ptr idx mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTQ)
+ x := b.NewValue0(v.Pos, OpAMD64MOVQloadidx8, typ.UInt64)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg3(ptr, idx, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPQconstloadidx8 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() != 0
+ // result: (CMPQconst (MOVQloadidx8 {sym} [vo.Off32()] ptr idx mem) [vo.Val32()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPQconst)
+ v.AuxInt = int32ToAuxInt(vo.Val32())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQloadidx8, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPQload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPQload {sym} [off] ptr x mem)
+ // result: (CMPQ (MOVQload {sym} [off] ptr mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ x := v_1
+ mem := v_2
+ v.reset(OpAMD64CMPQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueAMD64splitload_OpAMD64CMPQloadidx1(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPQloadidx1 {sym} [off] ptr idx x mem)
+ // result: (CMPQ (MOVQloadidx1 {sym} [off] ptr idx mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ x := v_2
+ mem := v_3
+ v.reset(OpAMD64CMPQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQloadidx1, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueAMD64splitload_OpAMD64CMPQloadidx8(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPQloadidx8 {sym} [off] ptr idx x mem)
+ // result: (CMPQ (MOVQloadidx8 {sym} [off] ptr idx mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ x := v_2
+ mem := v_3
+ v.reset(OpAMD64CMPQ)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVQloadidx8, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueAMD64splitload_OpAMD64CMPWconstload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPWconstload {sym} [vo] ptr mem)
+ // cond: vo.Val() == 0
+ // result: (TESTW x:(MOVWload {sym} [vo.Off32()] ptr mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTW)
+ x := b.NewValue0(v.Pos, OpAMD64MOVWload, typ.UInt16)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg2(ptr, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPWconstload {sym} [vo] ptr mem)
+ // cond: vo.Val() != 0
+ // result: (CMPWconst (MOVWload {sym} [vo.Off32()] ptr mem) [vo.Val16()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPWconst)
+ v.AuxInt = int16ToAuxInt(vo.Val16())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPWconstloadidx1(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPWconstloadidx1 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() == 0
+ // result: (TESTW x:(MOVWloadidx1 {sym} [vo.Off32()] ptr idx mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTW)
+ x := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, typ.UInt16)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg3(ptr, idx, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPWconstloadidx1 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() != 0
+ // result: (CMPWconst (MOVWloadidx1 {sym} [vo.Off32()] ptr idx mem) [vo.Val16()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPWconst)
+ v.AuxInt = int16ToAuxInt(vo.Val16())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPWconstloadidx2(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPWconstloadidx2 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() == 0
+ // result: (TESTW x:(MOVWloadidx2 {sym} [vo.Off32()] ptr idx mem) x)
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() == 0) {
+ break
+ }
+ v.reset(OpAMD64TESTW)
+ x := b.NewValue0(v.Pos, OpAMD64MOVWloadidx2, typ.UInt16)
+ x.AuxInt = int32ToAuxInt(vo.Off32())
+ x.Aux = symToAux(sym)
+ x.AddArg3(ptr, idx, mem)
+ v.AddArg2(x, x)
+ return true
+ }
+ // match: (CMPWconstloadidx2 {sym} [vo] ptr idx mem)
+ // cond: vo.Val() != 0
+ // result: (CMPWconst (MOVWloadidx2 {sym} [vo.Off32()] ptr idx mem) [vo.Val16()])
+ for {
+ vo := auxIntToValAndOff(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ mem := v_2
+ if !(vo.Val() != 0) {
+ break
+ }
+ v.reset(OpAMD64CMPWconst)
+ v.AuxInt = int16ToAuxInt(vo.Val16())
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx2, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(vo.Off32())
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64splitload_OpAMD64CMPWload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPWload {sym} [off] ptr x mem)
+ // result: (CMPW (MOVWload {sym} [off] ptr mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ x := v_1
+ mem := v_2
+ v.reset(OpAMD64CMPW)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueAMD64splitload_OpAMD64CMPWloadidx1(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPWloadidx1 {sym} [off] ptr idx x mem)
+ // result: (CMPW (MOVWloadidx1 {sym} [off] ptr idx mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ x := v_2
+ mem := v_3
+ v.reset(OpAMD64CMPW)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueAMD64splitload_OpAMD64CMPWloadidx2(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (CMPWloadidx2 {sym} [off] ptr idx x mem)
+ // result: (CMPW (MOVWloadidx2 {sym} [off] ptr idx mem) x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ idx := v_1
+ x := v_2
+ mem := v_3
+ v.reset(OpAMD64CMPW)
+ v0 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx2, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg3(ptr, idx, mem)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteBlockAMD64splitload(b *Block) bool {
+ switch b.Kind {
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go
new file mode 100644
index 0000000..1f25005
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewriteARM.go
@@ -0,0 +1,22017 @@
+// Code generated from gen/ARM.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "cmd/internal/objabi"
+import "cmd/compile/internal/types"
+
+func rewriteValueARM(v *Value) bool {
+ switch v.Op {
+ case OpARMADC:
+ return rewriteValueARM_OpARMADC(v)
+ case OpARMADCconst:
+ return rewriteValueARM_OpARMADCconst(v)
+ case OpARMADCshiftLL:
+ return rewriteValueARM_OpARMADCshiftLL(v)
+ case OpARMADCshiftLLreg:
+ return rewriteValueARM_OpARMADCshiftLLreg(v)
+ case OpARMADCshiftRA:
+ return rewriteValueARM_OpARMADCshiftRA(v)
+ case OpARMADCshiftRAreg:
+ return rewriteValueARM_OpARMADCshiftRAreg(v)
+ case OpARMADCshiftRL:
+ return rewriteValueARM_OpARMADCshiftRL(v)
+ case OpARMADCshiftRLreg:
+ return rewriteValueARM_OpARMADCshiftRLreg(v)
+ case OpARMADD:
+ return rewriteValueARM_OpARMADD(v)
+ case OpARMADDD:
+ return rewriteValueARM_OpARMADDD(v)
+ case OpARMADDF:
+ return rewriteValueARM_OpARMADDF(v)
+ case OpARMADDS:
+ return rewriteValueARM_OpARMADDS(v)
+ case OpARMADDSshiftLL:
+ return rewriteValueARM_OpARMADDSshiftLL(v)
+ case OpARMADDSshiftLLreg:
+ return rewriteValueARM_OpARMADDSshiftLLreg(v)
+ case OpARMADDSshiftRA:
+ return rewriteValueARM_OpARMADDSshiftRA(v)
+ case OpARMADDSshiftRAreg:
+ return rewriteValueARM_OpARMADDSshiftRAreg(v)
+ case OpARMADDSshiftRL:
+ return rewriteValueARM_OpARMADDSshiftRL(v)
+ case OpARMADDSshiftRLreg:
+ return rewriteValueARM_OpARMADDSshiftRLreg(v)
+ case OpARMADDconst:
+ return rewriteValueARM_OpARMADDconst(v)
+ case OpARMADDshiftLL:
+ return rewriteValueARM_OpARMADDshiftLL(v)
+ case OpARMADDshiftLLreg:
+ return rewriteValueARM_OpARMADDshiftLLreg(v)
+ case OpARMADDshiftRA:
+ return rewriteValueARM_OpARMADDshiftRA(v)
+ case OpARMADDshiftRAreg:
+ return rewriteValueARM_OpARMADDshiftRAreg(v)
+ case OpARMADDshiftRL:
+ return rewriteValueARM_OpARMADDshiftRL(v)
+ case OpARMADDshiftRLreg:
+ return rewriteValueARM_OpARMADDshiftRLreg(v)
+ case OpARMAND:
+ return rewriteValueARM_OpARMAND(v)
+ case OpARMANDconst:
+ return rewriteValueARM_OpARMANDconst(v)
+ case OpARMANDshiftLL:
+ return rewriteValueARM_OpARMANDshiftLL(v)
+ case OpARMANDshiftLLreg:
+ return rewriteValueARM_OpARMANDshiftLLreg(v)
+ case OpARMANDshiftRA:
+ return rewriteValueARM_OpARMANDshiftRA(v)
+ case OpARMANDshiftRAreg:
+ return rewriteValueARM_OpARMANDshiftRAreg(v)
+ case OpARMANDshiftRL:
+ return rewriteValueARM_OpARMANDshiftRL(v)
+ case OpARMANDshiftRLreg:
+ return rewriteValueARM_OpARMANDshiftRLreg(v)
+ case OpARMBFX:
+ return rewriteValueARM_OpARMBFX(v)
+ case OpARMBFXU:
+ return rewriteValueARM_OpARMBFXU(v)
+ case OpARMBIC:
+ return rewriteValueARM_OpARMBIC(v)
+ case OpARMBICconst:
+ return rewriteValueARM_OpARMBICconst(v)
+ case OpARMBICshiftLL:
+ return rewriteValueARM_OpARMBICshiftLL(v)
+ case OpARMBICshiftLLreg:
+ return rewriteValueARM_OpARMBICshiftLLreg(v)
+ case OpARMBICshiftRA:
+ return rewriteValueARM_OpARMBICshiftRA(v)
+ case OpARMBICshiftRAreg:
+ return rewriteValueARM_OpARMBICshiftRAreg(v)
+ case OpARMBICshiftRL:
+ return rewriteValueARM_OpARMBICshiftRL(v)
+ case OpARMBICshiftRLreg:
+ return rewriteValueARM_OpARMBICshiftRLreg(v)
+ case OpARMCMN:
+ return rewriteValueARM_OpARMCMN(v)
+ case OpARMCMNconst:
+ return rewriteValueARM_OpARMCMNconst(v)
+ case OpARMCMNshiftLL:
+ return rewriteValueARM_OpARMCMNshiftLL(v)
+ case OpARMCMNshiftLLreg:
+ return rewriteValueARM_OpARMCMNshiftLLreg(v)
+ case OpARMCMNshiftRA:
+ return rewriteValueARM_OpARMCMNshiftRA(v)
+ case OpARMCMNshiftRAreg:
+ return rewriteValueARM_OpARMCMNshiftRAreg(v)
+ case OpARMCMNshiftRL:
+ return rewriteValueARM_OpARMCMNshiftRL(v)
+ case OpARMCMNshiftRLreg:
+ return rewriteValueARM_OpARMCMNshiftRLreg(v)
+ case OpARMCMOVWHSconst:
+ return rewriteValueARM_OpARMCMOVWHSconst(v)
+ case OpARMCMOVWLSconst:
+ return rewriteValueARM_OpARMCMOVWLSconst(v)
+ case OpARMCMP:
+ return rewriteValueARM_OpARMCMP(v)
+ case OpARMCMPD:
+ return rewriteValueARM_OpARMCMPD(v)
+ case OpARMCMPF:
+ return rewriteValueARM_OpARMCMPF(v)
+ case OpARMCMPconst:
+ return rewriteValueARM_OpARMCMPconst(v)
+ case OpARMCMPshiftLL:
+ return rewriteValueARM_OpARMCMPshiftLL(v)
+ case OpARMCMPshiftLLreg:
+ return rewriteValueARM_OpARMCMPshiftLLreg(v)
+ case OpARMCMPshiftRA:
+ return rewriteValueARM_OpARMCMPshiftRA(v)
+ case OpARMCMPshiftRAreg:
+ return rewriteValueARM_OpARMCMPshiftRAreg(v)
+ case OpARMCMPshiftRL:
+ return rewriteValueARM_OpARMCMPshiftRL(v)
+ case OpARMCMPshiftRLreg:
+ return rewriteValueARM_OpARMCMPshiftRLreg(v)
+ case OpARMEqual:
+ return rewriteValueARM_OpARMEqual(v)
+ case OpARMGreaterEqual:
+ return rewriteValueARM_OpARMGreaterEqual(v)
+ case OpARMGreaterEqualU:
+ return rewriteValueARM_OpARMGreaterEqualU(v)
+ case OpARMGreaterThan:
+ return rewriteValueARM_OpARMGreaterThan(v)
+ case OpARMGreaterThanU:
+ return rewriteValueARM_OpARMGreaterThanU(v)
+ case OpARMLessEqual:
+ return rewriteValueARM_OpARMLessEqual(v)
+ case OpARMLessEqualU:
+ return rewriteValueARM_OpARMLessEqualU(v)
+ case OpARMLessThan:
+ return rewriteValueARM_OpARMLessThan(v)
+ case OpARMLessThanU:
+ return rewriteValueARM_OpARMLessThanU(v)
+ case OpARMMOVBUload:
+ return rewriteValueARM_OpARMMOVBUload(v)
+ case OpARMMOVBUloadidx:
+ return rewriteValueARM_OpARMMOVBUloadidx(v)
+ case OpARMMOVBUreg:
+ return rewriteValueARM_OpARMMOVBUreg(v)
+ case OpARMMOVBload:
+ return rewriteValueARM_OpARMMOVBload(v)
+ case OpARMMOVBloadidx:
+ return rewriteValueARM_OpARMMOVBloadidx(v)
+ case OpARMMOVBreg:
+ return rewriteValueARM_OpARMMOVBreg(v)
+ case OpARMMOVBstore:
+ return rewriteValueARM_OpARMMOVBstore(v)
+ case OpARMMOVBstoreidx:
+ return rewriteValueARM_OpARMMOVBstoreidx(v)
+ case OpARMMOVDload:
+ return rewriteValueARM_OpARMMOVDload(v)
+ case OpARMMOVDstore:
+ return rewriteValueARM_OpARMMOVDstore(v)
+ case OpARMMOVFload:
+ return rewriteValueARM_OpARMMOVFload(v)
+ case OpARMMOVFstore:
+ return rewriteValueARM_OpARMMOVFstore(v)
+ case OpARMMOVHUload:
+ return rewriteValueARM_OpARMMOVHUload(v)
+ case OpARMMOVHUloadidx:
+ return rewriteValueARM_OpARMMOVHUloadidx(v)
+ case OpARMMOVHUreg:
+ return rewriteValueARM_OpARMMOVHUreg(v)
+ case OpARMMOVHload:
+ return rewriteValueARM_OpARMMOVHload(v)
+ case OpARMMOVHloadidx:
+ return rewriteValueARM_OpARMMOVHloadidx(v)
+ case OpARMMOVHreg:
+ return rewriteValueARM_OpARMMOVHreg(v)
+ case OpARMMOVHstore:
+ return rewriteValueARM_OpARMMOVHstore(v)
+ case OpARMMOVHstoreidx:
+ return rewriteValueARM_OpARMMOVHstoreidx(v)
+ case OpARMMOVWload:
+ return rewriteValueARM_OpARMMOVWload(v)
+ case OpARMMOVWloadidx:
+ return rewriteValueARM_OpARMMOVWloadidx(v)
+ case OpARMMOVWloadshiftLL:
+ return rewriteValueARM_OpARMMOVWloadshiftLL(v)
+ case OpARMMOVWloadshiftRA:
+ return rewriteValueARM_OpARMMOVWloadshiftRA(v)
+ case OpARMMOVWloadshiftRL:
+ return rewriteValueARM_OpARMMOVWloadshiftRL(v)
+ case OpARMMOVWreg:
+ return rewriteValueARM_OpARMMOVWreg(v)
+ case OpARMMOVWstore:
+ return rewriteValueARM_OpARMMOVWstore(v)
+ case OpARMMOVWstoreidx:
+ return rewriteValueARM_OpARMMOVWstoreidx(v)
+ case OpARMMOVWstoreshiftLL:
+ return rewriteValueARM_OpARMMOVWstoreshiftLL(v)
+ case OpARMMOVWstoreshiftRA:
+ return rewriteValueARM_OpARMMOVWstoreshiftRA(v)
+ case OpARMMOVWstoreshiftRL:
+ return rewriteValueARM_OpARMMOVWstoreshiftRL(v)
+ case OpARMMUL:
+ return rewriteValueARM_OpARMMUL(v)
+ case OpARMMULA:
+ return rewriteValueARM_OpARMMULA(v)
+ case OpARMMULD:
+ return rewriteValueARM_OpARMMULD(v)
+ case OpARMMULF:
+ return rewriteValueARM_OpARMMULF(v)
+ case OpARMMULS:
+ return rewriteValueARM_OpARMMULS(v)
+ case OpARMMVN:
+ return rewriteValueARM_OpARMMVN(v)
+ case OpARMMVNshiftLL:
+ return rewriteValueARM_OpARMMVNshiftLL(v)
+ case OpARMMVNshiftLLreg:
+ return rewriteValueARM_OpARMMVNshiftLLreg(v)
+ case OpARMMVNshiftRA:
+ return rewriteValueARM_OpARMMVNshiftRA(v)
+ case OpARMMVNshiftRAreg:
+ return rewriteValueARM_OpARMMVNshiftRAreg(v)
+ case OpARMMVNshiftRL:
+ return rewriteValueARM_OpARMMVNshiftRL(v)
+ case OpARMMVNshiftRLreg:
+ return rewriteValueARM_OpARMMVNshiftRLreg(v)
+ case OpARMNEGD:
+ return rewriteValueARM_OpARMNEGD(v)
+ case OpARMNEGF:
+ return rewriteValueARM_OpARMNEGF(v)
+ case OpARMNMULD:
+ return rewriteValueARM_OpARMNMULD(v)
+ case OpARMNMULF:
+ return rewriteValueARM_OpARMNMULF(v)
+ case OpARMNotEqual:
+ return rewriteValueARM_OpARMNotEqual(v)
+ case OpARMOR:
+ return rewriteValueARM_OpARMOR(v)
+ case OpARMORconst:
+ return rewriteValueARM_OpARMORconst(v)
+ case OpARMORshiftLL:
+ return rewriteValueARM_OpARMORshiftLL(v)
+ case OpARMORshiftLLreg:
+ return rewriteValueARM_OpARMORshiftLLreg(v)
+ case OpARMORshiftRA:
+ return rewriteValueARM_OpARMORshiftRA(v)
+ case OpARMORshiftRAreg:
+ return rewriteValueARM_OpARMORshiftRAreg(v)
+ case OpARMORshiftRL:
+ return rewriteValueARM_OpARMORshiftRL(v)
+ case OpARMORshiftRLreg:
+ return rewriteValueARM_OpARMORshiftRLreg(v)
+ case OpARMRSB:
+ return rewriteValueARM_OpARMRSB(v)
+ case OpARMRSBSshiftLL:
+ return rewriteValueARM_OpARMRSBSshiftLL(v)
+ case OpARMRSBSshiftLLreg:
+ return rewriteValueARM_OpARMRSBSshiftLLreg(v)
+ case OpARMRSBSshiftRA:
+ return rewriteValueARM_OpARMRSBSshiftRA(v)
+ case OpARMRSBSshiftRAreg:
+ return rewriteValueARM_OpARMRSBSshiftRAreg(v)
+ case OpARMRSBSshiftRL:
+ return rewriteValueARM_OpARMRSBSshiftRL(v)
+ case OpARMRSBSshiftRLreg:
+ return rewriteValueARM_OpARMRSBSshiftRLreg(v)
+ case OpARMRSBconst:
+ return rewriteValueARM_OpARMRSBconst(v)
+ case OpARMRSBshiftLL:
+ return rewriteValueARM_OpARMRSBshiftLL(v)
+ case OpARMRSBshiftLLreg:
+ return rewriteValueARM_OpARMRSBshiftLLreg(v)
+ case OpARMRSBshiftRA:
+ return rewriteValueARM_OpARMRSBshiftRA(v)
+ case OpARMRSBshiftRAreg:
+ return rewriteValueARM_OpARMRSBshiftRAreg(v)
+ case OpARMRSBshiftRL:
+ return rewriteValueARM_OpARMRSBshiftRL(v)
+ case OpARMRSBshiftRLreg:
+ return rewriteValueARM_OpARMRSBshiftRLreg(v)
+ case OpARMRSCconst:
+ return rewriteValueARM_OpARMRSCconst(v)
+ case OpARMRSCshiftLL:
+ return rewriteValueARM_OpARMRSCshiftLL(v)
+ case OpARMRSCshiftLLreg:
+ return rewriteValueARM_OpARMRSCshiftLLreg(v)
+ case OpARMRSCshiftRA:
+ return rewriteValueARM_OpARMRSCshiftRA(v)
+ case OpARMRSCshiftRAreg:
+ return rewriteValueARM_OpARMRSCshiftRAreg(v)
+ case OpARMRSCshiftRL:
+ return rewriteValueARM_OpARMRSCshiftRL(v)
+ case OpARMRSCshiftRLreg:
+ return rewriteValueARM_OpARMRSCshiftRLreg(v)
+ case OpARMSBC:
+ return rewriteValueARM_OpARMSBC(v)
+ case OpARMSBCconst:
+ return rewriteValueARM_OpARMSBCconst(v)
+ case OpARMSBCshiftLL:
+ return rewriteValueARM_OpARMSBCshiftLL(v)
+ case OpARMSBCshiftLLreg:
+ return rewriteValueARM_OpARMSBCshiftLLreg(v)
+ case OpARMSBCshiftRA:
+ return rewriteValueARM_OpARMSBCshiftRA(v)
+ case OpARMSBCshiftRAreg:
+ return rewriteValueARM_OpARMSBCshiftRAreg(v)
+ case OpARMSBCshiftRL:
+ return rewriteValueARM_OpARMSBCshiftRL(v)
+ case OpARMSBCshiftRLreg:
+ return rewriteValueARM_OpARMSBCshiftRLreg(v)
+ case OpARMSLL:
+ return rewriteValueARM_OpARMSLL(v)
+ case OpARMSLLconst:
+ return rewriteValueARM_OpARMSLLconst(v)
+ case OpARMSRA:
+ return rewriteValueARM_OpARMSRA(v)
+ case OpARMSRAcond:
+ return rewriteValueARM_OpARMSRAcond(v)
+ case OpARMSRAconst:
+ return rewriteValueARM_OpARMSRAconst(v)
+ case OpARMSRL:
+ return rewriteValueARM_OpARMSRL(v)
+ case OpARMSRLconst:
+ return rewriteValueARM_OpARMSRLconst(v)
+ case OpARMSUB:
+ return rewriteValueARM_OpARMSUB(v)
+ case OpARMSUBD:
+ return rewriteValueARM_OpARMSUBD(v)
+ case OpARMSUBF:
+ return rewriteValueARM_OpARMSUBF(v)
+ case OpARMSUBS:
+ return rewriteValueARM_OpARMSUBS(v)
+ case OpARMSUBSshiftLL:
+ return rewriteValueARM_OpARMSUBSshiftLL(v)
+ case OpARMSUBSshiftLLreg:
+ return rewriteValueARM_OpARMSUBSshiftLLreg(v)
+ case OpARMSUBSshiftRA:
+ return rewriteValueARM_OpARMSUBSshiftRA(v)
+ case OpARMSUBSshiftRAreg:
+ return rewriteValueARM_OpARMSUBSshiftRAreg(v)
+ case OpARMSUBSshiftRL:
+ return rewriteValueARM_OpARMSUBSshiftRL(v)
+ case OpARMSUBSshiftRLreg:
+ return rewriteValueARM_OpARMSUBSshiftRLreg(v)
+ case OpARMSUBconst:
+ return rewriteValueARM_OpARMSUBconst(v)
+ case OpARMSUBshiftLL:
+ return rewriteValueARM_OpARMSUBshiftLL(v)
+ case OpARMSUBshiftLLreg:
+ return rewriteValueARM_OpARMSUBshiftLLreg(v)
+ case OpARMSUBshiftRA:
+ return rewriteValueARM_OpARMSUBshiftRA(v)
+ case OpARMSUBshiftRAreg:
+ return rewriteValueARM_OpARMSUBshiftRAreg(v)
+ case OpARMSUBshiftRL:
+ return rewriteValueARM_OpARMSUBshiftRL(v)
+ case OpARMSUBshiftRLreg:
+ return rewriteValueARM_OpARMSUBshiftRLreg(v)
+ case OpARMTEQ:
+ return rewriteValueARM_OpARMTEQ(v)
+ case OpARMTEQconst:
+ return rewriteValueARM_OpARMTEQconst(v)
+ case OpARMTEQshiftLL:
+ return rewriteValueARM_OpARMTEQshiftLL(v)
+ case OpARMTEQshiftLLreg:
+ return rewriteValueARM_OpARMTEQshiftLLreg(v)
+ case OpARMTEQshiftRA:
+ return rewriteValueARM_OpARMTEQshiftRA(v)
+ case OpARMTEQshiftRAreg:
+ return rewriteValueARM_OpARMTEQshiftRAreg(v)
+ case OpARMTEQshiftRL:
+ return rewriteValueARM_OpARMTEQshiftRL(v)
+ case OpARMTEQshiftRLreg:
+ return rewriteValueARM_OpARMTEQshiftRLreg(v)
+ case OpARMTST:
+ return rewriteValueARM_OpARMTST(v)
+ case OpARMTSTconst:
+ return rewriteValueARM_OpARMTSTconst(v)
+ case OpARMTSTshiftLL:
+ return rewriteValueARM_OpARMTSTshiftLL(v)
+ case OpARMTSTshiftLLreg:
+ return rewriteValueARM_OpARMTSTshiftLLreg(v)
+ case OpARMTSTshiftRA:
+ return rewriteValueARM_OpARMTSTshiftRA(v)
+ case OpARMTSTshiftRAreg:
+ return rewriteValueARM_OpARMTSTshiftRAreg(v)
+ case OpARMTSTshiftRL:
+ return rewriteValueARM_OpARMTSTshiftRL(v)
+ case OpARMTSTshiftRLreg:
+ return rewriteValueARM_OpARMTSTshiftRLreg(v)
+ case OpARMXOR:
+ return rewriteValueARM_OpARMXOR(v)
+ case OpARMXORconst:
+ return rewriteValueARM_OpARMXORconst(v)
+ case OpARMXORshiftLL:
+ return rewriteValueARM_OpARMXORshiftLL(v)
+ case OpARMXORshiftLLreg:
+ return rewriteValueARM_OpARMXORshiftLLreg(v)
+ case OpARMXORshiftRA:
+ return rewriteValueARM_OpARMXORshiftRA(v)
+ case OpARMXORshiftRAreg:
+ return rewriteValueARM_OpARMXORshiftRAreg(v)
+ case OpARMXORshiftRL:
+ return rewriteValueARM_OpARMXORshiftRL(v)
+ case OpARMXORshiftRLreg:
+ return rewriteValueARM_OpARMXORshiftRLreg(v)
+ case OpARMXORshiftRR:
+ return rewriteValueARM_OpARMXORshiftRR(v)
+ case OpAbs:
+ v.Op = OpARMABSD
+ return true
+ case OpAdd16:
+ v.Op = OpARMADD
+ return true
+ case OpAdd32:
+ v.Op = OpARMADD
+ return true
+ case OpAdd32F:
+ v.Op = OpARMADDF
+ return true
+ case OpAdd32carry:
+ v.Op = OpARMADDS
+ return true
+ case OpAdd32withcarry:
+ v.Op = OpARMADC
+ return true
+ case OpAdd64F:
+ v.Op = OpARMADDD
+ return true
+ case OpAdd8:
+ v.Op = OpARMADD
+ return true
+ case OpAddPtr:
+ v.Op = OpARMADD
+ return true
+ case OpAddr:
+ return rewriteValueARM_OpAddr(v)
+ case OpAnd16:
+ v.Op = OpARMAND
+ return true
+ case OpAnd32:
+ v.Op = OpARMAND
+ return true
+ case OpAnd8:
+ v.Op = OpARMAND
+ return true
+ case OpAndB:
+ v.Op = OpARMAND
+ return true
+ case OpAvg32u:
+ return rewriteValueARM_OpAvg32u(v)
+ case OpBitLen32:
+ return rewriteValueARM_OpBitLen32(v)
+ case OpBswap32:
+ return rewriteValueARM_OpBswap32(v)
+ case OpClosureCall:
+ v.Op = OpARMCALLclosure
+ return true
+ case OpCom16:
+ v.Op = OpARMMVN
+ return true
+ case OpCom32:
+ v.Op = OpARMMVN
+ return true
+ case OpCom8:
+ v.Op = OpARMMVN
+ return true
+ case OpConst16:
+ return rewriteValueARM_OpConst16(v)
+ case OpConst32:
+ return rewriteValueARM_OpConst32(v)
+ case OpConst32F:
+ return rewriteValueARM_OpConst32F(v)
+ case OpConst64F:
+ return rewriteValueARM_OpConst64F(v)
+ case OpConst8:
+ return rewriteValueARM_OpConst8(v)
+ case OpConstBool:
+ return rewriteValueARM_OpConstBool(v)
+ case OpConstNil:
+ return rewriteValueARM_OpConstNil(v)
+ case OpCtz16:
+ return rewriteValueARM_OpCtz16(v)
+ case OpCtz16NonZero:
+ v.Op = OpCtz32
+ return true
+ case OpCtz32:
+ return rewriteValueARM_OpCtz32(v)
+ case OpCtz32NonZero:
+ v.Op = OpCtz32
+ return true
+ case OpCtz8:
+ return rewriteValueARM_OpCtz8(v)
+ case OpCtz8NonZero:
+ v.Op = OpCtz32
+ return true
+ case OpCvt32Fto32:
+ v.Op = OpARMMOVFW
+ return true
+ case OpCvt32Fto32U:
+ v.Op = OpARMMOVFWU
+ return true
+ case OpCvt32Fto64F:
+ v.Op = OpARMMOVFD
+ return true
+ case OpCvt32Uto32F:
+ v.Op = OpARMMOVWUF
+ return true
+ case OpCvt32Uto64F:
+ v.Op = OpARMMOVWUD
+ return true
+ case OpCvt32to32F:
+ v.Op = OpARMMOVWF
+ return true
+ case OpCvt32to64F:
+ v.Op = OpARMMOVWD
+ return true
+ case OpCvt64Fto32:
+ v.Op = OpARMMOVDW
+ return true
+ case OpCvt64Fto32F:
+ v.Op = OpARMMOVDF
+ return true
+ case OpCvt64Fto32U:
+ v.Op = OpARMMOVDWU
+ return true
+ case OpCvtBoolToUint8:
+ v.Op = OpCopy
+ return true
+ case OpDiv16:
+ return rewriteValueARM_OpDiv16(v)
+ case OpDiv16u:
+ return rewriteValueARM_OpDiv16u(v)
+ case OpDiv32:
+ return rewriteValueARM_OpDiv32(v)
+ case OpDiv32F:
+ v.Op = OpARMDIVF
+ return true
+ case OpDiv32u:
+ return rewriteValueARM_OpDiv32u(v)
+ case OpDiv64F:
+ v.Op = OpARMDIVD
+ return true
+ case OpDiv8:
+ return rewriteValueARM_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValueARM_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValueARM_OpEq16(v)
+ case OpEq32:
+ return rewriteValueARM_OpEq32(v)
+ case OpEq32F:
+ return rewriteValueARM_OpEq32F(v)
+ case OpEq64F:
+ return rewriteValueARM_OpEq64F(v)
+ case OpEq8:
+ return rewriteValueARM_OpEq8(v)
+ case OpEqB:
+ return rewriteValueARM_OpEqB(v)
+ case OpEqPtr:
+ return rewriteValueARM_OpEqPtr(v)
+ case OpFMA:
+ return rewriteValueARM_OpFMA(v)
+ case OpGetCallerPC:
+ v.Op = OpARMLoweredGetCallerPC
+ return true
+ case OpGetCallerSP:
+ v.Op = OpARMLoweredGetCallerSP
+ return true
+ case OpGetClosurePtr:
+ v.Op = OpARMLoweredGetClosurePtr
+ return true
+ case OpHmul32:
+ v.Op = OpARMHMUL
+ return true
+ case OpHmul32u:
+ v.Op = OpARMHMULU
+ return true
+ case OpInterCall:
+ v.Op = OpARMCALLinter
+ return true
+ case OpIsInBounds:
+ return rewriteValueARM_OpIsInBounds(v)
+ case OpIsNonNil:
+ return rewriteValueARM_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ return rewriteValueARM_OpIsSliceInBounds(v)
+ case OpLeq16:
+ return rewriteValueARM_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValueARM_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValueARM_OpLeq32(v)
+ case OpLeq32F:
+ return rewriteValueARM_OpLeq32F(v)
+ case OpLeq32U:
+ return rewriteValueARM_OpLeq32U(v)
+ case OpLeq64F:
+ return rewriteValueARM_OpLeq64F(v)
+ case OpLeq8:
+ return rewriteValueARM_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValueARM_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValueARM_OpLess16(v)
+ case OpLess16U:
+ return rewriteValueARM_OpLess16U(v)
+ case OpLess32:
+ return rewriteValueARM_OpLess32(v)
+ case OpLess32F:
+ return rewriteValueARM_OpLess32F(v)
+ case OpLess32U:
+ return rewriteValueARM_OpLess32U(v)
+ case OpLess64F:
+ return rewriteValueARM_OpLess64F(v)
+ case OpLess8:
+ return rewriteValueARM_OpLess8(v)
+ case OpLess8U:
+ return rewriteValueARM_OpLess8U(v)
+ case OpLoad:
+ return rewriteValueARM_OpLoad(v)
+ case OpLocalAddr:
+ return rewriteValueARM_OpLocalAddr(v)
+ case OpLsh16x16:
+ return rewriteValueARM_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValueARM_OpLsh16x32(v)
+ case OpLsh16x64:
+ return rewriteValueARM_OpLsh16x64(v)
+ case OpLsh16x8:
+ return rewriteValueARM_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValueARM_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValueARM_OpLsh32x32(v)
+ case OpLsh32x64:
+ return rewriteValueARM_OpLsh32x64(v)
+ case OpLsh32x8:
+ return rewriteValueARM_OpLsh32x8(v)
+ case OpLsh8x16:
+ return rewriteValueARM_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValueARM_OpLsh8x32(v)
+ case OpLsh8x64:
+ return rewriteValueARM_OpLsh8x64(v)
+ case OpLsh8x8:
+ return rewriteValueARM_OpLsh8x8(v)
+ case OpMod16:
+ return rewriteValueARM_OpMod16(v)
+ case OpMod16u:
+ return rewriteValueARM_OpMod16u(v)
+ case OpMod32:
+ return rewriteValueARM_OpMod32(v)
+ case OpMod32u:
+ return rewriteValueARM_OpMod32u(v)
+ case OpMod8:
+ return rewriteValueARM_OpMod8(v)
+ case OpMod8u:
+ return rewriteValueARM_OpMod8u(v)
+ case OpMove:
+ return rewriteValueARM_OpMove(v)
+ case OpMul16:
+ v.Op = OpARMMUL
+ return true
+ case OpMul32:
+ v.Op = OpARMMUL
+ return true
+ case OpMul32F:
+ v.Op = OpARMMULF
+ return true
+ case OpMul32uhilo:
+ v.Op = OpARMMULLU
+ return true
+ case OpMul64F:
+ v.Op = OpARMMULD
+ return true
+ case OpMul8:
+ v.Op = OpARMMUL
+ return true
+ case OpNeg16:
+ return rewriteValueARM_OpNeg16(v)
+ case OpNeg32:
+ return rewriteValueARM_OpNeg32(v)
+ case OpNeg32F:
+ v.Op = OpARMNEGF
+ return true
+ case OpNeg64F:
+ v.Op = OpARMNEGD
+ return true
+ case OpNeg8:
+ return rewriteValueARM_OpNeg8(v)
+ case OpNeq16:
+ return rewriteValueARM_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValueARM_OpNeq32(v)
+ case OpNeq32F:
+ return rewriteValueARM_OpNeq32F(v)
+ case OpNeq64F:
+ return rewriteValueARM_OpNeq64F(v)
+ case OpNeq8:
+ return rewriteValueARM_OpNeq8(v)
+ case OpNeqB:
+ v.Op = OpARMXOR
+ return true
+ case OpNeqPtr:
+ return rewriteValueARM_OpNeqPtr(v)
+ case OpNilCheck:
+ v.Op = OpARMLoweredNilCheck
+ return true
+ case OpNot:
+ return rewriteValueARM_OpNot(v)
+ case OpOffPtr:
+ return rewriteValueARM_OpOffPtr(v)
+ case OpOr16:
+ v.Op = OpARMOR
+ return true
+ case OpOr32:
+ v.Op = OpARMOR
+ return true
+ case OpOr8:
+ v.Op = OpARMOR
+ return true
+ case OpOrB:
+ v.Op = OpARMOR
+ return true
+ case OpPanicBounds:
+ return rewriteValueARM_OpPanicBounds(v)
+ case OpPanicExtend:
+ return rewriteValueARM_OpPanicExtend(v)
+ case OpRotateLeft16:
+ return rewriteValueARM_OpRotateLeft16(v)
+ case OpRotateLeft32:
+ return rewriteValueARM_OpRotateLeft32(v)
+ case OpRotateLeft8:
+ return rewriteValueARM_OpRotateLeft8(v)
+ case OpRound32F:
+ v.Op = OpCopy
+ return true
+ case OpRound64F:
+ v.Op = OpCopy
+ return true
+ case OpRsh16Ux16:
+ return rewriteValueARM_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValueARM_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValueARM_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValueARM_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValueARM_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValueARM_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValueARM_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValueARM_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValueARM_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValueARM_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValueARM_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValueARM_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValueARM_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValueARM_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValueARM_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValueARM_OpRsh32x8(v)
+ case OpRsh8Ux16:
+ return rewriteValueARM_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValueARM_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValueARM_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValueARM_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValueARM_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValueARM_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValueARM_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValueARM_OpRsh8x8(v)
+ case OpSelect0:
+ return rewriteValueARM_OpSelect0(v)
+ case OpSelect1:
+ return rewriteValueARM_OpSelect1(v)
+ case OpSignExt16to32:
+ v.Op = OpARMMOVHreg
+ return true
+ case OpSignExt8to16:
+ v.Op = OpARMMOVBreg
+ return true
+ case OpSignExt8to32:
+ v.Op = OpARMMOVBreg
+ return true
+ case OpSignmask:
+ return rewriteValueARM_OpSignmask(v)
+ case OpSlicemask:
+ return rewriteValueARM_OpSlicemask(v)
+ case OpSqrt:
+ v.Op = OpARMSQRTD
+ return true
+ case OpStaticCall:
+ v.Op = OpARMCALLstatic
+ return true
+ case OpStore:
+ return rewriteValueARM_OpStore(v)
+ case OpSub16:
+ v.Op = OpARMSUB
+ return true
+ case OpSub32:
+ v.Op = OpARMSUB
+ return true
+ case OpSub32F:
+ v.Op = OpARMSUBF
+ return true
+ case OpSub32carry:
+ v.Op = OpARMSUBS
+ return true
+ case OpSub32withcarry:
+ v.Op = OpARMSBC
+ return true
+ case OpSub64F:
+ v.Op = OpARMSUBD
+ return true
+ case OpSub8:
+ v.Op = OpARMSUB
+ return true
+ case OpSubPtr:
+ v.Op = OpARMSUB
+ return true
+ case OpTrunc16to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to8:
+ v.Op = OpCopy
+ return true
+ case OpWB:
+ v.Op = OpARMLoweredWB
+ return true
+ case OpXor16:
+ v.Op = OpARMXOR
+ return true
+ case OpXor32:
+ v.Op = OpARMXOR
+ return true
+ case OpXor8:
+ v.Op = OpARMXOR
+ return true
+ case OpZero:
+ return rewriteValueARM_OpZero(v)
+ case OpZeroExt16to32:
+ v.Op = OpARMMOVHUreg
+ return true
+ case OpZeroExt8to16:
+ v.Op = OpARMMOVBUreg
+ return true
+ case OpZeroExt8to32:
+ v.Op = OpARMMOVBUreg
+ return true
+ case OpZeromask:
+ return rewriteValueARM_OpZeromask(v)
+ }
+ return false
+}
+func rewriteValueARM_OpARMADC(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADC (MOVWconst [c]) x flags)
+ // result: (ADCconst [c] x flags)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, flags)
+ return true
+ }
+ break
+ }
+ // match: (ADC x (SLLconst [c] y) flags)
+ // result: (ADCshiftLL x y [c] flags)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMADCshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ break
+ }
+ // match: (ADC x (SRLconst [c] y) flags)
+ // result: (ADCshiftRL x y [c] flags)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMADCshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ break
+ }
+ // match: (ADC x (SRAconst [c] y) flags)
+ // result: (ADCshiftRA x y [c] flags)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMADCshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ break
+ }
+ // match: (ADC x (SLL y z) flags)
+ // result: (ADCshiftLLreg x y z flags)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMADCshiftLLreg)
+ v.AddArg4(x, y, z, flags)
+ return true
+ }
+ break
+ }
+ // match: (ADC x (SRL y z) flags)
+ // result: (ADCshiftRLreg x y z flags)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMADCshiftRLreg)
+ v.AddArg4(x, y, z, flags)
+ return true
+ }
+ break
+ }
+ // match: (ADC x (SRA y z) flags)
+ // result: (ADCshiftRAreg x y z flags)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMADCshiftRAreg)
+ v.AddArg4(x, y, z, flags)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMADCconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADCconst [c] (ADDconst [d] x) flags)
+ // result: (ADCconst [c+d] x flags)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ flags := v_1
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg2(x, flags)
+ return true
+ }
+ // match: (ADCconst [c] (SUBconst [d] x) flags)
+ // result: (ADCconst [c-d] x flags)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ flags := v_1
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADCshiftLL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADCshiftLL (MOVWconst [c]) x [d] flags)
+ // result: (ADCconst [c] (SLLconst <x.Type> x [d]) flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (ADCshiftLL x (MOVWconst [c]) [d] flags)
+ // result: (ADCconst x [c<<uint64(d)] flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ flags := v_2
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADCshiftLLreg(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADCshiftLLreg (MOVWconst [c]) x y flags)
+ // result: (ADCconst [c] (SLL <x.Type> x y) flags)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ flags := v_3
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (ADCshiftLLreg x y (MOVWconst [c]) flags)
+ // cond: 0 <= c && c < 32
+ // result: (ADCshiftLL x y [c] flags)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ flags := v_3
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMADCshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADCshiftRA(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADCshiftRA (MOVWconst [c]) x [d] flags)
+ // result: (ADCconst [c] (SRAconst <x.Type> x [d]) flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (ADCshiftRA x (MOVWconst [c]) [d] flags)
+ // result: (ADCconst x [c>>uint64(d)] flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ flags := v_2
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADCshiftRAreg(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADCshiftRAreg (MOVWconst [c]) x y flags)
+ // result: (ADCconst [c] (SRA <x.Type> x y) flags)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ flags := v_3
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (ADCshiftRAreg x y (MOVWconst [c]) flags)
+ // cond: 0 <= c && c < 32
+ // result: (ADCshiftRA x y [c] flags)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ flags := v_3
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMADCshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADCshiftRL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADCshiftRL (MOVWconst [c]) x [d] flags)
+ // result: (ADCconst [c] (SRLconst <x.Type> x [d]) flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (ADCshiftRL x (MOVWconst [c]) [d] flags)
+ // result: (ADCconst x [int32(uint32(c)>>uint64(d))] flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ flags := v_2
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADCshiftRLreg(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADCshiftRLreg (MOVWconst [c]) x y flags)
+ // result: (ADCconst [c] (SRL <x.Type> x y) flags)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ flags := v_3
+ v.reset(OpARMADCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (ADCshiftRLreg x y (MOVWconst [c]) flags)
+ // cond: 0 <= c && c < 32
+ // result: (ADCshiftRL x y [c] flags)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ flags := v_3
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMADCshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADD x (MOVWconst [c]))
+ // result: (ADDconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (SLLconst [c] y))
+ // result: (ADDshiftLL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMADDshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (SRLconst [c] y))
+ // result: (ADDshiftRL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMADDshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (SRAconst [c] y))
+ // result: (ADDshiftRA x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMADDshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (SLL y z))
+ // result: (ADDshiftLLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMADDshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (SRL y z))
+ // result: (ADDshiftRLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMADDshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (SRA y z))
+ // result: (ADDshiftRAreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMADDshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (RSBconst [0] y))
+ // result: (SUB x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMRSBconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpARMSUB)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD <t> (RSBconst [c] x) (RSBconst [d] y))
+ // result: (RSBconst [c+d] (ADD <t> x y))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARMRSBconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpARMRSBconst {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v0 := b.NewValue0(v.Pos, OpARMADD, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (ADD (MUL x y) a)
+ // result: (MULA x y a)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARMMUL {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ a := v_1
+ v.reset(OpARMMULA)
+ v.AddArg3(x, y, a)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDD a (MULD x y))
+ // cond: a.Uses == 1 && objabi.GOARM >= 6
+ // result: (MULAD a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ if v_1.Op != OpARMMULD {
+ continue
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ if !(a.Uses == 1 && objabi.GOARM >= 6) {
+ continue
+ }
+ v.reset(OpARMMULAD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDD a (NMULD x y))
+ // cond: a.Uses == 1 && objabi.GOARM >= 6
+ // result: (MULSD a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ if v_1.Op != OpARMNMULD {
+ continue
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ if !(a.Uses == 1 && objabi.GOARM >= 6) {
+ continue
+ }
+ v.reset(OpARMMULSD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDF(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDF a (MULF x y))
+ // cond: a.Uses == 1 && objabi.GOARM >= 6
+ // result: (MULAF a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ if v_1.Op != OpARMMULF {
+ continue
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ if !(a.Uses == 1 && objabi.GOARM >= 6) {
+ continue
+ }
+ v.reset(OpARMMULAF)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDF a (NMULF x y))
+ // cond: a.Uses == 1 && objabi.GOARM >= 6
+ // result: (MULSF a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ if v_1.Op != OpARMNMULF {
+ continue
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ if !(a.Uses == 1 && objabi.GOARM >= 6) {
+ continue
+ }
+ v.reset(OpARMMULSF)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDS x (MOVWconst [c]))
+ // result: (ADDSconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMADDSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDS x (SLLconst [c] y))
+ // result: (ADDSshiftLL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMADDSshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDS x (SRLconst [c] y))
+ // result: (ADDSshiftRL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMADDSshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDS x (SRAconst [c] y))
+ // result: (ADDSshiftRA x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMADDSshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDS x (SLL y z))
+ // result: (ADDSshiftLLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMADDSshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (ADDS x (SRL y z))
+ // result: (ADDSshiftRLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMADDSshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (ADDS x (SRA y z))
+ // result: (ADDSshiftRAreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMADDSshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDSshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDSshiftLL (MOVWconst [c]) x [d])
+ // result: (ADDSconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMADDSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDSshiftLL x (MOVWconst [c]) [d])
+ // result: (ADDSconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMADDSconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDSshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDSshiftLLreg (MOVWconst [c]) x y)
+ // result: (ADDSconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMADDSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDSshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ADDSshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMADDSshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDSshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDSshiftRA (MOVWconst [c]) x [d])
+ // result: (ADDSconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMADDSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDSshiftRA x (MOVWconst [c]) [d])
+ // result: (ADDSconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMADDSconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDSshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDSshiftRAreg (MOVWconst [c]) x y)
+ // result: (ADDSconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMADDSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDSshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ADDSshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMADDSshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDSshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDSshiftRL (MOVWconst [c]) x [d])
+ // result: (ADDSconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMADDSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDSshiftRL x (MOVWconst [c]) [d])
+ // result: (ADDSconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMADDSconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDSshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDSshiftRLreg (MOVWconst [c]) x y)
+ // result: (ADDSconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMADDSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDSshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ADDSshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMADDSshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDconst [off1] (MOVWaddr [off2] {sym} ptr))
+ // result: (MOVWaddr [off1+off2] {sym} ptr)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ v.reset(OpARMMOVWaddr)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (ADDconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ADDconst [c] x)
+ // cond: !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c))
+ // result: (SUBconst [-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(!isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c))) {
+ break
+ }
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [c] x)
+ // cond: objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && uint32(-c)<=0xffff
+ // result: (SUBconst [-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(objabi.GOARM == 7 && !isARMImmRot(uint32(c)) && uint32(c) > 0xffff && uint32(-c) <= 0xffff) {
+ break
+ }
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [c+d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ return true
+ }
+ // match: (ADDconst [c] (ADDconst [d] x))
+ // result: (ADDconst [c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [c] (SUBconst [d] x))
+ // result: (ADDconst [c-d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [c] (RSBconst [d] x))
+ // result: (RSBconst [c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMRSBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ADDshiftLL (MOVWconst [c]) x [d])
+ // result: (ADDconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDshiftLL x (MOVWconst [c]) [d])
+ // result: (ADDconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDshiftLL [c] (SRLconst x [32-c]) x)
+ // result: (SRRconst [32-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != 32-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMSRRconst)
+ v.AuxInt = int32ToAuxInt(32 - c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDshiftLL <typ.UInt16> [8] (BFXU <typ.UInt16> [int32(armBFAuxInt(8, 8))] x) x)
+ // result: (REV16 x)
+ for {
+ if v.Type != typ.UInt16 || auxIntToInt32(v.AuxInt) != 8 || v_0.Op != OpARMBFXU || v_0.Type != typ.UInt16 || auxIntToInt32(v_0.AuxInt) != int32(armBFAuxInt(8, 8)) {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMREV16)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDshiftLL <typ.UInt16> [8] (SRLconst <typ.UInt16> [24] (SLLconst [16] x)) x)
+ // cond: objabi.GOARM>=6
+ // result: (REV16 x)
+ for {
+ if v.Type != typ.UInt16 || auxIntToInt32(v.AuxInt) != 8 || v_0.Op != OpARMSRLconst || v_0.Type != typ.UInt16 || auxIntToInt32(v_0.AuxInt) != 24 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMSLLconst || auxIntToInt32(v_0_0.AuxInt) != 16 {
+ break
+ }
+ x := v_0_0.Args[0]
+ if x != v_1 || !(objabi.GOARM >= 6) {
+ break
+ }
+ v.reset(OpARMREV16)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDshiftLLreg (MOVWconst [c]) x y)
+ // result: (ADDconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ADDshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMADDshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDshiftRA (MOVWconst [c]) x [d])
+ // result: (ADDconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDshiftRA x (MOVWconst [c]) [d])
+ // result: (ADDconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDshiftRAreg (MOVWconst [c]) x y)
+ // result: (ADDconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ADDshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMADDshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDshiftRL (MOVWconst [c]) x [d])
+ // result: (ADDconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDshiftRL x (MOVWconst [c]) [d])
+ // result: (ADDconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDshiftRL [c] (SLLconst x [32-c]) x)
+ // result: (SRRconst [ c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != 32-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMSRRconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMADDshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDshiftRLreg (MOVWconst [c]) x y)
+ // result: (ADDconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ADDshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMADDshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMAND(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AND x (MOVWconst [c]))
+ // result: (ANDconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND x (SLLconst [c] y))
+ // result: (ANDshiftLL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMANDshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (AND x (SRLconst [c] y))
+ // result: (ANDshiftRL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMANDshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (AND x (SRAconst [c] y))
+ // result: (ANDshiftRA x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMANDshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (AND x (SLL y z))
+ // result: (ANDshiftLLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMANDshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (AND x (SRL y z))
+ // result: (ANDshiftRLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMANDshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (AND x (SRA y z))
+ // result: (ANDshiftRAreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMANDshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (AND x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (AND x (MVN y))
+ // result: (BIC x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMVN {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpARMBIC)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (AND x (MVNshiftLL y [c]))
+ // result: (BICshiftLL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMVNshiftLL {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMBICshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (AND x (MVNshiftRL y [c]))
+ // result: (BICshiftRL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMVNshiftRL {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMBICshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (AND x (MVNshiftRA y [c]))
+ // result: (BICshiftRA x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMVNshiftRA {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMBICshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMANDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ANDconst [0] _)
+ // result: (MOVWconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (ANDconst [c] x)
+ // cond: int32(c)==-1
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(int32(c) == -1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDconst [c] x)
+ // cond: !isARMImmRot(uint32(c)) && isARMImmRot(^uint32(c))
+ // result: (BICconst [int32(^uint32(c))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(!isARMImmRot(uint32(c)) && isARMImmRot(^uint32(c))) {
+ break
+ }
+ v.reset(OpARMBICconst)
+ v.AuxInt = int32ToAuxInt(int32(^uint32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] x)
+ // cond: objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && ^uint32(c)<=0xffff
+ // result: (BICconst [int32(^uint32(c))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(objabi.GOARM == 7 && !isARMImmRot(uint32(c)) && uint32(c) > 0xffff && ^uint32(c) <= 0xffff) {
+ break
+ }
+ v.reset(OpARMBICconst)
+ v.AuxInt = int32ToAuxInt(int32(^uint32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [c&d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(c & d)
+ return true
+ }
+ // match: (ANDconst [c] (ANDconst [d] x))
+ // result: (ANDconst [c&d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMANDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c & d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMANDshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDshiftLL (MOVWconst [c]) x [d])
+ // result: (ANDconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ANDshiftLL x (MOVWconst [c]) [d])
+ // result: (ANDconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDshiftLL y:(SLLconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ y := v_0
+ if y.Op != OpARMSLLconst || auxIntToInt32(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMANDshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDshiftLLreg (MOVWconst [c]) x y)
+ // result: (ANDconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ANDshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ANDshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMANDshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMANDshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDshiftRA (MOVWconst [c]) x [d])
+ // result: (ANDconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ANDshiftRA x (MOVWconst [c]) [d])
+ // result: (ANDconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDshiftRA y:(SRAconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ y := v_0
+ if y.Op != OpARMSRAconst || auxIntToInt32(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMANDshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDshiftRAreg (MOVWconst [c]) x y)
+ // result: (ANDconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ANDshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ANDshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMANDshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMANDshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDshiftRL (MOVWconst [c]) x [d])
+ // result: (ANDconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ANDshiftRL x (MOVWconst [c]) [d])
+ // result: (ANDconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDshiftRL y:(SRLconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ y := v_0
+ if y.Op != OpARMSRLconst || auxIntToInt32(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMANDshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDshiftRLreg (MOVWconst [c]) x y)
+ // result: (ANDconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ANDshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ANDshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMANDshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMBFX(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BFX [c] (MOVWconst [d]))
+ // result: (MOVWconst [d<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8))])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(d << (32 - uint32(c&0xff) - uint32(c>>8)) >> (32 - uint32(c>>8)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMBFXU(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BFXU [c] (MOVWconst [d]))
+ // result: (MOVWconst [int32(uint32(d)<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8)))])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(d) << (32 - uint32(c&0xff) - uint32(c>>8)) >> (32 - uint32(c>>8))))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMBIC(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BIC x (MOVWconst [c]))
+ // result: (BICconst [c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMBICconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BIC x (SLLconst [c] y))
+ // result: (BICshiftLL x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMBICshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (BIC x (SRLconst [c] y))
+ // result: (BICshiftRL x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMBICshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (BIC x (SRAconst [c] y))
+ // result: (BICshiftRA x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMBICshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (BIC x (SLL y z))
+ // result: (BICshiftLLreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMBICshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (BIC x (SRL y z))
+ // result: (BICshiftRLreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMBICshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (BIC x (SRA y z))
+ // result: (BICshiftRAreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMBICshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (BIC x x)
+ // result: (MOVWconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMBICconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (BICconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (BICconst [c] _)
+ // cond: int32(c)==-1
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (BICconst [c] x)
+ // cond: !isARMImmRot(uint32(c)) && isARMImmRot(^uint32(c))
+ // result: (ANDconst [int32(^uint32(c))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(!isARMImmRot(uint32(c)) && isARMImmRot(^uint32(c))) {
+ break
+ }
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(int32(^uint32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BICconst [c] x)
+ // cond: objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && ^uint32(c)<=0xffff
+ // result: (ANDconst [int32(^uint32(c))] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(objabi.GOARM == 7 && !isARMImmRot(uint32(c)) && uint32(c) > 0xffff && ^uint32(c) <= 0xffff) {
+ break
+ }
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(int32(^uint32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BICconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [d&^c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(d &^ c)
+ return true
+ }
+ // match: (BICconst [c] (BICconst [d] x))
+ // result: (BICconst [c|d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMBICconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMBICconst)
+ v.AuxInt = int32ToAuxInt(c | d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMBICshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BICshiftLL x (MOVWconst [c]) [d])
+ // result: (BICconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMBICconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BICshiftLL (SLLconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMBICshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BICshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (BICshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMBICshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMBICshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BICshiftRA x (MOVWconst [c]) [d])
+ // result: (BICconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMBICconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BICshiftRA (SRAconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRAconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMBICshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BICshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (BICshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMBICshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMBICshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BICshiftRL x (MOVWconst [c]) [d])
+ // result: (BICconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMBICconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BICshiftRL (SRLconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMBICshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BICshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (BICshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMBICshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMN(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMN x (MOVWconst [c]))
+ // result: (CMNconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMCMNconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (CMN x (SLLconst [c] y))
+ // result: (CMNshiftLL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMCMNshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (CMN x (SRLconst [c] y))
+ // result: (CMNshiftRL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMCMNshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (CMN x (SRAconst [c] y))
+ // result: (CMNshiftRA x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMCMNshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (CMN x (SLL y z))
+ // result: (CMNshiftLLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMCMNshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (CMN x (SRL y z))
+ // result: (CMNshiftRLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMCMNshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (CMN x (SRA y z))
+ // result: (CMNshiftRAreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMCMNshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMNconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMNconst (MOVWconst [x]) [y])
+ // result: (FlagConstant [addFlags32(x,y)])
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMFlagConstant)
+ v.AuxInt = flagConstantToAuxInt(addFlags32(x, y))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMNshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMNshiftLL (MOVWconst [c]) x [d])
+ // result: (CMNconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMCMNconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftLL x (MOVWconst [c]) [d])
+ // result: (CMNconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMCMNconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMNshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMNshiftLLreg (MOVWconst [c]) x y)
+ // result: (CMNconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMCMNconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (CMNshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMCMNshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMNshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMNshiftRA (MOVWconst [c]) x [d])
+ // result: (CMNconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMCMNconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftRA x (MOVWconst [c]) [d])
+ // result: (CMNconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMCMNconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMNshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMNshiftRAreg (MOVWconst [c]) x y)
+ // result: (CMNconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMCMNconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (CMNshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMCMNshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMNshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMNshiftRL (MOVWconst [c]) x [d])
+ // result: (CMNconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMCMNconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftRL x (MOVWconst [c]) [d])
+ // result: (CMNconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMCMNconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMNshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMNshiftRLreg (MOVWconst [c]) x y)
+ // result: (CMNconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMCMNconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (CMNshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMCMNshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMOVWHSconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWHSconst _ (FlagConstant [fc]) [c])
+ // cond: fc.uge()
+ // result: (MOVWconst [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_1.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_1.AuxInt)
+ if !(fc.uge()) {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ return true
+ }
+ // match: (CMOVWHSconst x (FlagConstant [fc]) [c])
+ // cond: fc.ult()
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_1.AuxInt)
+ if !(fc.ult()) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWHSconst x (InvertFlags flags) [c])
+ // result: (CMOVWLSconst x flags [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMInvertFlags {
+ break
+ }
+ flags := v_1.Args[0]
+ v.reset(OpARMCMOVWLSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMOVWLSconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVWLSconst _ (FlagConstant [fc]) [c])
+ // cond: fc.ule()
+ // result: (MOVWconst [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_1.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_1.AuxInt)
+ if !(fc.ule()) {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ return true
+ }
+ // match: (CMOVWLSconst x (FlagConstant [fc]) [c])
+ // cond: fc.ugt()
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_1.AuxInt)
+ if !(fc.ugt()) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CMOVWLSconst x (InvertFlags flags) [c])
+ // result: (CMOVWHSconst x flags [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMInvertFlags {
+ break
+ }
+ flags := v_1.Args[0]
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMP(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMP x (MOVWconst [c]))
+ // result: (CMPconst [c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMCMPconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMP (MOVWconst [c]) x)
+ // result: (InvertFlags (CMPconst [c] x))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMP y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x (SLLconst [c] y))
+ // result: (CMPshiftLL x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMCMPshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMP (SLLconst [c] y) x)
+ // result: (InvertFlags (CMPshiftLL x y [c]))
+ for {
+ if v_0.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x (SRLconst [c] y))
+ // result: (CMPshiftRL x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMCMPshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMP (SRLconst [c] y) x)
+ // result: (InvertFlags (CMPshiftRL x y [c]))
+ for {
+ if v_0.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x (SRAconst [c] y))
+ // result: (CMPshiftRA x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMCMPshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMP (SRAconst [c] y) x)
+ // result: (InvertFlags (CMPshiftRA x y [c]))
+ for {
+ if v_0.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x (SLL y z))
+ // result: (CMPshiftLLreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMCMPshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (CMP (SLL y z) x)
+ // result: (InvertFlags (CMPshiftLLreg x y z))
+ for {
+ if v_0.Op != OpARMSLL {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x (SRL y z))
+ // result: (CMPshiftRLreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMCMPshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (CMP (SRL y z) x)
+ // result: (InvertFlags (CMPshiftRLreg x y z))
+ for {
+ if v_0.Op != OpARMSRL {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x (SRA y z))
+ // result: (CMPshiftRAreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMCMPshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (CMP (SRA y z) x)
+ // result: (InvertFlags (CMPshiftRAreg x y z))
+ for {
+ if v_0.Op != OpARMSRA {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMPD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPD x (MOVDconst [0]))
+ // result: (CMPD0 x)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVDconst || auxIntToFloat64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpARMCMPD0)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMPF(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMPF x (MOVFconst [0]))
+ // result: (CMPF0 x)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVFconst || auxIntToFloat64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpARMCMPF0)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMPconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPconst (MOVWconst [x]) [y])
+ // result: (FlagConstant [subFlags32(x,y)])
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMFlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags32(x, y))
+ return true
+ }
+ // match: (CMPconst (MOVBUreg _) [c])
+ // cond: 0xff < c
+ // result: (FlagConstant [subFlags32(0, 1)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVBUreg || !(0xff < c) {
+ break
+ }
+ v.reset(OpARMFlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags32(0, 1))
+ return true
+ }
+ // match: (CMPconst (MOVHUreg _) [c])
+ // cond: 0xffff < c
+ // result: (FlagConstant [subFlags32(0, 1)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVHUreg || !(0xffff < c) {
+ break
+ }
+ v.reset(OpARMFlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags32(0, 1))
+ return true
+ }
+ // match: (CMPconst (ANDconst _ [m]) [n])
+ // cond: 0 <= m && m < n
+ // result: (FlagConstant [subFlags32(0, 1)])
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMANDconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= m && m < n) {
+ break
+ }
+ v.reset(OpARMFlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags32(0, 1))
+ return true
+ }
+ // match: (CMPconst (SRLconst _ [c]) [n])
+ // cond: 0 <= n && 0 < c && c <= 32 && (1<<uint32(32-c)) <= uint32(n)
+ // result: (FlagConstant [subFlags32(0, 1)])
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= n && 0 < c && c <= 32 && (1<<uint32(32-c)) <= uint32(n)) {
+ break
+ }
+ v.reset(OpARMFlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags32(0, 1))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMPshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPshiftLL (MOVWconst [c]) x [d])
+ // result: (InvertFlags (CMPconst [c] (SLLconst <x.Type> x [d])))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v1 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v1.AuxInt = int32ToAuxInt(d)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPshiftLL x (MOVWconst [c]) [d])
+ // result: (CMPconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMCMPconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMPshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPshiftLLreg (MOVWconst [c]) x y)
+ // result: (InvertFlags (CMPconst [c] (SLL <x.Type> x y)))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v1 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (CMPshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMCMPshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMPshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPshiftRA (MOVWconst [c]) x [d])
+ // result: (InvertFlags (CMPconst [c] (SRAconst <x.Type> x [d])))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v1 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v1.AuxInt = int32ToAuxInt(d)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPshiftRA x (MOVWconst [c]) [d])
+ // result: (CMPconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMCMPconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMPshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPshiftRAreg (MOVWconst [c]) x y)
+ // result: (InvertFlags (CMPconst [c] (SRA <x.Type> x y)))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v1 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (CMPshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMCMPshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMPshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPshiftRL (MOVWconst [c]) x [d])
+ // result: (InvertFlags (CMPconst [c] (SRLconst <x.Type> x [d])))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v1 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v1.AuxInt = int32ToAuxInt(d)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPshiftRL x (MOVWconst [c]) [d])
+ // result: (CMPconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMCMPconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMCMPshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPshiftRLreg (MOVWconst [c]) x y)
+ // result: (InvertFlags (CMPconst [c] (SRL <x.Type> x y)))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v1 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (CMPshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMCMPshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Equal (FlagConstant [fc]))
+ // result: (MOVWconst [b2i32(fc.eq())])
+ for {
+ if v_0.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(fc.eq()))
+ return true
+ }
+ // match: (Equal (InvertFlags x))
+ // result: (Equal x)
+ for {
+ if v_0.Op != OpARMInvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARMEqual)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMGreaterEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (GreaterEqual (FlagConstant [fc]))
+ // result: (MOVWconst [b2i32(fc.ge())])
+ for {
+ if v_0.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(fc.ge()))
+ return true
+ }
+ // match: (GreaterEqual (InvertFlags x))
+ // result: (LessEqual x)
+ for {
+ if v_0.Op != OpARMInvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARMLessEqual)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMGreaterEqualU(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (GreaterEqualU (FlagConstant [fc]))
+ // result: (MOVWconst [b2i32(fc.uge())])
+ for {
+ if v_0.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(fc.uge()))
+ return true
+ }
+ // match: (GreaterEqualU (InvertFlags x))
+ // result: (LessEqualU x)
+ for {
+ if v_0.Op != OpARMInvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARMLessEqualU)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMGreaterThan(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (GreaterThan (FlagConstant [fc]))
+ // result: (MOVWconst [b2i32(fc.gt())])
+ for {
+ if v_0.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(fc.gt()))
+ return true
+ }
+ // match: (GreaterThan (InvertFlags x))
+ // result: (LessThan x)
+ for {
+ if v_0.Op != OpARMInvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARMLessThan)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMGreaterThanU(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (GreaterThanU (FlagConstant [fc]))
+ // result: (MOVWconst [b2i32(fc.ugt())])
+ for {
+ if v_0.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(fc.ugt()))
+ return true
+ }
+ // match: (GreaterThanU (InvertFlags x))
+ // result: (LessThanU x)
+ for {
+ if v_0.Op != OpARMInvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARMLessThanU)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMLessEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LessEqual (FlagConstant [fc]))
+ // result: (MOVWconst [b2i32(fc.le())])
+ for {
+ if v_0.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(fc.le()))
+ return true
+ }
+ // match: (LessEqual (InvertFlags x))
+ // result: (GreaterEqual x)
+ for {
+ if v_0.Op != OpARMInvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARMGreaterEqual)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMLessEqualU(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LessEqualU (FlagConstant [fc]))
+ // result: (MOVWconst [b2i32(fc.ule())])
+ for {
+ if v_0.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(fc.ule()))
+ return true
+ }
+ // match: (LessEqualU (InvertFlags x))
+ // result: (GreaterEqualU x)
+ for {
+ if v_0.Op != OpARMInvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARMGreaterEqualU)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMLessThan(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LessThan (FlagConstant [fc]))
+ // result: (MOVWconst [b2i32(fc.lt())])
+ for {
+ if v_0.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(fc.lt()))
+ return true
+ }
+ // match: (LessThan (InvertFlags x))
+ // result: (GreaterThan x)
+ for {
+ if v_0.Op != OpARMInvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARMGreaterThan)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMLessThanU(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LessThanU (FlagConstant [fc]))
+ // result: (MOVWconst [b2i32(fc.ult())])
+ for {
+ if v_0.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(fc.ult()))
+ return true
+ }
+ // match: (LessThanU (InvertFlags x))
+ // result: (GreaterThanU x)
+ for {
+ if v_0.Op != OpARMInvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARMGreaterThanU)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVBUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // result: (MOVBUload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // result: (MOVBUload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVBUreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVBstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARMMOVBUreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUload [0] {sym} (ADD ptr idx) mem)
+ // cond: sym == nil
+ // result: (MOVBUloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVBUloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVBUload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVWconst [int32(read8(sym, int64(off)))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(read8(sym, int64(off))))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVBUloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBUloadidx ptr idx (MOVBstoreidx ptr2 idx x _))
+ // cond: isSamePtr(ptr, ptr2)
+ // result: (MOVBUreg x)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARMMOVBstoreidx {
+ break
+ }
+ x := v_2.Args[2]
+ ptr2 := v_2.Args[0]
+ if idx != v_2.Args[1] || !(isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARMMOVBUreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUloadidx ptr (MOVWconst [c]) mem)
+ // result: (MOVBUload [c] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpARMMOVBUload)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUloadidx (MOVWconst [c]) ptr mem)
+ // result: (MOVBUload [c] ptr mem)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARMMOVBUload)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVBUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVBUreg x:(MOVBUload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVBUload {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg (ANDconst [c] x))
+ // result: (ANDconst [c&0xff] x)
+ for {
+ if v_0.Op != OpARMANDconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c & 0xff)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg x:(MOVBUreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVBUreg {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg (MOVWconst [c]))
+ // result: (MOVWconst [int32(uint8(c))])
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint8(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVBload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // result: (MOVBload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // result: (MOVBload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVBload)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVBreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVBstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARMMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBload [0] {sym} (ADD ptr idx) mem)
+ // cond: sym == nil
+ // result: (MOVBloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVBloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVBloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBloadidx ptr idx (MOVBstoreidx ptr2 idx x _))
+ // cond: isSamePtr(ptr, ptr2)
+ // result: (MOVBreg x)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARMMOVBstoreidx {
+ break
+ }
+ x := v_2.Args[2]
+ ptr2 := v_2.Args[0]
+ if idx != v_2.Args[1] || !(isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARMMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBloadidx ptr (MOVWconst [c]) mem)
+ // result: (MOVBload [c] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpARMMOVBload)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBloadidx (MOVWconst [c]) ptr mem)
+ // result: (MOVBload [c] ptr mem)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARMMOVBload)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVBreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVBreg x:(MOVBload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVBload {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (ANDconst [c] x))
+ // cond: c & 0x80 == 0
+ // result: (ANDconst [c&0x7f] x)
+ for {
+ if v_0.Op != OpARMANDconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c&0x80 == 0) {
+ break
+ }
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c & 0x7f)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg x:(MOVBreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVBreg {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (MOVWconst [c]))
+ // result: (MOVWconst [int32(int8(c))])
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(int8(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVBstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // result: (MOVBstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym} (SUBconst [off2] ptr) val mem)
+ // result: (MOVBstore [off1-off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVBreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVBUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVHUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [0] {sym} (ADD ptr idx) val mem)
+ // cond: sym == nil
+ // result: (MOVBstoreidx ptr idx val mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVBstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVBstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstoreidx ptr (MOVWconst [c]) val mem)
+ // result: (MOVBstore [c] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstoreidx (MOVWconst [c]) ptr val mem)
+ // result: (MOVBstore [c] ptr val mem)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // result: (MOVDload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // result: (MOVDload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVDstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // result: (MOVDstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ v.reset(OpARMMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off1] {sym} (SUBconst [off2] ptr) val mem)
+ // result: (MOVDstore [off1-off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ v.reset(OpARMMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVFload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVFload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // result: (MOVFload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVFload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVFload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // result: (MOVFload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVFload)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVFload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVFload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVFload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVFload [off] {sym} ptr (MOVFstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVFstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVFstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVFstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // result: (MOVFstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ v.reset(OpARMMOVFstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVFstore [off1] {sym} (SUBconst [off2] ptr) val mem)
+ // result: (MOVFstore [off1-off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ v.reset(OpARMMOVFstore)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVFstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVFstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVFstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVHUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // result: (MOVHUload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // result: (MOVHUload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVHUreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVHstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARMMOVHUreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUload [0] {sym} (ADD ptr idx) mem)
+ // cond: sym == nil
+ // result: (MOVHUloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVHUloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHUload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVWconst [int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVHUloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHUloadidx ptr idx (MOVHstoreidx ptr2 idx x _))
+ // cond: isSamePtr(ptr, ptr2)
+ // result: (MOVHUreg x)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARMMOVHstoreidx {
+ break
+ }
+ x := v_2.Args[2]
+ ptr2 := v_2.Args[0]
+ if idx != v_2.Args[1] || !(isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARMMOVHUreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUloadidx ptr (MOVWconst [c]) mem)
+ // result: (MOVHUload [c] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpARMMOVHUload)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUloadidx (MOVWconst [c]) ptr mem)
+ // result: (MOVHUload [c] ptr mem)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARMMOVHUload)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVHUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVHUreg x:(MOVBUload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVBUload {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVHUload {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg (ANDconst [c] x))
+ // result: (ANDconst [c&0xffff] x)
+ for {
+ if v_0.Op != OpARMANDconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c & 0xffff)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVBUreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVBUreg {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVHUreg {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg (MOVWconst [c]))
+ // result: (MOVWconst [int32(uint16(c))])
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint16(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVHload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // result: (MOVHload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // result: (MOVHload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVHload)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVHreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVHstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARMMOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHload [0] {sym} (ADD ptr idx) mem)
+ // cond: sym == nil
+ // result: (MOVHloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVHloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVHloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHloadidx ptr idx (MOVHstoreidx ptr2 idx x _))
+ // cond: isSamePtr(ptr, ptr2)
+ // result: (MOVHreg x)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARMMOVHstoreidx {
+ break
+ }
+ x := v_2.Args[2]
+ ptr2 := v_2.Args[0]
+ if idx != v_2.Args[1] || !(isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARMMOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHloadidx ptr (MOVWconst [c]) mem)
+ // result: (MOVHload [c] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpARMMOVHload)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHloadidx (MOVWconst [c]) ptr mem)
+ // result: (MOVHload [c] ptr mem)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARMMOVHload)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVHreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVHreg x:(MOVBload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVBload {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVBUload {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVHload {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (ANDconst [c] x))
+ // cond: c & 0x8000 == 0
+ // result: (ANDconst [c&0x7fff] x)
+ for {
+ if v_0.Op != OpARMANDconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c&0x8000 == 0) {
+ break
+ }
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c & 0x7fff)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVBreg {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVBUreg {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpARMMOVHreg {
+ break
+ }
+ v.reset(OpARMMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (MOVWconst [c]))
+ // result: (MOVWconst [int32(int16(c))])
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(int16(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVHstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // result: (MOVHstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ v.reset(OpARMMOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off1] {sym} (SUBconst [off2] ptr) val mem)
+ // result: (MOVHstore [off1-off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ v.reset(OpARMMOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARMMOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHUreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVHUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARMMOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [0] {sym} (ADD ptr idx) val mem)
+ // cond: sym == nil
+ // result: (MOVHstoreidx ptr idx val mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVHstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVHstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstoreidx ptr (MOVWconst [c]) val mem)
+ // result: (MOVHstore [c] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVHstore)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstoreidx (MOVWconst [c]) ptr val mem)
+ // result: (MOVHstore [c] ptr val mem)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVHstore)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVWload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // result: (MOVWload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // result: (MOVWload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ v.reset(OpARMMOVWload)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARMMOVWstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWload [0] {sym} (ADD ptr idx) mem)
+ // cond: sym == nil
+ // result: (MOVWloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVWloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWload [0] {sym} (ADDshiftLL ptr idx [c]) mem)
+ // cond: sym == nil
+ // result: (MOVWloadshiftLL ptr idx [c] mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDshiftLL {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVWloadshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWload [0] {sym} (ADDshiftRL ptr idx [c]) mem)
+ // cond: sym == nil
+ // result: (MOVWloadshiftRL ptr idx [c] mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDshiftRL {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVWloadshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWload [0] {sym} (ADDshiftRA ptr idx [c]) mem)
+ // cond: sym == nil
+ // result: (MOVWloadshiftRA ptr idx [c] mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDshiftRA {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVWloadshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVWconst [int32(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(read32(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWloadidx ptr idx (MOVWstoreidx ptr2 idx x _))
+ // cond: isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARMMOVWstoreidx {
+ break
+ }
+ x := v_2.Args[2]
+ ptr2 := v_2.Args[0]
+ if idx != v_2.Args[1] || !(isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWloadidx ptr (MOVWconst [c]) mem)
+ // result: (MOVWload [c] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpARMMOVWload)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWloadidx (MOVWconst [c]) ptr mem)
+ // result: (MOVWload [c] ptr mem)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARMMOVWload)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWloadidx ptr (SLLconst idx [c]) mem)
+ // result: (MOVWloadshiftLL ptr idx [c] mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARMMOVWloadshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWloadidx (SLLconst idx [c]) ptr mem)
+ // result: (MOVWloadshiftLL ptr idx [c] mem)
+ for {
+ if v_0.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[0]
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARMMOVWloadshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWloadidx ptr (SRLconst idx [c]) mem)
+ // result: (MOVWloadshiftRL ptr idx [c] mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARMMOVWloadshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWloadidx (SRLconst idx [c]) ptr mem)
+ // result: (MOVWloadshiftRL ptr idx [c] mem)
+ for {
+ if v_0.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[0]
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARMMOVWloadshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWloadidx ptr (SRAconst idx [c]) mem)
+ // result: (MOVWloadshiftRA ptr idx [c] mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARMMOVWloadshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWloadidx (SRAconst idx [c]) ptr mem)
+ // result: (MOVWloadshiftRA ptr idx [c] mem)
+ for {
+ if v_0.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[0]
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARMMOVWloadshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWloadshiftLL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWloadshiftLL ptr idx [c] (MOVWstoreshiftLL ptr2 idx [d] x _))
+ // cond: c==d && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARMMOVWstoreshiftLL {
+ break
+ }
+ d := auxIntToInt32(v_2.AuxInt)
+ x := v_2.Args[2]
+ ptr2 := v_2.Args[0]
+ if idx != v_2.Args[1] || !(c == d && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem)
+ // result: (MOVWload [int32(uint32(c)<<uint64(d))] ptr mem)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpARMMOVWload)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) << uint64(d)))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWloadshiftRA(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWloadshiftRA ptr idx [c] (MOVWstoreshiftRA ptr2 idx [d] x _))
+ // cond: c==d && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARMMOVWstoreshiftRA {
+ break
+ }
+ d := auxIntToInt32(v_2.AuxInt)
+ x := v_2.Args[2]
+ ptr2 := v_2.Args[0]
+ if idx != v_2.Args[1] || !(c == d && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWloadshiftRA ptr (MOVWconst [c]) [d] mem)
+ // result: (MOVWload [c>>uint64(d)] ptr mem)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpARMMOVWload)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWloadshiftRL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWloadshiftRL ptr idx [c] (MOVWstoreshiftRL ptr2 idx [d] x _))
+ // cond: c==d && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARMMOVWstoreshiftRL {
+ break
+ }
+ d := auxIntToInt32(v_2.AuxInt)
+ x := v_2.Args[2]
+ ptr2 := v_2.Args[0]
+ if idx != v_2.Args[1] || !(c == d && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWloadshiftRL ptr (MOVWconst [c]) [d] mem)
+ // result: (MOVWload [int32(uint32(c)>>uint64(d))] ptr mem)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ v.reset(OpARMMOVWload)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVWreg x)
+ // cond: x.Uses == 1
+ // result: (MOVWnop x)
+ for {
+ x := v_0
+ if !(x.Uses == 1) {
+ break
+ }
+ v.reset(OpARMMOVWnop)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg (MOVWconst [c]))
+ // result: (MOVWconst [c])
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // result: (MOVWstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ v.reset(OpARMMOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym} (SUBconst [off2] ptr) val mem)
+ // result: (MOVWstore [off1-off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ v.reset(OpARMMOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 - off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpARMMOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [0] {sym} (ADD ptr idx) val mem)
+ // cond: sym == nil
+ // result: (MOVWstoreidx ptr idx val mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVWstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstore [0] {sym} (ADDshiftLL ptr idx [c]) val mem)
+ // cond: sym == nil
+ // result: (MOVWstoreshiftLL ptr idx [c] val mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDshiftLL {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVWstoreshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstore [0] {sym} (ADDshiftRL ptr idx [c]) val mem)
+ // cond: sym == nil
+ // result: (MOVWstoreshiftRL ptr idx [c] val mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDshiftRL {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVWstoreshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstore [0] {sym} (ADDshiftRA ptr idx [c]) val mem)
+ // cond: sym == nil
+ // result: (MOVWstoreshiftRA ptr idx [c] val mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARMADDshiftRA {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(sym == nil) {
+ break
+ }
+ v.reset(OpARMMOVWstoreshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstoreidx ptr (MOVWconst [c]) val mem)
+ // result: (MOVWstore [c] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstore)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx (MOVWconst [c]) ptr val mem)
+ // result: (MOVWstore [c] ptr val mem)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstore)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx ptr (SLLconst idx [c]) val mem)
+ // result: (MOVWstoreshiftLL ptr idx [c] val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ idx := v_1.Args[0]
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstoreshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx (SLLconst idx [c]) ptr val mem)
+ // result: (MOVWstoreshiftLL ptr idx [c] val mem)
+ for {
+ if v_0.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[0]
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstoreshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx ptr (SRLconst idx [c]) val mem)
+ // result: (MOVWstoreshiftRL ptr idx [c] val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ idx := v_1.Args[0]
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstoreshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx (SRLconst idx [c]) ptr val mem)
+ // result: (MOVWstoreshiftRL ptr idx [c] val mem)
+ for {
+ if v_0.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[0]
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstoreshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx ptr (SRAconst idx [c]) val mem)
+ // result: (MOVWstoreshiftRA ptr idx [c] val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ idx := v_1.Args[0]
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstoreshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx (SRAconst idx [c]) ptr val mem)
+ // result: (MOVWstoreshiftRA ptr idx [c] val mem)
+ for {
+ if v_0.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ idx := v_0.Args[0]
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstoreshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWstoreshiftLL(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem)
+ // result: (MOVWstore [int32(uint32(c)<<uint64(d))] ptr val mem)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstore)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) << uint64(d)))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWstoreshiftRA(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstoreshiftRA ptr (MOVWconst [c]) [d] val mem)
+ // result: (MOVWstore [c>>uint64(d)] ptr val mem)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstore)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMOVWstoreshiftRL(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstoreshiftRL ptr (MOVWconst [c]) [d] val mem)
+ // result: (MOVWstore [int32(uint32(c)>>uint64(d))] ptr val mem)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ ptr := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ v.reset(OpARMMOVWstore)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMUL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MUL x (MOVWconst [c]))
+ // cond: int32(c) == -1
+ // result: (RSBconst [0] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(int32(c) == -1) {
+ continue
+ }
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MUL _ (MOVWconst [0]))
+ // result: (MOVWconst [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_1.Op != OpARMMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVWconst [1]))
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVWconst [c]))
+ // cond: isPowerOfTwo32(c)
+ // result: (SLLconst [int32(log32(c))] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(isPowerOfTwo32(c)) {
+ continue
+ }
+ v.reset(OpARMSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(log32(c)))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVWconst [c]))
+ // cond: isPowerOfTwo32(c-1) && c >= 3
+ // result: (ADDshiftLL x x [int32(log32(c-1))])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(isPowerOfTwo32(c-1) && c >= 3) {
+ continue
+ }
+ v.reset(OpARMADDshiftLL)
+ v.AuxInt = int32ToAuxInt(int32(log32(c - 1)))
+ v.AddArg2(x, x)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVWconst [c]))
+ // cond: isPowerOfTwo32(c+1) && c >= 7
+ // result: (RSBshiftLL x x [int32(log32(c+1))])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(isPowerOfTwo32(c+1) && c >= 7) {
+ continue
+ }
+ v.reset(OpARMRSBshiftLL)
+ v.AuxInt = int32ToAuxInt(int32(log32(c + 1)))
+ v.AddArg2(x, x)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVWconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo32(c/3)
+ // result: (SLLconst [int32(log32(c/3))] (ADDshiftLL <x.Type> x x [1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c%3 == 0 && isPowerOfTwo32(c/3)) {
+ continue
+ }
+ v.reset(OpARMSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(log32(c / 3)))
+ v0 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(1)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVWconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo32(c/5)
+ // result: (SLLconst [int32(log32(c/5))] (ADDshiftLL <x.Type> x x [2]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c%5 == 0 && isPowerOfTwo32(c/5)) {
+ continue
+ }
+ v.reset(OpARMSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(log32(c / 5)))
+ v0 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVWconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo32(c/7)
+ // result: (SLLconst [int32(log32(c/7))] (RSBshiftLL <x.Type> x x [3]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c%7 == 0 && isPowerOfTwo32(c/7)) {
+ continue
+ }
+ v.reset(OpARMSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(log32(c / 7)))
+ v0 := b.NewValue0(v.Pos, OpARMRSBshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVWconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo32(c/9)
+ // result: (SLLconst [int32(log32(c/9))] (ADDshiftLL <x.Type> x x [3]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c%9 == 0 && isPowerOfTwo32(c/9)) {
+ continue
+ }
+ v.reset(OpARMSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(log32(c / 9)))
+ v0 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MUL (MOVWconst [c]) (MOVWconst [d]))
+ // result: (MOVWconst [c*d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(c * d)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMMULA(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MULA x (MOVWconst [c]) a)
+ // cond: c == -1
+ // result: (SUB a x)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(c == -1) {
+ break
+ }
+ v.reset(OpARMSUB)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MULA _ (MOVWconst [0]) a)
+ // result: a
+ for {
+ if v_1.Op != OpARMMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ a := v_2
+ v.copyOf(a)
+ return true
+ }
+ // match: (MULA x (MOVWconst [1]) a)
+ // result: (ADD x a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ break
+ }
+ a := v_2
+ v.reset(OpARMADD)
+ v.AddArg2(x, a)
+ return true
+ }
+ // match: (MULA x (MOVWconst [c]) a)
+ // cond: isPowerOfTwo32(c)
+ // result: (ADD (SLLconst <x.Type> [int32(log32(c))] x) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c)))
+ v0.AddArg(x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA x (MOVWconst [c]) a)
+ // cond: isPowerOfTwo32(c-1) && c >= 3
+ // result: (ADD (ADDshiftLL <x.Type> x x [int32(log32(c-1))]) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(isPowerOfTwo32(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c - 1)))
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA x (MOVWconst [c]) a)
+ // cond: isPowerOfTwo32(c+1) && c >= 7
+ // result: (ADD (RSBshiftLL <x.Type> x x [int32(log32(c+1))]) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(isPowerOfTwo32(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMRSBshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c + 1)))
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA x (MOVWconst [c]) a)
+ // cond: c%3 == 0 && isPowerOfTwo32(c/3)
+ // result: (ADD (SLLconst <x.Type> [int32(log32(c/3))] (ADDshiftLL <x.Type> x x [1])) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(c%3 == 0 && isPowerOfTwo32(c/3)) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 3)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(1)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA x (MOVWconst [c]) a)
+ // cond: c%5 == 0 && isPowerOfTwo32(c/5)
+ // result: (ADD (SLLconst <x.Type> [int32(log32(c/5))] (ADDshiftLL <x.Type> x x [2])) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(c%5 == 0 && isPowerOfTwo32(c/5)) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 5)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(2)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA x (MOVWconst [c]) a)
+ // cond: c%7 == 0 && isPowerOfTwo32(c/7)
+ // result: (ADD (SLLconst <x.Type> [int32(log32(c/7))] (RSBshiftLL <x.Type> x x [3])) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(c%7 == 0 && isPowerOfTwo32(c/7)) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 7)))
+ v1 := b.NewValue0(v.Pos, OpARMRSBshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(3)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA x (MOVWconst [c]) a)
+ // cond: c%9 == 0 && isPowerOfTwo32(c/9)
+ // result: (ADD (SLLconst <x.Type> [int32(log32(c/9))] (ADDshiftLL <x.Type> x x [3])) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(c%9 == 0 && isPowerOfTwo32(c/9)) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 9)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(3)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA (MOVWconst [c]) x a)
+ // cond: c == -1
+ // result: (SUB a x)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(c == -1) {
+ break
+ }
+ v.reset(OpARMSUB)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MULA (MOVWconst [0]) _ a)
+ // result: a
+ for {
+ if v_0.Op != OpARMMOVWconst || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ a := v_2
+ v.copyOf(a)
+ return true
+ }
+ // match: (MULA (MOVWconst [1]) x a)
+ // result: (ADD x a)
+ for {
+ if v_0.Op != OpARMMOVWconst || auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_1
+ a := v_2
+ v.reset(OpARMADD)
+ v.AddArg2(x, a)
+ return true
+ }
+ // match: (MULA (MOVWconst [c]) x a)
+ // cond: isPowerOfTwo32(c)
+ // result: (ADD (SLLconst <x.Type> [int32(log32(c))] x) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c)))
+ v0.AddArg(x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA (MOVWconst [c]) x a)
+ // cond: isPowerOfTwo32(c-1) && c >= 3
+ // result: (ADD (ADDshiftLL <x.Type> x x [int32(log32(c-1))]) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(isPowerOfTwo32(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c - 1)))
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA (MOVWconst [c]) x a)
+ // cond: isPowerOfTwo32(c+1) && c >= 7
+ // result: (ADD (RSBshiftLL <x.Type> x x [int32(log32(c+1))]) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(isPowerOfTwo32(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMRSBshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c + 1)))
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA (MOVWconst [c]) x a)
+ // cond: c%3 == 0 && isPowerOfTwo32(c/3)
+ // result: (ADD (SLLconst <x.Type> [int32(log32(c/3))] (ADDshiftLL <x.Type> x x [1])) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(c%3 == 0 && isPowerOfTwo32(c/3)) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 3)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(1)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA (MOVWconst [c]) x a)
+ // cond: c%5 == 0 && isPowerOfTwo32(c/5)
+ // result: (ADD (SLLconst <x.Type> [int32(log32(c/5))] (ADDshiftLL <x.Type> x x [2])) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(c%5 == 0 && isPowerOfTwo32(c/5)) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 5)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(2)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA (MOVWconst [c]) x a)
+ // cond: c%7 == 0 && isPowerOfTwo32(c/7)
+ // result: (ADD (SLLconst <x.Type> [int32(log32(c/7))] (RSBshiftLL <x.Type> x x [3])) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(c%7 == 0 && isPowerOfTwo32(c/7)) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 7)))
+ v1 := b.NewValue0(v.Pos, OpARMRSBshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(3)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA (MOVWconst [c]) x a)
+ // cond: c%9 == 0 && isPowerOfTwo32(c/9)
+ // result: (ADD (SLLconst <x.Type> [int32(log32(c/9))] (ADDshiftLL <x.Type> x x [3])) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(c%9 == 0 && isPowerOfTwo32(c/9)) {
+ break
+ }
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 9)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(3)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULA (MOVWconst [c]) (MOVWconst [d]) a)
+ // result: (ADDconst [c*d] a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c * d)
+ v.AddArg(a)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMULD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULD (NEGD x) y)
+ // cond: objabi.GOARM >= 6
+ // result: (NMULD x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARMNEGD {
+ continue
+ }
+ x := v_0.Args[0]
+ y := v_1
+ if !(objabi.GOARM >= 6) {
+ continue
+ }
+ v.reset(OpARMNMULD)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMMULF(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULF (NEGF x) y)
+ // cond: objabi.GOARM >= 6
+ // result: (NMULF x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARMNEGF {
+ continue
+ }
+ x := v_0.Args[0]
+ y := v_1
+ if !(objabi.GOARM >= 6) {
+ continue
+ }
+ v.reset(OpARMNMULF)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMMULS(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MULS x (MOVWconst [c]) a)
+ // cond: c == -1
+ // result: (ADD a x)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(c == -1) {
+ break
+ }
+ v.reset(OpARMADD)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MULS _ (MOVWconst [0]) a)
+ // result: a
+ for {
+ if v_1.Op != OpARMMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ a := v_2
+ v.copyOf(a)
+ return true
+ }
+ // match: (MULS x (MOVWconst [1]) a)
+ // result: (RSB x a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ break
+ }
+ a := v_2
+ v.reset(OpARMRSB)
+ v.AddArg2(x, a)
+ return true
+ }
+ // match: (MULS x (MOVWconst [c]) a)
+ // cond: isPowerOfTwo32(c)
+ // result: (RSB (SLLconst <x.Type> [int32(log32(c))] x) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c)))
+ v0.AddArg(x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS x (MOVWconst [c]) a)
+ // cond: isPowerOfTwo32(c-1) && c >= 3
+ // result: (RSB (ADDshiftLL <x.Type> x x [int32(log32(c-1))]) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(isPowerOfTwo32(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c - 1)))
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS x (MOVWconst [c]) a)
+ // cond: isPowerOfTwo32(c+1) && c >= 7
+ // result: (RSB (RSBshiftLL <x.Type> x x [int32(log32(c+1))]) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(isPowerOfTwo32(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMRSBshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c + 1)))
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS x (MOVWconst [c]) a)
+ // cond: c%3 == 0 && isPowerOfTwo32(c/3)
+ // result: (RSB (SLLconst <x.Type> [int32(log32(c/3))] (ADDshiftLL <x.Type> x x [1])) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(c%3 == 0 && isPowerOfTwo32(c/3)) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 3)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(1)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS x (MOVWconst [c]) a)
+ // cond: c%5 == 0 && isPowerOfTwo32(c/5)
+ // result: (RSB (SLLconst <x.Type> [int32(log32(c/5))] (ADDshiftLL <x.Type> x x [2])) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(c%5 == 0 && isPowerOfTwo32(c/5)) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 5)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(2)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS x (MOVWconst [c]) a)
+ // cond: c%7 == 0 && isPowerOfTwo32(c/7)
+ // result: (RSB (SLLconst <x.Type> [int32(log32(c/7))] (RSBshiftLL <x.Type> x x [3])) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(c%7 == 0 && isPowerOfTwo32(c/7)) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 7)))
+ v1 := b.NewValue0(v.Pos, OpARMRSBshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(3)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS x (MOVWconst [c]) a)
+ // cond: c%9 == 0 && isPowerOfTwo32(c/9)
+ // result: (RSB (SLLconst <x.Type> [int32(log32(c/9))] (ADDshiftLL <x.Type> x x [3])) a)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ if !(c%9 == 0 && isPowerOfTwo32(c/9)) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 9)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(3)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS (MOVWconst [c]) x a)
+ // cond: c == -1
+ // result: (ADD a x)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(c == -1) {
+ break
+ }
+ v.reset(OpARMADD)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MULS (MOVWconst [0]) _ a)
+ // result: a
+ for {
+ if v_0.Op != OpARMMOVWconst || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ a := v_2
+ v.copyOf(a)
+ return true
+ }
+ // match: (MULS (MOVWconst [1]) x a)
+ // result: (RSB x a)
+ for {
+ if v_0.Op != OpARMMOVWconst || auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_1
+ a := v_2
+ v.reset(OpARMRSB)
+ v.AddArg2(x, a)
+ return true
+ }
+ // match: (MULS (MOVWconst [c]) x a)
+ // cond: isPowerOfTwo32(c)
+ // result: (RSB (SLLconst <x.Type> [int32(log32(c))] x) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c)))
+ v0.AddArg(x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS (MOVWconst [c]) x a)
+ // cond: isPowerOfTwo32(c-1) && c >= 3
+ // result: (RSB (ADDshiftLL <x.Type> x x [int32(log32(c-1))]) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(isPowerOfTwo32(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c - 1)))
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS (MOVWconst [c]) x a)
+ // cond: isPowerOfTwo32(c+1) && c >= 7
+ // result: (RSB (RSBshiftLL <x.Type> x x [int32(log32(c+1))]) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(isPowerOfTwo32(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMRSBshiftLL, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c + 1)))
+ v0.AddArg2(x, x)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS (MOVWconst [c]) x a)
+ // cond: c%3 == 0 && isPowerOfTwo32(c/3)
+ // result: (RSB (SLLconst <x.Type> [int32(log32(c/3))] (ADDshiftLL <x.Type> x x [1])) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(c%3 == 0 && isPowerOfTwo32(c/3)) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 3)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(1)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS (MOVWconst [c]) x a)
+ // cond: c%5 == 0 && isPowerOfTwo32(c/5)
+ // result: (RSB (SLLconst <x.Type> [int32(log32(c/5))] (ADDshiftLL <x.Type> x x [2])) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(c%5 == 0 && isPowerOfTwo32(c/5)) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 5)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(2)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS (MOVWconst [c]) x a)
+ // cond: c%7 == 0 && isPowerOfTwo32(c/7)
+ // result: (RSB (SLLconst <x.Type> [int32(log32(c/7))] (RSBshiftLL <x.Type> x x [3])) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(c%7 == 0 && isPowerOfTwo32(c/7)) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 7)))
+ v1 := b.NewValue0(v.Pos, OpARMRSBshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(3)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS (MOVWconst [c]) x a)
+ // cond: c%9 == 0 && isPowerOfTwo32(c/9)
+ // result: (RSB (SLLconst <x.Type> [int32(log32(c/9))] (ADDshiftLL <x.Type> x x [3])) a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ a := v_2
+ if !(c%9 == 0 && isPowerOfTwo32(c/9)) {
+ break
+ }
+ v.reset(OpARMRSB)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(int32(log32(c / 9)))
+ v1 := b.NewValue0(v.Pos, OpARMADDshiftLL, x.Type)
+ v1.AuxInt = int32ToAuxInt(3)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, a)
+ return true
+ }
+ // match: (MULS (MOVWconst [c]) (MOVWconst [d]) a)
+ // result: (SUBconst [c*d] a)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ a := v_2
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c * d)
+ v.AddArg(a)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMVN(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MVN (MOVWconst [c]))
+ // result: (MOVWconst [^c])
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(^c)
+ return true
+ }
+ // match: (MVN (SLLconst [c] x))
+ // result: (MVNshiftLL x [c])
+ for {
+ if v_0.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMMVNshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MVN (SRLconst [c] x))
+ // result: (MVNshiftRL x [c])
+ for {
+ if v_0.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMMVNshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MVN (SRAconst [c] x))
+ // result: (MVNshiftRA x [c])
+ for {
+ if v_0.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMMVNshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MVN (SLL x y))
+ // result: (MVNshiftLLreg x y)
+ for {
+ if v_0.Op != OpARMSLL {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpARMMVNshiftLLreg)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (MVN (SRL x y))
+ // result: (MVNshiftRLreg x y)
+ for {
+ if v_0.Op != OpARMSRL {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpARMMVNshiftRLreg)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (MVN (SRA x y))
+ // result: (MVNshiftRAreg x y)
+ for {
+ if v_0.Op != OpARMSRA {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpARMMVNshiftRAreg)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMVNshiftLL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MVNshiftLL (MOVWconst [c]) [d])
+ // result: (MOVWconst [^(c<<uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(^(c << uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMVNshiftLLreg(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MVNshiftLLreg x (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (MVNshiftLL x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMMVNshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMVNshiftRA(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MVNshiftRA (MOVWconst [c]) [d])
+ // result: (MOVWconst [int32(c)>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(c) >> uint64(d))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMVNshiftRAreg(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MVNshiftRAreg x (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (MVNshiftRA x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMMVNshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMVNshiftRL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MVNshiftRL (MOVWconst [c]) [d])
+ // result: (MOVWconst [^int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(^int32(uint32(c) >> uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMMVNshiftRLreg(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MVNshiftRLreg x (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (MVNshiftRL x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMMVNshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMNEGD(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEGD (MULD x y))
+ // cond: objabi.GOARM >= 6
+ // result: (NMULD x y)
+ for {
+ if v_0.Op != OpARMMULD {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(objabi.GOARM >= 6) {
+ break
+ }
+ v.reset(OpARMNMULD)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMNEGF(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEGF (MULF x y))
+ // cond: objabi.GOARM >= 6
+ // result: (NMULF x y)
+ for {
+ if v_0.Op != OpARMMULF {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(objabi.GOARM >= 6) {
+ break
+ }
+ v.reset(OpARMNMULF)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMNMULD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (NMULD (NEGD x) y)
+ // result: (MULD x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARMNEGD {
+ continue
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpARMMULD)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMNMULF(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (NMULF (NEGF x) y)
+ // result: (MULF x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARMNEGF {
+ continue
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpARMMULF)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMNotEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NotEqual (FlagConstant [fc]))
+ // result: (MOVWconst [b2i32(fc.ne())])
+ for {
+ if v_0.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(fc.ne()))
+ return true
+ }
+ // match: (NotEqual (InvertFlags x))
+ // result: (NotEqual x)
+ for {
+ if v_0.Op != OpARMInvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARMNotEqual)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (OR x (MOVWconst [c]))
+ // result: (ORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (OR x (SLLconst [c] y))
+ // result: (ORshiftLL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMORshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (OR x (SRLconst [c] y))
+ // result: (ORshiftRL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMORshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (OR x (SRAconst [c] y))
+ // result: (ORshiftRA x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMORshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (OR x (SLL y z))
+ // result: (ORshiftLLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMORshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (OR x (SRL y z))
+ // result: (ORshiftRLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMORshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (OR x (SRA y z))
+ // result: (ORshiftRAreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMORshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (OR x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORconst [c] _)
+ // cond: int32(c)==-1
+ // result: (MOVWconst [-1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ // match: (ORconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [c|d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(c | d)
+ return true
+ }
+ // match: (ORconst [c] (ORconst [d] x))
+ // result: (ORconst [c|d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMORconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(c | d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMORshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ORshiftLL (MOVWconst [c]) x [d])
+ // result: (ORconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ORshiftLL x (MOVWconst [c]) [d])
+ // result: (ORconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: ( ORshiftLL [c] (SRLconst x [32-c]) x)
+ // result: (SRRconst [32-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != 32-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMSRRconst)
+ v.AuxInt = int32ToAuxInt(32 - c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORshiftLL <typ.UInt16> [8] (BFXU <typ.UInt16> [int32(armBFAuxInt(8, 8))] x) x)
+ // result: (REV16 x)
+ for {
+ if v.Type != typ.UInt16 || auxIntToInt32(v.AuxInt) != 8 || v_0.Op != OpARMBFXU || v_0.Type != typ.UInt16 || auxIntToInt32(v_0.AuxInt) != int32(armBFAuxInt(8, 8)) {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMREV16)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORshiftLL <typ.UInt16> [8] (SRLconst <typ.UInt16> [24] (SLLconst [16] x)) x)
+ // cond: objabi.GOARM>=6
+ // result: (REV16 x)
+ for {
+ if v.Type != typ.UInt16 || auxIntToInt32(v.AuxInt) != 8 || v_0.Op != OpARMSRLconst || v_0.Type != typ.UInt16 || auxIntToInt32(v_0.AuxInt) != 24 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMSLLconst || auxIntToInt32(v_0_0.AuxInt) != 16 {
+ break
+ }
+ x := v_0_0.Args[0]
+ if x != v_1 || !(objabi.GOARM >= 6) {
+ break
+ }
+ v.reset(OpARMREV16)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORshiftLL y:(SLLconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ y := v_0
+ if y.Op != OpARMSLLconst || auxIntToInt32(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMORshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ORshiftLLreg (MOVWconst [c]) x y)
+ // result: (ORconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ORshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ORshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMORshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMORshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ORshiftRA (MOVWconst [c]) x [d])
+ // result: (ORconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ORshiftRA x (MOVWconst [c]) [d])
+ // result: (ORconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORshiftRA y:(SRAconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ y := v_0
+ if y.Op != OpARMSRAconst || auxIntToInt32(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMORshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ORshiftRAreg (MOVWconst [c]) x y)
+ // result: (ORconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ORshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ORshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMORshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMORshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ORshiftRL (MOVWconst [c]) x [d])
+ // result: (ORconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ORshiftRL x (MOVWconst [c]) [d])
+ // result: (ORconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: ( ORshiftRL [c] (SLLconst x [32-c]) x)
+ // result: (SRRconst [ c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != 32-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMSRRconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORshiftRL y:(SRLconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ y := v_0
+ if y.Op != OpARMSRLconst || auxIntToInt32(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMORshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ORshiftRLreg (MOVWconst [c]) x y)
+ // result: (ORconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ORshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (ORshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMORshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RSB (MOVWconst [c]) x)
+ // result: (SUBconst [c] x)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RSB x (MOVWconst [c]))
+ // result: (RSBconst [c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RSB x (SLLconst [c] y))
+ // result: (RSBshiftLL x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMRSBshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RSB (SLLconst [c] y) x)
+ // result: (SUBshiftLL x y [c])
+ for {
+ if v_0.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMSUBshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RSB x (SRLconst [c] y))
+ // result: (RSBshiftRL x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMRSBshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RSB (SRLconst [c] y) x)
+ // result: (SUBshiftRL x y [c])
+ for {
+ if v_0.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMSUBshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RSB x (SRAconst [c] y))
+ // result: (RSBshiftRA x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMRSBshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RSB (SRAconst [c] y) x)
+ // result: (SUBshiftRA x y [c])
+ for {
+ if v_0.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMSUBshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (RSB x (SLL y z))
+ // result: (RSBshiftLLreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMRSBshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (RSB (SLL y z) x)
+ // result: (SUBshiftLLreg x y z)
+ for {
+ if v_0.Op != OpARMSLL {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMSUBshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (RSB x (SRL y z))
+ // result: (RSBshiftRLreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMRSBshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (RSB (SRL y z) x)
+ // result: (SUBshiftRLreg x y z)
+ for {
+ if v_0.Op != OpARMSRL {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMSUBshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (RSB x (SRA y z))
+ // result: (RSBshiftRAreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMRSBshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (RSB (SRA y z) x)
+ // result: (SUBshiftRAreg x y z)
+ for {
+ if v_0.Op != OpARMSRA {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMSUBshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (RSB x x)
+ // result: (MOVWconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (RSB (MUL x y) a)
+ // cond: objabi.GOARM == 7
+ // result: (MULS x y a)
+ for {
+ if v_0.Op != OpARMMUL {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ a := v_1
+ if !(objabi.GOARM == 7) {
+ break
+ }
+ v.reset(OpARMMULS)
+ v.AddArg3(x, y, a)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBSshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBSshiftLL (MOVWconst [c]) x [d])
+ // result: (SUBSconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMSUBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBSshiftLL x (MOVWconst [c]) [d])
+ // result: (RSBSconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMRSBSconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBSshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBSshiftLLreg (MOVWconst [c]) x y)
+ // result: (SUBSconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMSUBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBSshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (RSBSshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMRSBSshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBSshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBSshiftRA (MOVWconst [c]) x [d])
+ // result: (SUBSconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMSUBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBSshiftRA x (MOVWconst [c]) [d])
+ // result: (RSBSconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMRSBSconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBSshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBSshiftRAreg (MOVWconst [c]) x y)
+ // result: (SUBSconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMSUBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBSshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (RSBSshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMRSBSshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBSshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBSshiftRL (MOVWconst [c]) x [d])
+ // result: (SUBSconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMSUBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBSshiftRL x (MOVWconst [c]) [d])
+ // result: (RSBSconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMRSBSconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBSshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBSshiftRLreg (MOVWconst [c]) x y)
+ // result: (SUBSconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMSUBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBSshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (RSBSshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMRSBSshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (RSBconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [c-d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(c - d)
+ return true
+ }
+ // match: (RSBconst [c] (RSBconst [d] x))
+ // result: (ADDconst [c-d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMRSBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RSBconst [c] (ADDconst [d] x))
+ // result: (RSBconst [c-d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RSBconst [c] (SUBconst [d] x))
+ // result: (RSBconst [c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBshiftLL (MOVWconst [c]) x [d])
+ // result: (SUBconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBshiftLL x (MOVWconst [c]) [d])
+ // result: (RSBconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RSBshiftLL (SLLconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBshiftLLreg (MOVWconst [c]) x y)
+ // result: (SUBconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (RSBshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMRSBshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBshiftRA (MOVWconst [c]) x [d])
+ // result: (SUBconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBshiftRA x (MOVWconst [c]) [d])
+ // result: (RSBconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RSBshiftRA (SRAconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRAconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBshiftRAreg (MOVWconst [c]) x y)
+ // result: (SUBconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (RSBshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMRSBshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBshiftRL (MOVWconst [c]) x [d])
+ // result: (SUBconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBshiftRL x (MOVWconst [c]) [d])
+ // result: (RSBconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RSBshiftRL (SRLconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSBshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSBshiftRLreg (MOVWconst [c]) x y)
+ // result: (SUBconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (RSBshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (RSBshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMRSBshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSCconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RSCconst [c] (ADDconst [d] x) flags)
+ // result: (RSCconst [c-d] x flags)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ flags := v_1
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg2(x, flags)
+ return true
+ }
+ // match: (RSCconst [c] (SUBconst [d] x) flags)
+ // result: (RSCconst [c+d] x flags)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ flags := v_1
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSCshiftLL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSCshiftLL (MOVWconst [c]) x [d] flags)
+ // result: (SBCconst [c] (SLLconst <x.Type> x [d]) flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (RSCshiftLL x (MOVWconst [c]) [d] flags)
+ // result: (RSCconst x [c<<uint64(d)] flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ flags := v_2
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSCshiftLLreg(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSCshiftLLreg (MOVWconst [c]) x y flags)
+ // result: (SBCconst [c] (SLL <x.Type> x y) flags)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ flags := v_3
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (RSCshiftLLreg x y (MOVWconst [c]) flags)
+ // cond: 0 <= c && c < 32
+ // result: (RSCshiftLL x y [c] flags)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ flags := v_3
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMRSCshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSCshiftRA(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSCshiftRA (MOVWconst [c]) x [d] flags)
+ // result: (SBCconst [c] (SRAconst <x.Type> x [d]) flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (RSCshiftRA x (MOVWconst [c]) [d] flags)
+ // result: (RSCconst x [c>>uint64(d)] flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ flags := v_2
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSCshiftRAreg(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSCshiftRAreg (MOVWconst [c]) x y flags)
+ // result: (SBCconst [c] (SRA <x.Type> x y) flags)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ flags := v_3
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (RSCshiftRAreg x y (MOVWconst [c]) flags)
+ // cond: 0 <= c && c < 32
+ // result: (RSCshiftRA x y [c] flags)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ flags := v_3
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMRSCshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSCshiftRL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSCshiftRL (MOVWconst [c]) x [d] flags)
+ // result: (SBCconst [c] (SRLconst <x.Type> x [d]) flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (RSCshiftRL x (MOVWconst [c]) [d] flags)
+ // result: (RSCconst x [int32(uint32(c)>>uint64(d))] flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ flags := v_2
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMRSCshiftRLreg(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RSCshiftRLreg (MOVWconst [c]) x y flags)
+ // result: (SBCconst [c] (SRL <x.Type> x y) flags)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ flags := v_3
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (RSCshiftRLreg x y (MOVWconst [c]) flags)
+ // cond: 0 <= c && c < 32
+ // result: (RSCshiftRL x y [c] flags)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ flags := v_3
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMRSCshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSBC(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SBC (MOVWconst [c]) x flags)
+ // result: (RSCconst [c] x flags)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, flags)
+ return true
+ }
+ // match: (SBC x (MOVWconst [c]) flags)
+ // result: (SBCconst [c] x flags)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ flags := v_2
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, flags)
+ return true
+ }
+ // match: (SBC x (SLLconst [c] y) flags)
+ // result: (SBCshiftLL x y [c] flags)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMSBCshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ // match: (SBC (SLLconst [c] y) x flags)
+ // result: (RSCshiftLL x y [c] flags)
+ for {
+ if v_0.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ flags := v_2
+ v.reset(OpARMRSCshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ // match: (SBC x (SRLconst [c] y) flags)
+ // result: (SBCshiftRL x y [c] flags)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMSBCshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ // match: (SBC (SRLconst [c] y) x flags)
+ // result: (RSCshiftRL x y [c] flags)
+ for {
+ if v_0.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ flags := v_2
+ v.reset(OpARMRSCshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ // match: (SBC x (SRAconst [c] y) flags)
+ // result: (SBCshiftRA x y [c] flags)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMSBCshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ // match: (SBC (SRAconst [c] y) x flags)
+ // result: (RSCshiftRA x y [c] flags)
+ for {
+ if v_0.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ flags := v_2
+ v.reset(OpARMRSCshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ // match: (SBC x (SLL y z) flags)
+ // result: (SBCshiftLLreg x y z flags)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMSBCshiftLLreg)
+ v.AddArg4(x, y, z, flags)
+ return true
+ }
+ // match: (SBC (SLL y z) x flags)
+ // result: (RSCshiftLLreg x y z flags)
+ for {
+ if v_0.Op != OpARMSLL {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ flags := v_2
+ v.reset(OpARMRSCshiftLLreg)
+ v.AddArg4(x, y, z, flags)
+ return true
+ }
+ // match: (SBC x (SRL y z) flags)
+ // result: (SBCshiftRLreg x y z flags)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMSBCshiftRLreg)
+ v.AddArg4(x, y, z, flags)
+ return true
+ }
+ // match: (SBC (SRL y z) x flags)
+ // result: (RSCshiftRLreg x y z flags)
+ for {
+ if v_0.Op != OpARMSRL {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ flags := v_2
+ v.reset(OpARMRSCshiftRLreg)
+ v.AddArg4(x, y, z, flags)
+ return true
+ }
+ // match: (SBC x (SRA y z) flags)
+ // result: (SBCshiftRAreg x y z flags)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ flags := v_2
+ v.reset(OpARMSBCshiftRAreg)
+ v.AddArg4(x, y, z, flags)
+ return true
+ }
+ // match: (SBC (SRA y z) x flags)
+ // result: (RSCshiftRAreg x y z flags)
+ for {
+ if v_0.Op != OpARMSRA {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ flags := v_2
+ v.reset(OpARMRSCshiftRAreg)
+ v.AddArg4(x, y, z, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSBCconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SBCconst [c] (ADDconst [d] x) flags)
+ // result: (SBCconst [c-d] x flags)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ flags := v_1
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg2(x, flags)
+ return true
+ }
+ // match: (SBCconst [c] (SUBconst [d] x) flags)
+ // result: (SBCconst [c+d] x flags)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ flags := v_1
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSBCshiftLL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SBCshiftLL (MOVWconst [c]) x [d] flags)
+ // result: (RSCconst [c] (SLLconst <x.Type> x [d]) flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (SBCshiftLL x (MOVWconst [c]) [d] flags)
+ // result: (SBCconst x [c<<uint64(d)] flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ flags := v_2
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSBCshiftLLreg(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SBCshiftLLreg (MOVWconst [c]) x y flags)
+ // result: (RSCconst [c] (SLL <x.Type> x y) flags)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ flags := v_3
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (SBCshiftLLreg x y (MOVWconst [c]) flags)
+ // cond: 0 <= c && c < 32
+ // result: (SBCshiftLL x y [c] flags)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ flags := v_3
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSBCshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSBCshiftRA(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SBCshiftRA (MOVWconst [c]) x [d] flags)
+ // result: (RSCconst [c] (SRAconst <x.Type> x [d]) flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (SBCshiftRA x (MOVWconst [c]) [d] flags)
+ // result: (SBCconst x [c>>uint64(d)] flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ flags := v_2
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSBCshiftRAreg(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SBCshiftRAreg (MOVWconst [c]) x y flags)
+ // result: (RSCconst [c] (SRA <x.Type> x y) flags)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ flags := v_3
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (SBCshiftRAreg x y (MOVWconst [c]) flags)
+ // cond: 0 <= c && c < 32
+ // result: (SBCshiftRA x y [c] flags)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ flags := v_3
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSBCshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSBCshiftRL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SBCshiftRL (MOVWconst [c]) x [d] flags)
+ // result: (RSCconst [c] (SRLconst <x.Type> x [d]) flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ flags := v_2
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (SBCshiftRL x (MOVWconst [c]) [d] flags)
+ // result: (SBCconst x [int32(uint32(c)>>uint64(d))] flags)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ flags := v_2
+ v.reset(OpARMSBCconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg2(x, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSBCshiftRLreg(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SBCshiftRLreg (MOVWconst [c]) x y flags)
+ // result: (RSCconst [c] (SRL <x.Type> x y) flags)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ flags := v_3
+ v.reset(OpARMRSCconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, flags)
+ return true
+ }
+ // match: (SBCshiftRLreg x y (MOVWconst [c]) flags)
+ // cond: 0 <= c && c < 32
+ // result: (SBCshiftRL x y [c] flags)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ flags := v_3
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSBCshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg3(x, y, flags)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SLL x (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (SLLconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSLLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSLLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SLLconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [d<<uint64(c)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(d << uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRA x (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (SRAconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSRAcond(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRAcond x _ (FlagConstant [fc]))
+ // cond: fc.uge()
+ // result: (SRAconst x [31])
+ for {
+ x := v_0
+ if v_2.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_2.AuxInt)
+ if !(fc.uge()) {
+ break
+ }
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAcond x y (FlagConstant [fc]))
+ // cond: fc.ult()
+ // result: (SRA x y)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMFlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_2.AuxInt)
+ if !(fc.ult()) {
+ break
+ }
+ v.reset(OpARMSRA)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSRAconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRAconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [d>>uint64(c)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(d >> uint64(c))
+ return true
+ }
+ // match: (SRAconst (SLLconst x [c]) [d])
+ // cond: objabi.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31
+ // result: (BFX [(d-c)|(32-d)<<8] x)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(objabi.GOARM == 7 && uint64(d) >= uint64(c) && uint64(d) <= 31) {
+ break
+ }
+ v.reset(OpARMBFX)
+ v.AuxInt = int32ToAuxInt((d - c) | (32-d)<<8)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRL x (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (SRLconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSRLconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSRLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRLconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [int32(uint32(d)>>uint64(c))])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(d) >> uint64(c)))
+ return true
+ }
+ // match: (SRLconst (SLLconst x [c]) [d])
+ // cond: objabi.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31
+ // result: (BFXU [(d-c)|(32-d)<<8] x)
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(objabi.GOARM == 7 && uint64(d) >= uint64(c) && uint64(d) <= 31) {
+ break
+ }
+ v.reset(OpARMBFXU)
+ v.AuxInt = int32ToAuxInt((d - c) | (32-d)<<8)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUB (MOVWconst [c]) x)
+ // result: (RSBconst [c] x)
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB x (MOVWconst [c]))
+ // result: (SUBconst [c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB x (SLLconst [c] y))
+ // result: (SUBshiftLL x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMSUBshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUB (SLLconst [c] y) x)
+ // result: (RSBshiftLL x y [c])
+ for {
+ if v_0.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUB x (SRLconst [c] y))
+ // result: (SUBshiftRL x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMSUBshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUB (SRLconst [c] y) x)
+ // result: (RSBshiftRL x y [c])
+ for {
+ if v_0.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUB x (SRAconst [c] y))
+ // result: (SUBshiftRA x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMSUBshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUB (SRAconst [c] y) x)
+ // result: (RSBshiftRA x y [c])
+ for {
+ if v_0.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUB x (SLL y z))
+ // result: (SUBshiftLLreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMSUBshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUB (SLL y z) x)
+ // result: (RSBshiftLLreg x y z)
+ for {
+ if v_0.Op != OpARMSLL {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUB x (SRL y z))
+ // result: (SUBshiftRLreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMSUBshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUB (SRL y z) x)
+ // result: (RSBshiftRLreg x y z)
+ for {
+ if v_0.Op != OpARMSRL {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUB x (SRA y z))
+ // result: (SUBshiftRAreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMSUBshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUB (SRA y z) x)
+ // result: (RSBshiftRAreg x y z)
+ for {
+ if v_0.Op != OpARMSRA {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUB x x)
+ // result: (MOVWconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SUB a (MUL x y))
+ // cond: objabi.GOARM == 7
+ // result: (MULS x y a)
+ for {
+ a := v_0
+ if v_1.Op != OpARMMUL {
+ break
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ if !(objabi.GOARM == 7) {
+ break
+ }
+ v.reset(OpARMMULS)
+ v.AddArg3(x, y, a)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBD a (MULD x y))
+ // cond: a.Uses == 1 && objabi.GOARM >= 6
+ // result: (MULSD a x y)
+ for {
+ a := v_0
+ if v_1.Op != OpARMMULD {
+ break
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ if !(a.Uses == 1 && objabi.GOARM >= 6) {
+ break
+ }
+ v.reset(OpARMMULSD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (SUBD a (NMULD x y))
+ // cond: a.Uses == 1 && objabi.GOARM >= 6
+ // result: (MULAD a x y)
+ for {
+ a := v_0
+ if v_1.Op != OpARMNMULD {
+ break
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ if !(a.Uses == 1 && objabi.GOARM >= 6) {
+ break
+ }
+ v.reset(OpARMMULAD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBF(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBF a (MULF x y))
+ // cond: a.Uses == 1 && objabi.GOARM >= 6
+ // result: (MULSF a x y)
+ for {
+ a := v_0
+ if v_1.Op != OpARMMULF {
+ break
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ if !(a.Uses == 1 && objabi.GOARM >= 6) {
+ break
+ }
+ v.reset(OpARMMULSF)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (SUBF a (NMULF x y))
+ // cond: a.Uses == 1 && objabi.GOARM >= 6
+ // result: (MULAF a x y)
+ for {
+ a := v_0
+ if v_1.Op != OpARMNMULF {
+ break
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ if !(a.Uses == 1 && objabi.GOARM >= 6) {
+ break
+ }
+ v.reset(OpARMMULAF)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBS x (MOVWconst [c]))
+ // result: (SUBSconst [c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMSUBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBS x (SLLconst [c] y))
+ // result: (SUBSshiftLL x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMSUBSshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUBS (SLLconst [c] y) x)
+ // result: (RSBSshiftLL x y [c])
+ for {
+ if v_0.Op != OpARMSLLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBSshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUBS x (SRLconst [c] y))
+ // result: (SUBSshiftRL x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMSUBSshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUBS (SRLconst [c] y) x)
+ // result: (RSBSshiftRL x y [c])
+ for {
+ if v_0.Op != OpARMSRLconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBSshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUBS x (SRAconst [c] y))
+ // result: (SUBSshiftRA x y [c])
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMSUBSshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUBS (SRAconst [c] y) x)
+ // result: (RSBSshiftRA x y [c])
+ for {
+ if v_0.Op != OpARMSRAconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBSshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUBS x (SLL y z))
+ // result: (SUBSshiftLLreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMSUBSshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUBS (SLL y z) x)
+ // result: (RSBSshiftLLreg x y z)
+ for {
+ if v_0.Op != OpARMSLL {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBSshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUBS x (SRL y z))
+ // result: (SUBSshiftRLreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMSUBSshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUBS (SRL y z) x)
+ // result: (RSBSshiftRLreg x y z)
+ for {
+ if v_0.Op != OpARMSRL {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBSshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUBS x (SRA y z))
+ // result: (SUBSshiftRAreg x y z)
+ for {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMSUBSshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (SUBS (SRA y z) x)
+ // result: (RSBSshiftRAreg x y z)
+ for {
+ if v_0.Op != OpARMSRA {
+ break
+ }
+ z := v_0.Args[1]
+ y := v_0.Args[0]
+ x := v_1
+ v.reset(OpARMRSBSshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBSshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBSshiftLL (MOVWconst [c]) x [d])
+ // result: (RSBSconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMRSBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBSshiftLL x (MOVWconst [c]) [d])
+ // result: (SUBSconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMSUBSconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBSshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBSshiftLLreg (MOVWconst [c]) x y)
+ // result: (RSBSconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMRSBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBSshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (SUBSshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSUBSshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBSshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBSshiftRA (MOVWconst [c]) x [d])
+ // result: (RSBSconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMRSBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBSshiftRA x (MOVWconst [c]) [d])
+ // result: (SUBSconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMSUBSconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBSshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBSshiftRAreg (MOVWconst [c]) x y)
+ // result: (RSBSconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMRSBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBSshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (SUBSshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSUBSshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBSshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBSshiftRL (MOVWconst [c]) x [d])
+ // result: (RSBSconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMRSBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBSshiftRL x (MOVWconst [c]) [d])
+ // result: (SUBSconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMSUBSconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBSshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBSshiftRLreg (MOVWconst [c]) x y)
+ // result: (RSBSconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMRSBSconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBSshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (SUBSshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSUBSshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SUBconst [off1] (MOVWaddr [off2] {sym} ptr))
+ // result: (MOVWaddr [off2-off1] {sym} ptr)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ v.reset(OpARMMOVWaddr)
+ v.AuxInt = int32ToAuxInt(off2 - off1)
+ v.Aux = symToAux(sym)
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (SUBconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUBconst [c] x)
+ // cond: !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c))
+ // result: (ADDconst [-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(!isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c))) {
+ break
+ }
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBconst [c] x)
+ // cond: objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && uint32(-c)<=0xffff
+ // result: (ADDconst [-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(objabi.GOARM == 7 && !isARMImmRot(uint32(c)) && uint32(c) > 0xffff && uint32(-c) <= 0xffff) {
+ break
+ }
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [d-c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(d - c)
+ return true
+ }
+ // match: (SUBconst [c] (SUBconst [d] x))
+ // result: (ADDconst [-c-d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(-c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBconst [c] (ADDconst [d] x))
+ // result: (ADDconst [-c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMADDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(-c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBconst [c] (RSBconst [d] x))
+ // result: (RSBconst [-c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMRSBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(-c + d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBshiftLL (MOVWconst [c]) x [d])
+ // result: (RSBconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBshiftLL x (MOVWconst [c]) [d])
+ // result: (SUBconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBshiftLL (SLLconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBshiftLLreg (MOVWconst [c]) x y)
+ // result: (RSBconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (SUBshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSUBshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBshiftRA (MOVWconst [c]) x [d])
+ // result: (RSBconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBshiftRA x (MOVWconst [c]) [d])
+ // result: (SUBconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBshiftRA (SRAconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRAconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBshiftRAreg (MOVWconst [c]) x y)
+ // result: (RSBconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (SUBshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSUBshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBshiftRL (MOVWconst [c]) x [d])
+ // result: (RSBconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBshiftRL x (MOVWconst [c]) [d])
+ // result: (SUBconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBshiftRL (SRLconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMSUBshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBshiftRLreg (MOVWconst [c]) x y)
+ // result: (RSBconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (SUBshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMSUBshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTEQ(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (TEQ x (MOVWconst [c]))
+ // result: (TEQconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMTEQconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (TEQ x (SLLconst [c] y))
+ // result: (TEQshiftLL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMTEQshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (TEQ x (SRLconst [c] y))
+ // result: (TEQshiftRL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMTEQshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (TEQ x (SRAconst [c] y))
+ // result: (TEQshiftRA x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMTEQshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (TEQ x (SLL y z))
+ // result: (TEQshiftLLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMTEQshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (TEQ x (SRL y z))
+ // result: (TEQshiftRLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMTEQshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (TEQ x (SRA y z))
+ // result: (TEQshiftRAreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMTEQshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMTEQconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (TEQconst (MOVWconst [x]) [y])
+ // result: (FlagConstant [logicFlags32(x^y)])
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMFlagConstant)
+ v.AuxInt = flagConstantToAuxInt(logicFlags32(x ^ y))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTEQshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TEQshiftLL (MOVWconst [c]) x [d])
+ // result: (TEQconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMTEQconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TEQshiftLL x (MOVWconst [c]) [d])
+ // result: (TEQconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMTEQconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTEQshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TEQshiftLLreg (MOVWconst [c]) x y)
+ // result: (TEQconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMTEQconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TEQshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (TEQshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMTEQshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTEQshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TEQshiftRA (MOVWconst [c]) x [d])
+ // result: (TEQconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMTEQconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TEQshiftRA x (MOVWconst [c]) [d])
+ // result: (TEQconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMTEQconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTEQshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TEQshiftRAreg (MOVWconst [c]) x y)
+ // result: (TEQconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMTEQconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TEQshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (TEQshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMTEQshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTEQshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TEQshiftRL (MOVWconst [c]) x [d])
+ // result: (TEQconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMTEQconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TEQshiftRL x (MOVWconst [c]) [d])
+ // result: (TEQconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMTEQconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTEQshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TEQshiftRLreg (MOVWconst [c]) x y)
+ // result: (TEQconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMTEQconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TEQshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (TEQshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMTEQshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTST(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (TST x (MOVWconst [c]))
+ // result: (TSTconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMTSTconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (TST x (SLLconst [c] y))
+ // result: (TSTshiftLL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMTSTshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (TST x (SRLconst [c] y))
+ // result: (TSTshiftRL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMTSTshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (TST x (SRAconst [c] y))
+ // result: (TSTshiftRA x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMTSTshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (TST x (SLL y z))
+ // result: (TSTshiftLLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMTSTshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (TST x (SRL y z))
+ // result: (TSTshiftRLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMTSTshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (TST x (SRA y z))
+ // result: (TSTshiftRAreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMTSTshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM_OpARMTSTconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (TSTconst (MOVWconst [x]) [y])
+ // result: (FlagConstant [logicFlags32(x&y)])
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMFlagConstant)
+ v.AuxInt = flagConstantToAuxInt(logicFlags32(x & y))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTSTshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TSTshiftLL (MOVWconst [c]) x [d])
+ // result: (TSTconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMTSTconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftLL x (MOVWconst [c]) [d])
+ // result: (TSTconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMTSTconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTSTshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TSTshiftLLreg (MOVWconst [c]) x y)
+ // result: (TSTconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMTSTconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (TSTshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMTSTshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTSTshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TSTshiftRA (MOVWconst [c]) x [d])
+ // result: (TSTconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMTSTconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftRA x (MOVWconst [c]) [d])
+ // result: (TSTconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMTSTconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTSTshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TSTshiftRAreg (MOVWconst [c]) x y)
+ // result: (TSTconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMTSTconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (TSTshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMTSTshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTSTshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TSTshiftRL (MOVWconst [c]) x [d])
+ // result: (TSTconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMTSTconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftRL x (MOVWconst [c]) [d])
+ // result: (TSTconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMTSTconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMTSTshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TSTshiftRLreg (MOVWconst [c]) x y)
+ // result: (TSTconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMTSTconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (TSTshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMTSTshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMXOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XOR x (MOVWconst [c]))
+ // result: (XORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR x (SLLconst [c] y))
+ // result: (XORshiftLL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMXORshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR x (SRLconst [c] y))
+ // result: (XORshiftRL x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRLconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMXORshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR x (SRAconst [c] y))
+ // result: (XORshiftRA x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRAconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMXORshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR x (SRRconst [c] y))
+ // result: (XORshiftRR x y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRRconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ v.reset(OpARMXORshiftRR)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR x (SLL y z))
+ // result: (XORshiftLLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSLL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMXORshiftLLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (XOR x (SRL y z))
+ // result: (XORshiftRLreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRL {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMXORshiftRLreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (XOR x (SRA y z))
+ // result: (XORshiftRAreg x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARMSRA {
+ continue
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARMXORshiftRAreg)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (XOR x x)
+ // result: (MOVWconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMXORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (XORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (XORconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [c^d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(c ^ d)
+ return true
+ }
+ // match: (XORconst [c] (XORconst [d] x))
+ // result: (XORconst [c^d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMXORconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c ^ d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMXORshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (XORshiftLL (MOVWconst [c]) x [d])
+ // result: (XORconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XORshiftLL x (MOVWconst [c]) [d])
+ // result: (XORconst x [c<<uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftLL [c] (SRLconst x [32-c]) x)
+ // result: (SRRconst [32-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != 32-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMSRRconst)
+ v.AuxInt = int32ToAuxInt(32 - c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftLL <typ.UInt16> [8] (BFXU <typ.UInt16> [int32(armBFAuxInt(8, 8))] x) x)
+ // result: (REV16 x)
+ for {
+ if v.Type != typ.UInt16 || auxIntToInt32(v.AuxInt) != 8 || v_0.Op != OpARMBFXU || v_0.Type != typ.UInt16 || auxIntToInt32(v_0.AuxInt) != int32(armBFAuxInt(8, 8)) {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMREV16)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftLL <typ.UInt16> [8] (SRLconst <typ.UInt16> [24] (SLLconst [16] x)) x)
+ // cond: objabi.GOARM>=6
+ // result: (REV16 x)
+ for {
+ if v.Type != typ.UInt16 || auxIntToInt32(v.AuxInt) != 8 || v_0.Op != OpARMSRLconst || v_0.Type != typ.UInt16 || auxIntToInt32(v_0.AuxInt) != 24 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMSLLconst || auxIntToInt32(v_0_0.AuxInt) != 16 {
+ break
+ }
+ x := v_0_0.Args[0]
+ if x != v_1 || !(objabi.GOARM >= 6) {
+ break
+ }
+ v.reset(OpARMREV16)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftLL (SLLconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMXORshiftLLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORshiftLLreg (MOVWconst [c]) x y)
+ // result: (XORconst [c] (SLL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XORshiftLLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (XORshiftLL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMXORshiftLL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMXORshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORshiftRA (MOVWconst [c]) x [d])
+ // result: (XORconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRAconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XORshiftRA x (MOVWconst [c]) [d])
+ // result: (XORconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftRA (SRAconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRAconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMXORshiftRAreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORshiftRAreg (MOVWconst [c]) x y)
+ // result: (XORconst [c] (SRA <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRA, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XORshiftRAreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (XORshiftRA x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMXORshiftRA)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMXORshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORshiftRL (MOVWconst [c]) x [d])
+ // result: (XORconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XORshiftRL x (MOVWconst [c]) [d])
+ // result: (XORconst x [int32(uint32(c)>>uint64(d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftRL [c] (SLLconst x [32-c]) x)
+ // result: (SRRconst [ c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != 32-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMSRRconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftRL (SRLconst x [c]) x [c])
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMXORshiftRLreg(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORshiftRLreg (MOVWconst [c]) x y)
+ // result: (XORconst [c] (SRL <x.Type> x y))
+ for {
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XORshiftRLreg x y (MOVWconst [c]))
+ // cond: 0 <= c && c < 32
+ // result: (XORshiftRL x y [c])
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(0 <= c && c < 32) {
+ break
+ }
+ v.reset(OpARMXORshiftRL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpARMXORshiftRR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORshiftRR (MOVWconst [c]) x [d])
+ // result: (XORconst [c] (SRRconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARMSRRconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XORshiftRR x (MOVWconst [c]) [d])
+ // result: (XORconst x [int32(uint32(c)>>uint64(d)|uint32(c)<<uint64(32-d))])
+ for {
+ d := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c)>>uint64(d) | uint32(c)<<uint64(32-d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Addr {sym} base)
+ // result: (MOVWaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpARMMOVWaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueARM_OpAvg32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Avg32u <t> x y)
+ // result: (ADD (SRLconst <t> (SUB <t> x y) [1]) y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARMADD)
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, t)
+ v0.AuxInt = int32ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpARMSUB, t)
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueARM_OpBitLen32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (BitLen32 <t> x)
+ // result: (RSBconst [32] (CLZ <t> x))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpARMCLZ, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpBswap32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Bswap32 <t> x)
+ // cond: objabi.GOARM==5
+ // result: (XOR <t> (SRLconst <t> (BICconst <t> (XOR <t> x (SRRconst <t> [16] x)) [0xff0000]) [8]) (SRRconst <t> x [8]))
+ for {
+ t := v.Type
+ x := v_0
+ if !(objabi.GOARM == 5) {
+ break
+ }
+ v.reset(OpARMXOR)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpARMSRLconst, t)
+ v0.AuxInt = int32ToAuxInt(8)
+ v1 := b.NewValue0(v.Pos, OpARMBICconst, t)
+ v1.AuxInt = int32ToAuxInt(0xff0000)
+ v2 := b.NewValue0(v.Pos, OpARMXOR, t)
+ v3 := b.NewValue0(v.Pos, OpARMSRRconst, t)
+ v3.AuxInt = int32ToAuxInt(16)
+ v3.AddArg(x)
+ v2.AddArg2(x, v3)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpARMSRRconst, t)
+ v4.AuxInt = int32ToAuxInt(8)
+ v4.AddArg(x)
+ v.AddArg2(v0, v4)
+ return true
+ }
+ // match: (Bswap32 x)
+ // cond: objabi.GOARM>=6
+ // result: (REV x)
+ for {
+ x := v_0
+ if !(objabi.GOARM >= 6) {
+ break
+ }
+ v.reset(OpARMREV)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpConst16(v *Value) bool {
+ // match: (Const16 [val])
+ // result: (MOVWconst [int32(val)])
+ for {
+ val := auxIntToInt16(v.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(val))
+ return true
+ }
+}
+func rewriteValueARM_OpConst32(v *Value) bool {
+ // match: (Const32 [val])
+ // result: (MOVWconst [int32(val)])
+ for {
+ val := auxIntToInt32(v.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(val))
+ return true
+ }
+}
+func rewriteValueARM_OpConst32F(v *Value) bool {
+ // match: (Const32F [val])
+ // result: (MOVFconst [float64(val)])
+ for {
+ val := auxIntToFloat32(v.AuxInt)
+ v.reset(OpARMMOVFconst)
+ v.AuxInt = float64ToAuxInt(float64(val))
+ return true
+ }
+}
+func rewriteValueARM_OpConst64F(v *Value) bool {
+ // match: (Const64F [val])
+ // result: (MOVDconst [float64(val)])
+ for {
+ val := auxIntToFloat64(v.AuxInt)
+ v.reset(OpARMMOVDconst)
+ v.AuxInt = float64ToAuxInt(float64(val))
+ return true
+ }
+}
+func rewriteValueARM_OpConst8(v *Value) bool {
+ // match: (Const8 [val])
+ // result: (MOVWconst [int32(val)])
+ for {
+ val := auxIntToInt8(v.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(val))
+ return true
+ }
+}
+func rewriteValueARM_OpConstBool(v *Value) bool {
+ // match: (ConstBool [b])
+ // result: (MOVWconst [b2i32(b)])
+ for {
+ b := auxIntToBool(v.AuxInt)
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(b))
+ return true
+ }
+}
+func rewriteValueARM_OpConstNil(v *Value) bool {
+ // match: (ConstNil)
+ // result: (MOVWconst [0])
+ for {
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+}
+func rewriteValueARM_OpCtz16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz16 <t> x)
+ // cond: objabi.GOARM<=6
+ // result: (RSBconst [32] (CLZ <t> (SUBconst <typ.UInt32> (AND <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x) (RSBconst <typ.UInt32> [0] (ORconst <typ.UInt32> [0x10000] x))) [1])))
+ for {
+ t := v.Type
+ x := v_0
+ if !(objabi.GOARM <= 6) {
+ break
+ }
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpARMCLZ, t)
+ v1 := b.NewValue0(v.Pos, OpARMSUBconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpARMAND, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpARMORconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(0x10000)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpARMRSBconst, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(0)
+ v4.AddArg(v3)
+ v2.AddArg2(v3, v4)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Ctz16 <t> x)
+ // cond: objabi.GOARM==7
+ // result: (CLZ <t> (RBIT <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x)))
+ for {
+ t := v.Type
+ x := v_0
+ if !(objabi.GOARM == 7) {
+ break
+ }
+ v.reset(OpARMCLZ)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpARMRBIT, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpARMORconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0x10000)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpCtz32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Ctz32 <t> x)
+ // cond: objabi.GOARM<=6
+ // result: (RSBconst [32] (CLZ <t> (SUBconst <t> (AND <t> x (RSBconst <t> [0] x)) [1])))
+ for {
+ t := v.Type
+ x := v_0
+ if !(objabi.GOARM <= 6) {
+ break
+ }
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpARMCLZ, t)
+ v1 := b.NewValue0(v.Pos, OpARMSUBconst, t)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpARMAND, t)
+ v3 := b.NewValue0(v.Pos, OpARMRSBconst, t)
+ v3.AuxInt = int32ToAuxInt(0)
+ v3.AddArg(x)
+ v2.AddArg2(x, v3)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Ctz32 <t> x)
+ // cond: objabi.GOARM==7
+ // result: (CLZ <t> (RBIT <t> x))
+ for {
+ t := v.Type
+ x := v_0
+ if !(objabi.GOARM == 7) {
+ break
+ }
+ v.reset(OpARMCLZ)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpARMRBIT, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpCtz8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz8 <t> x)
+ // cond: objabi.GOARM<=6
+ // result: (RSBconst [32] (CLZ <t> (SUBconst <typ.UInt32> (AND <typ.UInt32> (ORconst <typ.UInt32> [0x100] x) (RSBconst <typ.UInt32> [0] (ORconst <typ.UInt32> [0x100] x))) [1])))
+ for {
+ t := v.Type
+ x := v_0
+ if !(objabi.GOARM <= 6) {
+ break
+ }
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpARMCLZ, t)
+ v1 := b.NewValue0(v.Pos, OpARMSUBconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpARMAND, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpARMORconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(0x100)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpARMRSBconst, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(0)
+ v4.AddArg(v3)
+ v2.AddArg2(v3, v4)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Ctz8 <t> x)
+ // cond: objabi.GOARM==7
+ // result: (CLZ <t> (RBIT <typ.UInt32> (ORconst <typ.UInt32> [0x100] x)))
+ for {
+ t := v.Type
+ x := v_0
+ if !(objabi.GOARM == 7) {
+ break
+ }
+ v.reset(OpARMCLZ)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpARMRBIT, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpARMORconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0x100)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpDiv16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16 x y)
+ // result: (Div32 (SignExt16to32 x) (SignExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpDiv32)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpDiv16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16u x y)
+ // result: (Div32u (ZeroExt16to32 x) (ZeroExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpDiv32u)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpDiv32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32 x y)
+ // result: (SUB (XOR <typ.UInt32> (Select0 <typ.UInt32> (CALLudiv (SUB <typ.UInt32> (XOR x <typ.UInt32> (Signmask x)) (Signmask x)) (SUB <typ.UInt32> (XOR y <typ.UInt32> (Signmask y)) (Signmask y)))) (Signmask (XOR <typ.UInt32> x y))) (Signmask (XOR <typ.UInt32> x y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSUB)
+ v0 := b.NewValue0(v.Pos, OpARMXOR, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpSelect0, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpARMCALLudiv, types.NewTuple(typ.UInt32, typ.UInt32))
+ v3 := b.NewValue0(v.Pos, OpARMSUB, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpARMXOR, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpSignmask, typ.Int32)
+ v5.AddArg(x)
+ v4.AddArg2(x, v5)
+ v3.AddArg2(v4, v5)
+ v6 := b.NewValue0(v.Pos, OpARMSUB, typ.UInt32)
+ v7 := b.NewValue0(v.Pos, OpARMXOR, typ.UInt32)
+ v8 := b.NewValue0(v.Pos, OpSignmask, typ.Int32)
+ v8.AddArg(y)
+ v7.AddArg2(y, v8)
+ v6.AddArg2(v7, v8)
+ v2.AddArg2(v3, v6)
+ v1.AddArg(v2)
+ v9 := b.NewValue0(v.Pos, OpSignmask, typ.Int32)
+ v10 := b.NewValue0(v.Pos, OpARMXOR, typ.UInt32)
+ v10.AddArg2(x, y)
+ v9.AddArg(v10)
+ v0.AddArg2(v1, v9)
+ v.AddArg2(v0, v9)
+ return true
+ }
+}
+func rewriteValueARM_OpDiv32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32u x y)
+ // result: (Select0 <typ.UInt32> (CALLudiv x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v.Type = typ.UInt32
+ v0 := b.NewValue0(v.Pos, OpARMCALLudiv, types.NewTuple(typ.UInt32, typ.UInt32))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 x y)
+ // result: (Div32 (SignExt8to32 x) (SignExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpDiv32)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u x y)
+ // result: (Div32u (ZeroExt8to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpDiv32u)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq16 x y)
+ // result: (Equal (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32 x y)
+ // result: (Equal (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpEq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32F x y)
+ // result: (Equal (CMPF x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMPF, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpEq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64F x y)
+ // result: (Equal (CMPD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMPD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq8 x y)
+ // result: (Equal (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpEqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqB x y)
+ // result: (XORconst [1] (XOR <typ.Bool> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpARMXOR, typ.Bool)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpEqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (EqPtr x y)
+ // result: (Equal (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpFMA(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMA x y z)
+ // result: (FMULAD z x y)
+ for {
+ x := v_0
+ y := v_1
+ z := v_2
+ v.reset(OpARMFMULAD)
+ v.AddArg3(z, x, y)
+ return true
+ }
+}
+func rewriteValueARM_OpIsInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsInBounds idx len)
+ // result: (LessThanU (CMP idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpARMLessThanU)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsNonNil ptr)
+ // result: (NotEqual (CMPconst [0] ptr))
+ for {
+ ptr := v_0
+ v.reset(OpARMNotEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(ptr)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpIsSliceInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsSliceInBounds idx len)
+ // result: (LessEqualU (CMP idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpARMLessEqualU)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16 x y)
+ // result: (LessEqual (CMP (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16U x y)
+ // result: (LessEqualU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessEqualU)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32 x y)
+ // result: (LessEqual (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32F x y)
+ // result: (GreaterEqual (CMPF y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMGreaterEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMPF, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32U x y)
+ // result: (LessEqualU (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessEqualU)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64F x y)
+ // result: (GreaterEqual (CMPD y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMGreaterEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMPD, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8 x y)
+ // result: (LessEqual (CMP (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8U x y)
+ // result: (LessEqualU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessEqualU)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16 x y)
+ // result: (LessThan (CMP (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessThan)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16U x y)
+ // result: (LessThanU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessThanU)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32 x y)
+ // result: (LessThan (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessThan)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLess32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32F x y)
+ // result: (GreaterThan (CMPF y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMGreaterThan)
+ v0 := b.NewValue0(v.Pos, OpARMCMPF, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32U x y)
+ // result: (LessThanU (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessThanU)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLess64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64F x y)
+ // result: (GreaterThan (CMPD y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMGreaterThan)
+ v0 := b.NewValue0(v.Pos, OpARMCMPD, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8 x y)
+ // result: (LessThan (CMP (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessThan)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8U x y)
+ // result: (LessThanU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMLessThanU)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Load <t> ptr mem)
+ // cond: t.IsBoolean()
+ // result: (MOVBUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsBoolean()) {
+ break
+ }
+ v.reset(OpARMMOVBUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is8BitInt(t) && isSigned(t))
+ // result: (MOVBload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpARMMOVBload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is8BitInt(t) && !isSigned(t))
+ // result: (MOVBUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpARMMOVBUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is16BitInt(t) && isSigned(t))
+ // result: (MOVHload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpARMMOVHload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is16BitInt(t) && !isSigned(t))
+ // result: (MOVHUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpARMMOVHUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is32BitInt(t) || isPtr(t))
+ // result: (MOVWload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpARMMOVWload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitFloat(t)
+ // result: (MOVFload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(OpARMMOVFload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitFloat(t)
+ // result: (MOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(OpARMMOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpLocalAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LocalAddr {sym} base _)
+ // result: (MOVWaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpARMMOVWaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueARM_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x16 x y)
+ // result: (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(256)
+ v2.AddArg(v1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueARM_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x32 x y)
+ // result: (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v1.AuxInt = int32ToAuxInt(256)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Lsh16x64 x (Const64 [c]))
+ // cond: uint64(c) < 16
+ // result: (SLLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 16) {
+ break
+ }
+ v.reset(OpARMSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh16x64 _ (Const64 [c]))
+ // cond: uint64(c) >= 16
+ // result: (Const16 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x8 x y)
+ // result: (SLL x (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSLL)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x16 x y)
+ // result: (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(256)
+ v2.AddArg(v1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueARM_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x32 x y)
+ // result: (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v1.AuxInt = int32ToAuxInt(256)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Lsh32x64 x (Const64 [c]))
+ // cond: uint64(c) < 32
+ // result: (SLLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 32) {
+ break
+ }
+ v.reset(OpARMSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh32x64 _ (Const64 [c]))
+ // cond: uint64(c) >= 32
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x8 x y)
+ // result: (SLL x (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSLL)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x16 x y)
+ // result: (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(256)
+ v2.AddArg(v1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueARM_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x32 x y)
+ // result: (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSLL, x.Type)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v1.AuxInt = int32ToAuxInt(256)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Lsh8x64 x (Const64 [c]))
+ // cond: uint64(c) < 8
+ // result: (SLLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 8) {
+ break
+ }
+ v.reset(OpARMSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh8x64 _ (Const64 [c]))
+ // cond: uint64(c) >= 8
+ // result: (Const8 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x8 x y)
+ // result: (SLL x (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSLL)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM_OpMod16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16 x y)
+ // result: (Mod32 (SignExt16to32 x) (SignExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMod32)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpMod16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16u x y)
+ // result: (Mod32u (ZeroExt16to32 x) (ZeroExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMod32u)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpMod32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32 x y)
+ // result: (SUB (XOR <typ.UInt32> (Select1 <typ.UInt32> (CALLudiv (SUB <typ.UInt32> (XOR <typ.UInt32> x (Signmask x)) (Signmask x)) (SUB <typ.UInt32> (XOR <typ.UInt32> y (Signmask y)) (Signmask y)))) (Signmask x)) (Signmask x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSUB)
+ v0 := b.NewValue0(v.Pos, OpARMXOR, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpSelect1, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpARMCALLudiv, types.NewTuple(typ.UInt32, typ.UInt32))
+ v3 := b.NewValue0(v.Pos, OpARMSUB, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpARMXOR, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpSignmask, typ.Int32)
+ v5.AddArg(x)
+ v4.AddArg2(x, v5)
+ v3.AddArg2(v4, v5)
+ v6 := b.NewValue0(v.Pos, OpARMSUB, typ.UInt32)
+ v7 := b.NewValue0(v.Pos, OpARMXOR, typ.UInt32)
+ v8 := b.NewValue0(v.Pos, OpSignmask, typ.Int32)
+ v8.AddArg(y)
+ v7.AddArg2(y, v8)
+ v6.AddArg2(v7, v8)
+ v2.AddArg2(v3, v6)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, v5)
+ v.AddArg2(v0, v5)
+ return true
+ }
+}
+func rewriteValueARM_OpMod32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32u x y)
+ // result: (Select1 <typ.UInt32> (CALLudiv x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v.Type = typ.UInt32
+ v0 := b.NewValue0(v.Pos, OpARMCALLudiv, types.NewTuple(typ.UInt32, typ.UInt32))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8 x y)
+ // result: (Mod32 (SignExt8to32 x) (SignExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMod32)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8u x y)
+ // result: (Mod32u (ZeroExt8to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMod32u)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Move [0] _ _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Move [1] dst src mem)
+ // result: (MOVBstore dst (MOVBUload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARMMOVBstore)
+ v0 := b.NewValue0(v.Pos, OpARMMOVBUload, typ.UInt8)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore dst (MOVHUload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpARMMOVHstore)
+ v0 := b.NewValue0(v.Pos, OpARMMOVHUload, typ.UInt16)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] dst src mem)
+ // result: (MOVBstore [1] dst (MOVBUload [1] src mem) (MOVBstore dst (MOVBUload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpARMMOVBUload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpARMMOVBUload, typ.UInt8)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [4] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore dst (MOVWload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpARMMOVWstore)
+ v0 := b.NewValue0(v.Pos, OpARMMOVWload, typ.UInt32)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [4] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [2] dst (MOVHUload [2] src mem) (MOVHstore dst (MOVHUload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpARMMOVHstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpARMMOVHUload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARMMOVHstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpARMMOVHUload, typ.UInt16)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [4] dst src mem)
+ // result: (MOVBstore [3] dst (MOVBUload [3] src mem) (MOVBstore [2] dst (MOVBUload [2] src mem) (MOVBstore [1] dst (MOVBUload [1] src mem) (MOVBstore dst (MOVBUload src mem) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpARMMOVBUload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(3)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpARMMOVBUload, typ.UInt8)
+ v2.AuxInt = int32ToAuxInt(2)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(1)
+ v4 := b.NewValue0(v.Pos, OpARMMOVBUload, typ.UInt8)
+ v4.AuxInt = int32ToAuxInt(1)
+ v4.AddArg2(src, mem)
+ v5 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v6 := b.NewValue0(v.Pos, OpARMMOVBUload, typ.UInt8)
+ v6.AddArg2(src, mem)
+ v5.AddArg3(dst, v6, mem)
+ v3.AddArg3(dst, v4, v5)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [3] dst src mem)
+ // result: (MOVBstore [2] dst (MOVBUload [2] src mem) (MOVBstore [1] dst (MOVBUload [1] src mem) (MOVBstore dst (MOVBUload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpARMMOVBUload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpARMMOVBUload, typ.UInt8)
+ v2.AuxInt = int32ToAuxInt(1)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpARMMOVBUload, typ.UInt8)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] {t} dst src mem)
+ // cond: s%4 == 0 && s > 4 && s <= 512 && t.Alignment()%4 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
+ // result: (DUFFCOPY [8 * (128 - s/4)] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s%4 == 0 && s > 4 && s <= 512 && t.Alignment()%4 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpARMDUFFCOPY)
+ v.AuxInt = int64ToAuxInt(8 * (128 - s/4))
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (Move [s] {t} dst src mem)
+ // cond: ((s > 512 || config.noDuffDevice) || t.Alignment()%4 != 0) && logLargeCopy(v, s)
+ // result: (LoweredMove [t.Alignment()] dst src (ADDconst <src.Type> src [int32(s-moveSize(t.Alignment(), config))]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(((s > 512 || config.noDuffDevice) || t.Alignment()%4 != 0) && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpARMLoweredMove)
+ v.AuxInt = int64ToAuxInt(t.Alignment())
+ v0 := b.NewValue0(v.Pos, OpARMADDconst, src.Type)
+ v0.AuxInt = int32ToAuxInt(int32(s - moveSize(t.Alignment(), config)))
+ v0.AddArg(src)
+ v.AddArg4(dst, src, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpNeg16(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Neg16 x)
+ // result: (RSBconst [0] x)
+ for {
+ x := v_0
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueARM_OpNeg32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Neg32 x)
+ // result: (RSBconst [0] x)
+ for {
+ x := v_0
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueARM_OpNeg8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Neg8 x)
+ // result: (RSBconst [0] x)
+ for {
+ x := v_0
+ v.reset(OpARMRSBconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueARM_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq16 x y)
+ // result: (NotEqual (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMNotEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32 x y)
+ // result: (NotEqual (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMNotEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpNeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32F x y)
+ // result: (NotEqual (CMPF x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMNotEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMPF, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpNeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64F x y)
+ // result: (NotEqual (CMPD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMNotEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMPD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq8 x y)
+ // result: (NotEqual (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMNotEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpNeqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (NeqPtr x y)
+ // result: (NotEqual (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMNotEqual)
+ v0 := b.NewValue0(v.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpNot(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Not x)
+ // result: (XORconst [1] x)
+ for {
+ x := v_0
+ v.reset(OpARMXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueARM_OpOffPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (OffPtr [off] ptr:(SP))
+ // result: (MOVWaddr [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ if ptr.Op != OpSP {
+ break
+ }
+ v.reset(OpARMMOVWaddr)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (OffPtr [off] ptr)
+ // result: (ADDconst [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ v.reset(OpARMADDconst)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+}
+func rewriteValueARM_OpPanicBounds(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicBoundsA [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(OpARMLoweredPanicBoundsA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicBoundsB [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(OpARMLoweredPanicBoundsB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicBoundsC [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(OpARMLoweredPanicBoundsC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpPanicExtend(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicExtend [kind] hi lo y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicExtendA [kind] hi lo y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ hi := v_0
+ lo := v_1
+ y := v_2
+ mem := v_3
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(OpARMLoweredPanicExtendA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg4(hi, lo, y, mem)
+ return true
+ }
+ // match: (PanicExtend [kind] hi lo y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicExtendB [kind] hi lo y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ hi := v_0
+ lo := v_1
+ y := v_2
+ mem := v_3
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(OpARMLoweredPanicExtendB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg4(hi, lo, y, mem)
+ return true
+ }
+ // match: (PanicExtend [kind] hi lo y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicExtendC [kind] hi lo y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ hi := v_0
+ lo := v_1
+ y := v_2
+ mem := v_3
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(OpARMLoweredPanicExtendC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg4(hi, lo, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpRotateLeft16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft16 <t> x (MOVWconst [c]))
+ // result: (Or16 (Lsh16x32 <t> x (MOVWconst [c&15])) (Rsh16Ux32 <t> x (MOVWconst [-c&15])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpLsh16x32, t)
+ v1 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(c & 15)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh16Ux32, t)
+ v3 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(-c & 15)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpRotateLeft32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RotateLeft32 x (MOVWconst [c]))
+ // result: (SRRconst [-c&31] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpARMSRRconst)
+ v.AuxInt = int32ToAuxInt(-c & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RotateLeft32 x y)
+ // result: (SRR x (RSBconst [0] <y.Type> y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRR)
+ v0 := b.NewValue0(v.Pos, OpARMRSBconst, y.Type)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM_OpRotateLeft8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft8 <t> x (MOVWconst [c]))
+ // result: (Or8 (Lsh8x32 <t> x (MOVWconst [c&7])) (Rsh8Ux32 <t> x (MOVWconst [-c&7])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpLsh8x32, t)
+ v1 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(c & 7)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh8Ux32, t)
+ v3 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(-c & 7)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux16 x y)
+ // result: (CMOVWHSconst (SRL <x.Type> (ZeroExt16to32 x) (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(256)
+ v3.AddArg(v2)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux32 x y)
+ // result: (CMOVWHSconst (SRL <x.Type> (ZeroExt16to32 x) y) (CMPconst [256] y) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(256)
+ v2.AddArg(y)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux64 x (Const64 [c]))
+ // cond: uint64(c) < 16
+ // result: (SRLconst (SLLconst <typ.UInt32> x [16]) [int32(c+16)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 16) {
+ break
+ }
+ v.reset(OpARMSRLconst)
+ v.AuxInt = int32ToAuxInt(int32(c + 16))
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh16Ux64 _ (Const64 [c]))
+ // cond: uint64(c) >= 16
+ // result: (Const16 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux8 x y)
+ // result: (SRL (ZeroExt16to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRL)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x16 x y)
+ // result: (SRAcond (SignExt16to32 x) (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRAcond)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v2 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(256)
+ v2.AddArg(v1)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x32 x y)
+ // result: (SRAcond (SignExt16to32 x) y (CMPconst [256] y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRAcond)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v1.AuxInt = int32ToAuxInt(256)
+ v1.AddArg(y)
+ v.AddArg3(v0, y, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x64 x (Const64 [c]))
+ // cond: uint64(c) < 16
+ // result: (SRAconst (SLLconst <typ.UInt32> x [16]) [int32(c+16)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 16) {
+ break
+ }
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(int32(c + 16))
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh16x64 x (Const64 [c]))
+ // cond: uint64(c) >= 16
+ // result: (SRAconst (SLLconst <typ.UInt32> x [16]) [31])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x8 x y)
+ // result: (SRA (SignExt16to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux16 x y)
+ // result: (CMOVWHSconst (SRL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(256)
+ v2.AddArg(v1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux32 x y)
+ // result: (CMOVWHSconst (SRL <x.Type> x y) (CMPconst [256] y) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v1.AuxInt = int32ToAuxInt(256)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Rsh32Ux64 x (Const64 [c]))
+ // cond: uint64(c) < 32
+ // result: (SRLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 32) {
+ break
+ }
+ v.reset(OpARMSRLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32Ux64 _ (Const64 [c]))
+ // cond: uint64(c) >= 32
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux8 x y)
+ // result: (SRL x (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRL)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x16 x y)
+ // result: (SRAcond x (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRAcond)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v1.AuxInt = int32ToAuxInt(256)
+ v1.AddArg(v0)
+ v.AddArg3(x, v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x32 x y)
+ // result: (SRAcond x y (CMPconst [256] y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRAcond)
+ v0 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(256)
+ v0.AddArg(y)
+ v.AddArg3(x, y, v0)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Rsh32x64 x (Const64 [c]))
+ // cond: uint64(c) < 32
+ // result: (SRAconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 32) {
+ break
+ }
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32x64 x (Const64 [c]))
+ // cond: uint64(c) >= 32
+ // result: (SRAconst x [31])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x8 x y)
+ // result: (SRA x (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRA)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux16 x y)
+ // result: (CMOVWHSconst (SRL <x.Type> (ZeroExt8to32 x) (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(256)
+ v3.AddArg(v2)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux32 x y)
+ // result: (CMOVWHSconst (SRL <x.Type> (ZeroExt8to32 x) y) (CMPconst [256] y) [0])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMCMOVWHSconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARMSRL, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(256)
+ v2.AddArg(y)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux64 x (Const64 [c]))
+ // cond: uint64(c) < 8
+ // result: (SRLconst (SLLconst <typ.UInt32> x [24]) [int32(c+24)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 8) {
+ break
+ }
+ v.reset(OpARMSRLconst)
+ v.AuxInt = int32ToAuxInt(int32(c + 24))
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(24)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh8Ux64 _ (Const64 [c]))
+ // cond: uint64(c) >= 8
+ // result: (Const8 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux8 x y)
+ // result: (SRL (ZeroExt8to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRL)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x16 x y)
+ // result: (SRAcond (SignExt8to32 x) (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRAcond)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v2 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(256)
+ v2.AddArg(v1)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x32 x y)
+ // result: (SRAcond (SignExt8to32 x) y (CMPconst [256] y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRAcond)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARMCMPconst, types.TypeFlags)
+ v1.AuxInt = int32ToAuxInt(256)
+ v1.AddArg(y)
+ v.AddArg3(v0, y, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x64 x (Const64 [c]))
+ // cond: uint64(c) < 8
+ // result: (SRAconst (SLLconst <typ.UInt32> x [24]) [int32(c+24)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 8) {
+ break
+ }
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(int32(c + 24))
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(24)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh8x64 x (Const64 [c]))
+ // cond: uint64(c) >= 8
+ // result: (SRAconst (SLLconst <typ.UInt32> x [24]) [31])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v0 := b.NewValue0(v.Pos, OpARMSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(24)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x8 x y)
+ // result: (SRA (SignExt8to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARMSRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM_OpSelect0(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Select0 (CALLudiv x (MOVWconst [1])))
+ // result: x
+ for {
+ if v_0.Op != OpARMCALLudiv {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMMOVWconst || auxIntToInt32(v_0_1.AuxInt) != 1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Select0 (CALLudiv x (MOVWconst [c])))
+ // cond: isPowerOfTwo32(c)
+ // result: (SRLconst [int32(log32(c))] x)
+ for {
+ if v_0.Op != OpARMCALLudiv {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0_1.AuxInt)
+ if !(isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpARMSRLconst)
+ v.AuxInt = int32ToAuxInt(int32(log32(c)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
+ // result: (MOVWconst [int32(uint32(c)/uint32(d))])
+ for {
+ if v_0.Op != OpARMCALLudiv {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) / uint32(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpSelect1(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Select1 (CALLudiv _ (MOVWconst [1])))
+ // result: (MOVWconst [0])
+ for {
+ if v_0.Op != OpARMCALLudiv {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMMOVWconst || auxIntToInt32(v_0_1.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Select1 (CALLudiv x (MOVWconst [c])))
+ // cond: isPowerOfTwo32(c)
+ // result: (ANDconst [c-1] x)
+ for {
+ if v_0.Op != OpARMCALLudiv {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0_1.AuxInt)
+ if !(isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpARMANDconst)
+ v.AuxInt = int32ToAuxInt(c - 1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
+ // result: (MOVWconst [int32(uint32(c)%uint32(d))])
+ for {
+ if v_0.Op != OpARMCALLudiv {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpARMMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) % uint32(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpSignmask(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Signmask x)
+ // result: (SRAconst x [31])
+ for {
+ x := v_0
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueARM_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Slicemask <t> x)
+ // result: (SRAconst (RSBconst <t> [0] x) [31])
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v0 := b.NewValue0(v.Pos, OpARMRSBconst, t)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 1
+ // result: (MOVBstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 1) {
+ break
+ }
+ v.reset(OpARMMOVBstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 2
+ // result: (MOVHstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 2) {
+ break
+ }
+ v.reset(OpARMMOVHstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && !is32BitFloat(val.Type)
+ // result: (MOVWstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && !is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpARMMOVWstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && is32BitFloat(val.Type)
+ // result: (MOVFstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpARMMOVFstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && is64BitFloat(val.Type)
+ // result: (MOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpARMMOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Zero [0] _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_1
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero [1] ptr mem)
+ // result: (MOVBstore ptr (MOVWconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARMMOVBstore)
+ v0 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [2] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore ptr (MOVWconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpARMMOVHstore)
+ v0 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [2] ptr mem)
+ // result: (MOVBstore [1] ptr (MOVWconst [0]) (MOVBstore [0] ptr (MOVWconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [4] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore ptr (MOVWconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpARMMOVWstore)
+ v0 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [4] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [2] ptr (MOVWconst [0]) (MOVHstore [0] ptr (MOVWconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpARMMOVHstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARMMOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [4] ptr mem)
+ // result: (MOVBstore [3] ptr (MOVWconst [0]) (MOVBstore [2] ptr (MOVWconst [0]) (MOVBstore [1] ptr (MOVWconst [0]) (MOVBstore [0] ptr (MOVWconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(1)
+ v3 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(0)
+ v3.AddArg3(ptr, v0, mem)
+ v2.AddArg3(ptr, v0, v3)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [3] ptr mem)
+ // result: (MOVBstore [2] ptr (MOVWconst [0]) (MOVBstore [1] ptr (MOVWconst [0]) (MOVBstore [0] ptr (MOVWconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpARMMOVBstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [s] {t} ptr mem)
+ // cond: s%4 == 0 && s > 4 && s <= 512 && t.Alignment()%4 == 0 && !config.noDuffDevice
+ // result: (DUFFZERO [4 * (128 - s/4)] ptr (MOVWconst [0]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(s%4 == 0 && s > 4 && s <= 512 && t.Alignment()%4 == 0 && !config.noDuffDevice) {
+ break
+ }
+ v.reset(OpARMDUFFZERO)
+ v.AuxInt = int64ToAuxInt(4 * (128 - s/4))
+ v0 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [s] {t} ptr mem)
+ // cond: (s > 512 || config.noDuffDevice) || t.Alignment()%4 != 0
+ // result: (LoweredZero [t.Alignment()] ptr (ADDconst <ptr.Type> ptr [int32(s-moveSize(t.Alignment(), config))]) (MOVWconst [0]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !((s > 512 || config.noDuffDevice) || t.Alignment()%4 != 0) {
+ break
+ }
+ v.reset(OpARMLoweredZero)
+ v.AuxInt = int64ToAuxInt(t.Alignment())
+ v0 := b.NewValue0(v.Pos, OpARMADDconst, ptr.Type)
+ v0.AuxInt = int32ToAuxInt(int32(s - moveSize(t.Alignment(), config)))
+ v0.AddArg(ptr)
+ v1 := b.NewValue0(v.Pos, OpARMMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v.AddArg4(ptr, v0, v1, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM_OpZeromask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Zeromask x)
+ // result: (SRAconst (RSBshiftRL <typ.Int32> x x [1]) [31])
+ for {
+ x := v_0
+ v.reset(OpARMSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v0 := b.NewValue0(v.Pos, OpARMRSBshiftRL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(1)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteBlockARM(b *Block) bool {
+ switch b.Kind {
+ case BlockARMEQ:
+ // match: (EQ (FlagConstant [fc]) yes no)
+ // cond: fc.eq()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.eq()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (EQ (FlagConstant [fc]) yes no)
+ // cond: !fc.eq()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.eq()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (EQ (InvertFlags cmp) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMEQ, cmp)
+ return true
+ }
+ // match: (EQ (CMP x (RSBconst [0] y)))
+ // result: (EQ (CMN x y))
+ for b.Controls[0].Op == OpARMCMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMN x (RSBconst [0] y)))
+ // result: (EQ (CMP x y))
+ for b.Controls[0].Op == OpARMCMN {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (CMPconst [0] l:(SUB x y)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMP x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUB {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(MULS x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULS {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(SUBconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMPconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(SUBshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMPshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(SUBshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMPshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(SUBshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMPshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMPshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMPshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMPshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ADD x y)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMN x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADD {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (CMPconst [0] l:(MULA x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULA {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ADDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMNconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ADDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMNshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ADDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMNshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ADDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMNshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMNshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMNshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (CMNshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(AND x y)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TST x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMAND {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (CMPconst [0] l:(ANDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TSTconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ANDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TSTshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ANDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TSTshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ANDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TSTshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TSTshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TSTshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TSTshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(XOR x y)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TEQ x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXOR {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (CMPconst [0] l:(XORconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TEQconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(XORshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TEQshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(XORshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TEQshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(XORshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TEQshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(XORshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TEQshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(XORshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TEQshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] l:(XORshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (EQ (TEQshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMEQ, v0)
+ return true
+ }
+ case BlockARMGE:
+ // match: (GE (FlagConstant [fc]) yes no)
+ // cond: fc.ge()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ge()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GE (FlagConstant [fc]) yes no)
+ // cond: !fc.ge()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ge()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GE (InvertFlags cmp) yes no)
+ // result: (LE cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMLE, cmp)
+ return true
+ }
+ // match: (GE (CMP x (RSBconst [0] y)))
+ // result: (GE (CMN x y))
+ for b.Controls[0].Op == OpARMCMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGE, v0)
+ return true
+ }
+ // match: (GE (CMN x (RSBconst [0] y)))
+ // result: (GE (CMP x y))
+ for b.Controls[0].Op == OpARMCMN {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGE, v0)
+ return true
+ }
+ break
+ }
+ // match: (GE (CMPconst [0] l:(SUB x y)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMP x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUB {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(MULS x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULS {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(SUBconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMPconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMPshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMPshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMPshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMPshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMPshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMPshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ADD x y)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMN x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADD {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (GE (CMPconst [0] l:(MULA x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULA {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ADDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMNconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMNshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMNshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMNshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMNshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMNshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (CMNshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(AND x y)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TST x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMAND {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (GE (CMPconst [0] l:(ANDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TSTconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TSTshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TSTshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TSTshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TSTshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TSTshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TSTshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(XOR x y)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TEQ x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXOR {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (GE (CMPconst [0] l:(XORconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TEQconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TEQshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TEQshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TEQshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TEQshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TEQshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GEnoov (TEQshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGEnoov, v0)
+ return true
+ }
+ case BlockARMGEnoov:
+ // match: (GEnoov (FlagConstant [fc]) yes no)
+ // cond: fc.geNoov()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.geNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GEnoov (FlagConstant [fc]) yes no)
+ // cond: !fc.geNoov()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.geNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GEnoov (InvertFlags cmp) yes no)
+ // result: (LEnoov cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMLEnoov, cmp)
+ return true
+ }
+ case BlockARMGT:
+ // match: (GT (FlagConstant [fc]) yes no)
+ // cond: fc.gt()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.gt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GT (FlagConstant [fc]) yes no)
+ // cond: !fc.gt()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.gt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GT (InvertFlags cmp) yes no)
+ // result: (LT cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMLT, cmp)
+ return true
+ }
+ // match: (GT (CMP x (RSBconst [0] y)))
+ // result: (GT (CMN x y))
+ for b.Controls[0].Op == OpARMCMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGT, v0)
+ return true
+ }
+ // match: (GT (CMN x (RSBconst [0] y)))
+ // result: (GT (CMP x y))
+ for b.Controls[0].Op == OpARMCMN {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGT, v0)
+ return true
+ }
+ break
+ }
+ // match: (GT (CMPconst [0] l:(SUB x y)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMP x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUB {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(MULS x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULS {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(SUBconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMPconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMPshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMPshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMPshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMPshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMPshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMPshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ADD x y)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMN x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADD {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (GT (CMPconst [0] l:(ADDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMNconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMNshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMNshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMNshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMNshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMNshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMNshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(MULA x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULA {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(AND x y)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TST x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMAND {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (GT (CMPconst [0] l:(ANDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TSTconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TSTshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TSTshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TSTshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TSTshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TSTshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TSTshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(XOR x y)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TEQ x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXOR {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (GT (CMPconst [0] l:(XORconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TEQconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TEQshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TEQshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TEQshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TEQshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TEQshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TEQshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ case BlockARMGTnoov:
+ // match: (GTnoov (FlagConstant [fc]) yes no)
+ // cond: fc.gtNoov()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.gtNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GTnoov (FlagConstant [fc]) yes no)
+ // cond: !fc.gtNoov()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.gtNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GTnoov (InvertFlags cmp) yes no)
+ // result: (LTnoov cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMLTnoov, cmp)
+ return true
+ }
+ case BlockIf:
+ // match: (If (Equal cc) yes no)
+ // result: (EQ cc yes no)
+ for b.Controls[0].Op == OpARMEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARMEQ, cc)
+ return true
+ }
+ // match: (If (NotEqual cc) yes no)
+ // result: (NE cc yes no)
+ for b.Controls[0].Op == OpARMNotEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARMNE, cc)
+ return true
+ }
+ // match: (If (LessThan cc) yes no)
+ // result: (LT cc yes no)
+ for b.Controls[0].Op == OpARMLessThan {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARMLT, cc)
+ return true
+ }
+ // match: (If (LessThanU cc) yes no)
+ // result: (ULT cc yes no)
+ for b.Controls[0].Op == OpARMLessThanU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARMULT, cc)
+ return true
+ }
+ // match: (If (LessEqual cc) yes no)
+ // result: (LE cc yes no)
+ for b.Controls[0].Op == OpARMLessEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARMLE, cc)
+ return true
+ }
+ // match: (If (LessEqualU cc) yes no)
+ // result: (ULE cc yes no)
+ for b.Controls[0].Op == OpARMLessEqualU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARMULE, cc)
+ return true
+ }
+ // match: (If (GreaterThan cc) yes no)
+ // result: (GT cc yes no)
+ for b.Controls[0].Op == OpARMGreaterThan {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARMGT, cc)
+ return true
+ }
+ // match: (If (GreaterThanU cc) yes no)
+ // result: (UGT cc yes no)
+ for b.Controls[0].Op == OpARMGreaterThanU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARMUGT, cc)
+ return true
+ }
+ // match: (If (GreaterEqual cc) yes no)
+ // result: (GE cc yes no)
+ for b.Controls[0].Op == OpARMGreaterEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARMGE, cc)
+ return true
+ }
+ // match: (If (GreaterEqualU cc) yes no)
+ // result: (UGE cc yes no)
+ for b.Controls[0].Op == OpARMGreaterEqualU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARMUGE, cc)
+ return true
+ }
+ // match: (If cond yes no)
+ // result: (NE (CMPconst [0] cond) yes no)
+ for {
+ cond := b.Controls[0]
+ v0 := b.NewValue0(cond.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(cond)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ case BlockARMLE:
+ // match: (LE (FlagConstant [fc]) yes no)
+ // cond: fc.le()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.le()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LE (FlagConstant [fc]) yes no)
+ // cond: !fc.le()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.le()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LE (InvertFlags cmp) yes no)
+ // result: (GE cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMGE, cmp)
+ return true
+ }
+ // match: (LE (CMP x (RSBconst [0] y)))
+ // result: (LE (CMN x y))
+ for b.Controls[0].Op == OpARMCMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLE, v0)
+ return true
+ }
+ // match: (LE (CMN x (RSBconst [0] y)))
+ // result: (LE (CMP x y))
+ for b.Controls[0].Op == OpARMCMN {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLE, v0)
+ return true
+ }
+ break
+ }
+ // match: (LE (CMPconst [0] l:(SUB x y)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMP x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUB {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(MULS x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULS {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(SUBconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMPconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMPshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMPshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMPshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMPshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMPshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMPshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ADD x y)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMN x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADD {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (LE (CMPconst [0] l:(MULA x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULA {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ADDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMNconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMNshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMNshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMNshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMNshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMNshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (CMNshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(AND x y)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TST x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMAND {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (LE (CMPconst [0] l:(ANDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TSTconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TSTshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TSTshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TSTshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TSTshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TSTshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TSTshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(XOR x y)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TEQ x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXOR {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (LE (CMPconst [0] l:(XORconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TEQconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TEQshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TEQshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TEQshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TEQshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TEQshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LEnoov (TEQshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLEnoov, v0)
+ return true
+ }
+ case BlockARMLEnoov:
+ // match: (LEnoov (FlagConstant [fc]) yes no)
+ // cond: fc.leNoov()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.leNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LEnoov (FlagConstant [fc]) yes no)
+ // cond: !fc.leNoov()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.leNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LEnoov (InvertFlags cmp) yes no)
+ // result: (GEnoov cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMGEnoov, cmp)
+ return true
+ }
+ case BlockARMLT:
+ // match: (LT (FlagConstant [fc]) yes no)
+ // cond: fc.lt()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.lt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LT (FlagConstant [fc]) yes no)
+ // cond: !fc.lt()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.lt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LT (InvertFlags cmp) yes no)
+ // result: (GT cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMGT, cmp)
+ return true
+ }
+ // match: (LT (CMP x (RSBconst [0] y)))
+ // result: (LT (CMN x y))
+ for b.Controls[0].Op == OpARMCMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLT, v0)
+ return true
+ }
+ // match: (LT (CMN x (RSBconst [0] y)))
+ // result: (LT (CMP x y))
+ for b.Controls[0].Op == OpARMCMN {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLT, v0)
+ return true
+ }
+ break
+ }
+ // match: (LT (CMPconst [0] l:(SUB x y)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMP x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUB {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(MULS x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULS {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(SUBconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMPconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMPshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMPshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMPshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMPshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMPshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMPshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ADD x y)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMN x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADD {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (LT (CMPconst [0] l:(MULA x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULA {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ADDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMNconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMNshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMNshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMNshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMNshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMNshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (CMNshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(AND x y)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TST x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMAND {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (LT (CMPconst [0] l:(ANDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TSTconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TSTshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TSTshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TSTshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TSTshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TSTshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TSTshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(XOR x y)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TEQ x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXOR {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (LT (CMPconst [0] l:(XORconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TEQconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TEQshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TEQshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TEQshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TEQshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TEQshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (LTnoov (TEQshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMLTnoov, v0)
+ return true
+ }
+ case BlockARMLTnoov:
+ // match: (LTnoov (FlagConstant [fc]) yes no)
+ // cond: fc.ltNoov()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ltNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LTnoov (FlagConstant [fc]) yes no)
+ // cond: !fc.ltNoov()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ltNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LTnoov (InvertFlags cmp) yes no)
+ // result: (GTnoov cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMGTnoov, cmp)
+ return true
+ }
+ case BlockARMNE:
+ // match: (NE (CMPconst [0] (Equal cc)) yes no)
+ // result: (EQ cc yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMEqual {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockARMEQ, cc)
+ return true
+ }
+ // match: (NE (CMPconst [0] (NotEqual cc)) yes no)
+ // result: (NE cc yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMNotEqual {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockARMNE, cc)
+ return true
+ }
+ // match: (NE (CMPconst [0] (LessThan cc)) yes no)
+ // result: (LT cc yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMLessThan {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockARMLT, cc)
+ return true
+ }
+ // match: (NE (CMPconst [0] (LessThanU cc)) yes no)
+ // result: (ULT cc yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMLessThanU {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockARMULT, cc)
+ return true
+ }
+ // match: (NE (CMPconst [0] (LessEqual cc)) yes no)
+ // result: (LE cc yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMLessEqual {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockARMLE, cc)
+ return true
+ }
+ // match: (NE (CMPconst [0] (LessEqualU cc)) yes no)
+ // result: (ULE cc yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMLessEqualU {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockARMULE, cc)
+ return true
+ }
+ // match: (NE (CMPconst [0] (GreaterThan cc)) yes no)
+ // result: (GT cc yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMGreaterThan {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockARMGT, cc)
+ return true
+ }
+ // match: (NE (CMPconst [0] (GreaterThanU cc)) yes no)
+ // result: (UGT cc yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMGreaterThanU {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockARMUGT, cc)
+ return true
+ }
+ // match: (NE (CMPconst [0] (GreaterEqual cc)) yes no)
+ // result: (GE cc yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMGreaterEqual {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockARMGE, cc)
+ return true
+ }
+ // match: (NE (CMPconst [0] (GreaterEqualU cc)) yes no)
+ // result: (UGE cc yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARMGreaterEqualU {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockARMUGE, cc)
+ return true
+ }
+ // match: (NE (FlagConstant [fc]) yes no)
+ // cond: fc.ne()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ne()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (NE (FlagConstant [fc]) yes no)
+ // cond: !fc.ne()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ne()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (NE (InvertFlags cmp) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMNE, cmp)
+ return true
+ }
+ // match: (NE (CMP x (RSBconst [0] y)))
+ // result: (NE (CMN x y))
+ for b.Controls[0].Op == OpARMCMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMN x (RSBconst [0] y)))
+ // result: (NE (CMP x y))
+ for b.Controls[0].Op == OpARMCMN {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (CMPconst [0] l:(SUB x y)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMP x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUB {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(MULS x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULS {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(SUBconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMPconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMPshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMPshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMPshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMPshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMPshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMPshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMSUBshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ADD x y)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMN x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADD {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (CMPconst [0] l:(MULA x y a)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMMULA {
+ break
+ }
+ a := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ADDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMNconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMNshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMNshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMNshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMNshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMNshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (CMNshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMADDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(AND x y)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TST x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMAND {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (CMPconst [0] l:(ANDconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TSTconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TSTshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TSTshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TSTshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TSTshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TSTshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TSTshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMANDshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(XOR x y)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TEQ x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXOR {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (CMPconst [0] l:(XORconst [c] x)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TEQconst [c] x) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORconst {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(XORshiftLL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TEQshiftLL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(XORshiftRL x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TEQshiftRL x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRL {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(XORshiftRA x y [c])) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TEQshiftRA x y [c]) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRA {
+ break
+ }
+ c := auxIntToInt32(l.AuxInt)
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TEQshiftLLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftLLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TEQshiftRLreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRLreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no)
+ // cond: l.Uses==1
+ // result: (NE (TEQshiftRAreg x y z) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMXORshiftRAreg {
+ break
+ }
+ z := l.Args[2]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags)
+ v0.AddArg3(x, y, z)
+ b.resetWithControl(BlockARMNE, v0)
+ return true
+ }
+ case BlockARMUGE:
+ // match: (UGE (FlagConstant [fc]) yes no)
+ // cond: fc.uge()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.uge()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGE (FlagConstant [fc]) yes no)
+ // cond: !fc.uge()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.uge()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGE (InvertFlags cmp) yes no)
+ // result: (ULE cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMULE, cmp)
+ return true
+ }
+ case BlockARMUGT:
+ // match: (UGT (FlagConstant [fc]) yes no)
+ // cond: fc.ugt()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ugt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGT (FlagConstant [fc]) yes no)
+ // cond: !fc.ugt()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ugt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGT (InvertFlags cmp) yes no)
+ // result: (ULT cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMULT, cmp)
+ return true
+ }
+ case BlockARMULE:
+ // match: (ULE (FlagConstant [fc]) yes no)
+ // cond: fc.ule()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ule()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULE (FlagConstant [fc]) yes no)
+ // cond: !fc.ule()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ule()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULE (InvertFlags cmp) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMUGE, cmp)
+ return true
+ }
+ case BlockARMULT:
+ // match: (ULT (FlagConstant [fc]) yes no)
+ // cond: fc.ult()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ult()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULT (FlagConstant [fc]) yes no)
+ // cond: !fc.ult()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARMFlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ult()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULT (InvertFlags cmp) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == OpARMInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARMUGT, cmp)
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go
new file mode 100644
index 0000000..e61d899
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewriteARM64.go
@@ -0,0 +1,28662 @@
+// Code generated from gen/ARM64.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "cmd/compile/internal/types"
+
+func rewriteValueARM64(v *Value) bool {
+ switch v.Op {
+ case OpARM64ADCSflags:
+ return rewriteValueARM64_OpARM64ADCSflags(v)
+ case OpARM64ADD:
+ return rewriteValueARM64_OpARM64ADD(v)
+ case OpARM64ADDconst:
+ return rewriteValueARM64_OpARM64ADDconst(v)
+ case OpARM64ADDshiftLL:
+ return rewriteValueARM64_OpARM64ADDshiftLL(v)
+ case OpARM64ADDshiftRA:
+ return rewriteValueARM64_OpARM64ADDshiftRA(v)
+ case OpARM64ADDshiftRL:
+ return rewriteValueARM64_OpARM64ADDshiftRL(v)
+ case OpARM64AND:
+ return rewriteValueARM64_OpARM64AND(v)
+ case OpARM64ANDconst:
+ return rewriteValueARM64_OpARM64ANDconst(v)
+ case OpARM64ANDshiftLL:
+ return rewriteValueARM64_OpARM64ANDshiftLL(v)
+ case OpARM64ANDshiftRA:
+ return rewriteValueARM64_OpARM64ANDshiftRA(v)
+ case OpARM64ANDshiftRL:
+ return rewriteValueARM64_OpARM64ANDshiftRL(v)
+ case OpARM64BIC:
+ return rewriteValueARM64_OpARM64BIC(v)
+ case OpARM64BICshiftLL:
+ return rewriteValueARM64_OpARM64BICshiftLL(v)
+ case OpARM64BICshiftRA:
+ return rewriteValueARM64_OpARM64BICshiftRA(v)
+ case OpARM64BICshiftRL:
+ return rewriteValueARM64_OpARM64BICshiftRL(v)
+ case OpARM64CMN:
+ return rewriteValueARM64_OpARM64CMN(v)
+ case OpARM64CMNW:
+ return rewriteValueARM64_OpARM64CMNW(v)
+ case OpARM64CMNWconst:
+ return rewriteValueARM64_OpARM64CMNWconst(v)
+ case OpARM64CMNconst:
+ return rewriteValueARM64_OpARM64CMNconst(v)
+ case OpARM64CMNshiftLL:
+ return rewriteValueARM64_OpARM64CMNshiftLL(v)
+ case OpARM64CMNshiftRA:
+ return rewriteValueARM64_OpARM64CMNshiftRA(v)
+ case OpARM64CMNshiftRL:
+ return rewriteValueARM64_OpARM64CMNshiftRL(v)
+ case OpARM64CMP:
+ return rewriteValueARM64_OpARM64CMP(v)
+ case OpARM64CMPW:
+ return rewriteValueARM64_OpARM64CMPW(v)
+ case OpARM64CMPWconst:
+ return rewriteValueARM64_OpARM64CMPWconst(v)
+ case OpARM64CMPconst:
+ return rewriteValueARM64_OpARM64CMPconst(v)
+ case OpARM64CMPshiftLL:
+ return rewriteValueARM64_OpARM64CMPshiftLL(v)
+ case OpARM64CMPshiftRA:
+ return rewriteValueARM64_OpARM64CMPshiftRA(v)
+ case OpARM64CMPshiftRL:
+ return rewriteValueARM64_OpARM64CMPshiftRL(v)
+ case OpARM64CSEL:
+ return rewriteValueARM64_OpARM64CSEL(v)
+ case OpARM64CSEL0:
+ return rewriteValueARM64_OpARM64CSEL0(v)
+ case OpARM64DIV:
+ return rewriteValueARM64_OpARM64DIV(v)
+ case OpARM64DIVW:
+ return rewriteValueARM64_OpARM64DIVW(v)
+ case OpARM64EON:
+ return rewriteValueARM64_OpARM64EON(v)
+ case OpARM64EONshiftLL:
+ return rewriteValueARM64_OpARM64EONshiftLL(v)
+ case OpARM64EONshiftRA:
+ return rewriteValueARM64_OpARM64EONshiftRA(v)
+ case OpARM64EONshiftRL:
+ return rewriteValueARM64_OpARM64EONshiftRL(v)
+ case OpARM64Equal:
+ return rewriteValueARM64_OpARM64Equal(v)
+ case OpARM64FADDD:
+ return rewriteValueARM64_OpARM64FADDD(v)
+ case OpARM64FADDS:
+ return rewriteValueARM64_OpARM64FADDS(v)
+ case OpARM64FCMPD:
+ return rewriteValueARM64_OpARM64FCMPD(v)
+ case OpARM64FCMPS:
+ return rewriteValueARM64_OpARM64FCMPS(v)
+ case OpARM64FMOVDfpgp:
+ return rewriteValueARM64_OpARM64FMOVDfpgp(v)
+ case OpARM64FMOVDgpfp:
+ return rewriteValueARM64_OpARM64FMOVDgpfp(v)
+ case OpARM64FMOVDload:
+ return rewriteValueARM64_OpARM64FMOVDload(v)
+ case OpARM64FMOVDloadidx:
+ return rewriteValueARM64_OpARM64FMOVDloadidx(v)
+ case OpARM64FMOVDstore:
+ return rewriteValueARM64_OpARM64FMOVDstore(v)
+ case OpARM64FMOVDstoreidx:
+ return rewriteValueARM64_OpARM64FMOVDstoreidx(v)
+ case OpARM64FMOVSload:
+ return rewriteValueARM64_OpARM64FMOVSload(v)
+ case OpARM64FMOVSloadidx:
+ return rewriteValueARM64_OpARM64FMOVSloadidx(v)
+ case OpARM64FMOVSstore:
+ return rewriteValueARM64_OpARM64FMOVSstore(v)
+ case OpARM64FMOVSstoreidx:
+ return rewriteValueARM64_OpARM64FMOVSstoreidx(v)
+ case OpARM64FMULD:
+ return rewriteValueARM64_OpARM64FMULD(v)
+ case OpARM64FMULS:
+ return rewriteValueARM64_OpARM64FMULS(v)
+ case OpARM64FNEGD:
+ return rewriteValueARM64_OpARM64FNEGD(v)
+ case OpARM64FNEGS:
+ return rewriteValueARM64_OpARM64FNEGS(v)
+ case OpARM64FNMULD:
+ return rewriteValueARM64_OpARM64FNMULD(v)
+ case OpARM64FNMULS:
+ return rewriteValueARM64_OpARM64FNMULS(v)
+ case OpARM64FSUBD:
+ return rewriteValueARM64_OpARM64FSUBD(v)
+ case OpARM64FSUBS:
+ return rewriteValueARM64_OpARM64FSUBS(v)
+ case OpARM64GreaterEqual:
+ return rewriteValueARM64_OpARM64GreaterEqual(v)
+ case OpARM64GreaterEqualF:
+ return rewriteValueARM64_OpARM64GreaterEqualF(v)
+ case OpARM64GreaterEqualU:
+ return rewriteValueARM64_OpARM64GreaterEqualU(v)
+ case OpARM64GreaterThan:
+ return rewriteValueARM64_OpARM64GreaterThan(v)
+ case OpARM64GreaterThanF:
+ return rewriteValueARM64_OpARM64GreaterThanF(v)
+ case OpARM64GreaterThanU:
+ return rewriteValueARM64_OpARM64GreaterThanU(v)
+ case OpARM64LessEqual:
+ return rewriteValueARM64_OpARM64LessEqual(v)
+ case OpARM64LessEqualF:
+ return rewriteValueARM64_OpARM64LessEqualF(v)
+ case OpARM64LessEqualU:
+ return rewriteValueARM64_OpARM64LessEqualU(v)
+ case OpARM64LessThan:
+ return rewriteValueARM64_OpARM64LessThan(v)
+ case OpARM64LessThanF:
+ return rewriteValueARM64_OpARM64LessThanF(v)
+ case OpARM64LessThanU:
+ return rewriteValueARM64_OpARM64LessThanU(v)
+ case OpARM64MADD:
+ return rewriteValueARM64_OpARM64MADD(v)
+ case OpARM64MADDW:
+ return rewriteValueARM64_OpARM64MADDW(v)
+ case OpARM64MNEG:
+ return rewriteValueARM64_OpARM64MNEG(v)
+ case OpARM64MNEGW:
+ return rewriteValueARM64_OpARM64MNEGW(v)
+ case OpARM64MOD:
+ return rewriteValueARM64_OpARM64MOD(v)
+ case OpARM64MODW:
+ return rewriteValueARM64_OpARM64MODW(v)
+ case OpARM64MOVBUload:
+ return rewriteValueARM64_OpARM64MOVBUload(v)
+ case OpARM64MOVBUloadidx:
+ return rewriteValueARM64_OpARM64MOVBUloadidx(v)
+ case OpARM64MOVBUreg:
+ return rewriteValueARM64_OpARM64MOVBUreg(v)
+ case OpARM64MOVBload:
+ return rewriteValueARM64_OpARM64MOVBload(v)
+ case OpARM64MOVBloadidx:
+ return rewriteValueARM64_OpARM64MOVBloadidx(v)
+ case OpARM64MOVBreg:
+ return rewriteValueARM64_OpARM64MOVBreg(v)
+ case OpARM64MOVBstore:
+ return rewriteValueARM64_OpARM64MOVBstore(v)
+ case OpARM64MOVBstoreidx:
+ return rewriteValueARM64_OpARM64MOVBstoreidx(v)
+ case OpARM64MOVBstorezero:
+ return rewriteValueARM64_OpARM64MOVBstorezero(v)
+ case OpARM64MOVBstorezeroidx:
+ return rewriteValueARM64_OpARM64MOVBstorezeroidx(v)
+ case OpARM64MOVDload:
+ return rewriteValueARM64_OpARM64MOVDload(v)
+ case OpARM64MOVDloadidx:
+ return rewriteValueARM64_OpARM64MOVDloadidx(v)
+ case OpARM64MOVDloadidx8:
+ return rewriteValueARM64_OpARM64MOVDloadidx8(v)
+ case OpARM64MOVDreg:
+ return rewriteValueARM64_OpARM64MOVDreg(v)
+ case OpARM64MOVDstore:
+ return rewriteValueARM64_OpARM64MOVDstore(v)
+ case OpARM64MOVDstoreidx:
+ return rewriteValueARM64_OpARM64MOVDstoreidx(v)
+ case OpARM64MOVDstoreidx8:
+ return rewriteValueARM64_OpARM64MOVDstoreidx8(v)
+ case OpARM64MOVDstorezero:
+ return rewriteValueARM64_OpARM64MOVDstorezero(v)
+ case OpARM64MOVDstorezeroidx:
+ return rewriteValueARM64_OpARM64MOVDstorezeroidx(v)
+ case OpARM64MOVDstorezeroidx8:
+ return rewriteValueARM64_OpARM64MOVDstorezeroidx8(v)
+ case OpARM64MOVHUload:
+ return rewriteValueARM64_OpARM64MOVHUload(v)
+ case OpARM64MOVHUloadidx:
+ return rewriteValueARM64_OpARM64MOVHUloadidx(v)
+ case OpARM64MOVHUloadidx2:
+ return rewriteValueARM64_OpARM64MOVHUloadidx2(v)
+ case OpARM64MOVHUreg:
+ return rewriteValueARM64_OpARM64MOVHUreg(v)
+ case OpARM64MOVHload:
+ return rewriteValueARM64_OpARM64MOVHload(v)
+ case OpARM64MOVHloadidx:
+ return rewriteValueARM64_OpARM64MOVHloadidx(v)
+ case OpARM64MOVHloadidx2:
+ return rewriteValueARM64_OpARM64MOVHloadidx2(v)
+ case OpARM64MOVHreg:
+ return rewriteValueARM64_OpARM64MOVHreg(v)
+ case OpARM64MOVHstore:
+ return rewriteValueARM64_OpARM64MOVHstore(v)
+ case OpARM64MOVHstoreidx:
+ return rewriteValueARM64_OpARM64MOVHstoreidx(v)
+ case OpARM64MOVHstoreidx2:
+ return rewriteValueARM64_OpARM64MOVHstoreidx2(v)
+ case OpARM64MOVHstorezero:
+ return rewriteValueARM64_OpARM64MOVHstorezero(v)
+ case OpARM64MOVHstorezeroidx:
+ return rewriteValueARM64_OpARM64MOVHstorezeroidx(v)
+ case OpARM64MOVHstorezeroidx2:
+ return rewriteValueARM64_OpARM64MOVHstorezeroidx2(v)
+ case OpARM64MOVQstorezero:
+ return rewriteValueARM64_OpARM64MOVQstorezero(v)
+ case OpARM64MOVWUload:
+ return rewriteValueARM64_OpARM64MOVWUload(v)
+ case OpARM64MOVWUloadidx:
+ return rewriteValueARM64_OpARM64MOVWUloadidx(v)
+ case OpARM64MOVWUloadidx4:
+ return rewriteValueARM64_OpARM64MOVWUloadidx4(v)
+ case OpARM64MOVWUreg:
+ return rewriteValueARM64_OpARM64MOVWUreg(v)
+ case OpARM64MOVWload:
+ return rewriteValueARM64_OpARM64MOVWload(v)
+ case OpARM64MOVWloadidx:
+ return rewriteValueARM64_OpARM64MOVWloadidx(v)
+ case OpARM64MOVWloadidx4:
+ return rewriteValueARM64_OpARM64MOVWloadidx4(v)
+ case OpARM64MOVWreg:
+ return rewriteValueARM64_OpARM64MOVWreg(v)
+ case OpARM64MOVWstore:
+ return rewriteValueARM64_OpARM64MOVWstore(v)
+ case OpARM64MOVWstoreidx:
+ return rewriteValueARM64_OpARM64MOVWstoreidx(v)
+ case OpARM64MOVWstoreidx4:
+ return rewriteValueARM64_OpARM64MOVWstoreidx4(v)
+ case OpARM64MOVWstorezero:
+ return rewriteValueARM64_OpARM64MOVWstorezero(v)
+ case OpARM64MOVWstorezeroidx:
+ return rewriteValueARM64_OpARM64MOVWstorezeroidx(v)
+ case OpARM64MOVWstorezeroidx4:
+ return rewriteValueARM64_OpARM64MOVWstorezeroidx4(v)
+ case OpARM64MSUB:
+ return rewriteValueARM64_OpARM64MSUB(v)
+ case OpARM64MSUBW:
+ return rewriteValueARM64_OpARM64MSUBW(v)
+ case OpARM64MUL:
+ return rewriteValueARM64_OpARM64MUL(v)
+ case OpARM64MULW:
+ return rewriteValueARM64_OpARM64MULW(v)
+ case OpARM64MVN:
+ return rewriteValueARM64_OpARM64MVN(v)
+ case OpARM64MVNshiftLL:
+ return rewriteValueARM64_OpARM64MVNshiftLL(v)
+ case OpARM64MVNshiftRA:
+ return rewriteValueARM64_OpARM64MVNshiftRA(v)
+ case OpARM64MVNshiftRL:
+ return rewriteValueARM64_OpARM64MVNshiftRL(v)
+ case OpARM64NEG:
+ return rewriteValueARM64_OpARM64NEG(v)
+ case OpARM64NEGshiftLL:
+ return rewriteValueARM64_OpARM64NEGshiftLL(v)
+ case OpARM64NEGshiftRA:
+ return rewriteValueARM64_OpARM64NEGshiftRA(v)
+ case OpARM64NEGshiftRL:
+ return rewriteValueARM64_OpARM64NEGshiftRL(v)
+ case OpARM64NotEqual:
+ return rewriteValueARM64_OpARM64NotEqual(v)
+ case OpARM64OR:
+ return rewriteValueARM64_OpARM64OR(v)
+ case OpARM64ORN:
+ return rewriteValueARM64_OpARM64ORN(v)
+ case OpARM64ORNshiftLL:
+ return rewriteValueARM64_OpARM64ORNshiftLL(v)
+ case OpARM64ORNshiftRA:
+ return rewriteValueARM64_OpARM64ORNshiftRA(v)
+ case OpARM64ORNshiftRL:
+ return rewriteValueARM64_OpARM64ORNshiftRL(v)
+ case OpARM64ORconst:
+ return rewriteValueARM64_OpARM64ORconst(v)
+ case OpARM64ORshiftLL:
+ return rewriteValueARM64_OpARM64ORshiftLL(v)
+ case OpARM64ORshiftRA:
+ return rewriteValueARM64_OpARM64ORshiftRA(v)
+ case OpARM64ORshiftRL:
+ return rewriteValueARM64_OpARM64ORshiftRL(v)
+ case OpARM64RORWconst:
+ return rewriteValueARM64_OpARM64RORWconst(v)
+ case OpARM64RORconst:
+ return rewriteValueARM64_OpARM64RORconst(v)
+ case OpARM64SBCSflags:
+ return rewriteValueARM64_OpARM64SBCSflags(v)
+ case OpARM64SLL:
+ return rewriteValueARM64_OpARM64SLL(v)
+ case OpARM64SLLconst:
+ return rewriteValueARM64_OpARM64SLLconst(v)
+ case OpARM64SRA:
+ return rewriteValueARM64_OpARM64SRA(v)
+ case OpARM64SRAconst:
+ return rewriteValueARM64_OpARM64SRAconst(v)
+ case OpARM64SRL:
+ return rewriteValueARM64_OpARM64SRL(v)
+ case OpARM64SRLconst:
+ return rewriteValueARM64_OpARM64SRLconst(v)
+ case OpARM64STP:
+ return rewriteValueARM64_OpARM64STP(v)
+ case OpARM64SUB:
+ return rewriteValueARM64_OpARM64SUB(v)
+ case OpARM64SUBconst:
+ return rewriteValueARM64_OpARM64SUBconst(v)
+ case OpARM64SUBshiftLL:
+ return rewriteValueARM64_OpARM64SUBshiftLL(v)
+ case OpARM64SUBshiftRA:
+ return rewriteValueARM64_OpARM64SUBshiftRA(v)
+ case OpARM64SUBshiftRL:
+ return rewriteValueARM64_OpARM64SUBshiftRL(v)
+ case OpARM64TST:
+ return rewriteValueARM64_OpARM64TST(v)
+ case OpARM64TSTW:
+ return rewriteValueARM64_OpARM64TSTW(v)
+ case OpARM64TSTWconst:
+ return rewriteValueARM64_OpARM64TSTWconst(v)
+ case OpARM64TSTconst:
+ return rewriteValueARM64_OpARM64TSTconst(v)
+ case OpARM64TSTshiftLL:
+ return rewriteValueARM64_OpARM64TSTshiftLL(v)
+ case OpARM64TSTshiftRA:
+ return rewriteValueARM64_OpARM64TSTshiftRA(v)
+ case OpARM64TSTshiftRL:
+ return rewriteValueARM64_OpARM64TSTshiftRL(v)
+ case OpARM64UBFIZ:
+ return rewriteValueARM64_OpARM64UBFIZ(v)
+ case OpARM64UBFX:
+ return rewriteValueARM64_OpARM64UBFX(v)
+ case OpARM64UDIV:
+ return rewriteValueARM64_OpARM64UDIV(v)
+ case OpARM64UDIVW:
+ return rewriteValueARM64_OpARM64UDIVW(v)
+ case OpARM64UMOD:
+ return rewriteValueARM64_OpARM64UMOD(v)
+ case OpARM64UMODW:
+ return rewriteValueARM64_OpARM64UMODW(v)
+ case OpARM64XOR:
+ return rewriteValueARM64_OpARM64XOR(v)
+ case OpARM64XORconst:
+ return rewriteValueARM64_OpARM64XORconst(v)
+ case OpARM64XORshiftLL:
+ return rewriteValueARM64_OpARM64XORshiftLL(v)
+ case OpARM64XORshiftRA:
+ return rewriteValueARM64_OpARM64XORshiftRA(v)
+ case OpARM64XORshiftRL:
+ return rewriteValueARM64_OpARM64XORshiftRL(v)
+ case OpAbs:
+ v.Op = OpARM64FABSD
+ return true
+ case OpAdd16:
+ v.Op = OpARM64ADD
+ return true
+ case OpAdd32:
+ v.Op = OpARM64ADD
+ return true
+ case OpAdd32F:
+ v.Op = OpARM64FADDS
+ return true
+ case OpAdd64:
+ v.Op = OpARM64ADD
+ return true
+ case OpAdd64F:
+ v.Op = OpARM64FADDD
+ return true
+ case OpAdd8:
+ v.Op = OpARM64ADD
+ return true
+ case OpAddPtr:
+ v.Op = OpARM64ADD
+ return true
+ case OpAddr:
+ return rewriteValueARM64_OpAddr(v)
+ case OpAnd16:
+ v.Op = OpARM64AND
+ return true
+ case OpAnd32:
+ v.Op = OpARM64AND
+ return true
+ case OpAnd64:
+ v.Op = OpARM64AND
+ return true
+ case OpAnd8:
+ v.Op = OpARM64AND
+ return true
+ case OpAndB:
+ v.Op = OpARM64AND
+ return true
+ case OpAtomicAdd32:
+ v.Op = OpARM64LoweredAtomicAdd32
+ return true
+ case OpAtomicAdd32Variant:
+ v.Op = OpARM64LoweredAtomicAdd32Variant
+ return true
+ case OpAtomicAdd64:
+ v.Op = OpARM64LoweredAtomicAdd64
+ return true
+ case OpAtomicAdd64Variant:
+ v.Op = OpARM64LoweredAtomicAdd64Variant
+ return true
+ case OpAtomicAnd32:
+ return rewriteValueARM64_OpAtomicAnd32(v)
+ case OpAtomicAnd32Variant:
+ return rewriteValueARM64_OpAtomicAnd32Variant(v)
+ case OpAtomicAnd8:
+ return rewriteValueARM64_OpAtomicAnd8(v)
+ case OpAtomicAnd8Variant:
+ return rewriteValueARM64_OpAtomicAnd8Variant(v)
+ case OpAtomicCompareAndSwap32:
+ v.Op = OpARM64LoweredAtomicCas32
+ return true
+ case OpAtomicCompareAndSwap32Variant:
+ v.Op = OpARM64LoweredAtomicCas32Variant
+ return true
+ case OpAtomicCompareAndSwap64:
+ v.Op = OpARM64LoweredAtomicCas64
+ return true
+ case OpAtomicCompareAndSwap64Variant:
+ v.Op = OpARM64LoweredAtomicCas64Variant
+ return true
+ case OpAtomicExchange32:
+ v.Op = OpARM64LoweredAtomicExchange32
+ return true
+ case OpAtomicExchange32Variant:
+ v.Op = OpARM64LoweredAtomicExchange32Variant
+ return true
+ case OpAtomicExchange64:
+ v.Op = OpARM64LoweredAtomicExchange64
+ return true
+ case OpAtomicExchange64Variant:
+ v.Op = OpARM64LoweredAtomicExchange64Variant
+ return true
+ case OpAtomicLoad32:
+ v.Op = OpARM64LDARW
+ return true
+ case OpAtomicLoad64:
+ v.Op = OpARM64LDAR
+ return true
+ case OpAtomicLoad8:
+ v.Op = OpARM64LDARB
+ return true
+ case OpAtomicLoadPtr:
+ v.Op = OpARM64LDAR
+ return true
+ case OpAtomicOr32:
+ return rewriteValueARM64_OpAtomicOr32(v)
+ case OpAtomicOr32Variant:
+ return rewriteValueARM64_OpAtomicOr32Variant(v)
+ case OpAtomicOr8:
+ return rewriteValueARM64_OpAtomicOr8(v)
+ case OpAtomicOr8Variant:
+ return rewriteValueARM64_OpAtomicOr8Variant(v)
+ case OpAtomicStore32:
+ v.Op = OpARM64STLRW
+ return true
+ case OpAtomicStore64:
+ v.Op = OpARM64STLR
+ return true
+ case OpAtomicStore8:
+ v.Op = OpARM64STLRB
+ return true
+ case OpAtomicStorePtrNoWB:
+ v.Op = OpARM64STLR
+ return true
+ case OpAvg64u:
+ return rewriteValueARM64_OpAvg64u(v)
+ case OpBitLen32:
+ return rewriteValueARM64_OpBitLen32(v)
+ case OpBitLen64:
+ return rewriteValueARM64_OpBitLen64(v)
+ case OpBitRev16:
+ return rewriteValueARM64_OpBitRev16(v)
+ case OpBitRev32:
+ v.Op = OpARM64RBITW
+ return true
+ case OpBitRev64:
+ v.Op = OpARM64RBIT
+ return true
+ case OpBitRev8:
+ return rewriteValueARM64_OpBitRev8(v)
+ case OpBswap32:
+ v.Op = OpARM64REVW
+ return true
+ case OpBswap64:
+ v.Op = OpARM64REV
+ return true
+ case OpCeil:
+ v.Op = OpARM64FRINTPD
+ return true
+ case OpClosureCall:
+ v.Op = OpARM64CALLclosure
+ return true
+ case OpCom16:
+ v.Op = OpARM64MVN
+ return true
+ case OpCom32:
+ v.Op = OpARM64MVN
+ return true
+ case OpCom64:
+ v.Op = OpARM64MVN
+ return true
+ case OpCom8:
+ v.Op = OpARM64MVN
+ return true
+ case OpCondSelect:
+ return rewriteValueARM64_OpCondSelect(v)
+ case OpConst16:
+ return rewriteValueARM64_OpConst16(v)
+ case OpConst32:
+ return rewriteValueARM64_OpConst32(v)
+ case OpConst32F:
+ return rewriteValueARM64_OpConst32F(v)
+ case OpConst64:
+ return rewriteValueARM64_OpConst64(v)
+ case OpConst64F:
+ return rewriteValueARM64_OpConst64F(v)
+ case OpConst8:
+ return rewriteValueARM64_OpConst8(v)
+ case OpConstBool:
+ return rewriteValueARM64_OpConstBool(v)
+ case OpConstNil:
+ return rewriteValueARM64_OpConstNil(v)
+ case OpCtz16:
+ return rewriteValueARM64_OpCtz16(v)
+ case OpCtz16NonZero:
+ v.Op = OpCtz32
+ return true
+ case OpCtz32:
+ return rewriteValueARM64_OpCtz32(v)
+ case OpCtz32NonZero:
+ v.Op = OpCtz32
+ return true
+ case OpCtz64:
+ return rewriteValueARM64_OpCtz64(v)
+ case OpCtz64NonZero:
+ v.Op = OpCtz64
+ return true
+ case OpCtz8:
+ return rewriteValueARM64_OpCtz8(v)
+ case OpCtz8NonZero:
+ v.Op = OpCtz32
+ return true
+ case OpCvt32Fto32:
+ v.Op = OpARM64FCVTZSSW
+ return true
+ case OpCvt32Fto32U:
+ v.Op = OpARM64FCVTZUSW
+ return true
+ case OpCvt32Fto64:
+ v.Op = OpARM64FCVTZSS
+ return true
+ case OpCvt32Fto64F:
+ v.Op = OpARM64FCVTSD
+ return true
+ case OpCvt32Fto64U:
+ v.Op = OpARM64FCVTZUS
+ return true
+ case OpCvt32Uto32F:
+ v.Op = OpARM64UCVTFWS
+ return true
+ case OpCvt32Uto64F:
+ v.Op = OpARM64UCVTFWD
+ return true
+ case OpCvt32to32F:
+ v.Op = OpARM64SCVTFWS
+ return true
+ case OpCvt32to64F:
+ v.Op = OpARM64SCVTFWD
+ return true
+ case OpCvt64Fto32:
+ v.Op = OpARM64FCVTZSDW
+ return true
+ case OpCvt64Fto32F:
+ v.Op = OpARM64FCVTDS
+ return true
+ case OpCvt64Fto32U:
+ v.Op = OpARM64FCVTZUDW
+ return true
+ case OpCvt64Fto64:
+ v.Op = OpARM64FCVTZSD
+ return true
+ case OpCvt64Fto64U:
+ v.Op = OpARM64FCVTZUD
+ return true
+ case OpCvt64Uto32F:
+ v.Op = OpARM64UCVTFS
+ return true
+ case OpCvt64Uto64F:
+ v.Op = OpARM64UCVTFD
+ return true
+ case OpCvt64to32F:
+ v.Op = OpARM64SCVTFS
+ return true
+ case OpCvt64to64F:
+ v.Op = OpARM64SCVTFD
+ return true
+ case OpCvtBoolToUint8:
+ v.Op = OpCopy
+ return true
+ case OpDiv16:
+ return rewriteValueARM64_OpDiv16(v)
+ case OpDiv16u:
+ return rewriteValueARM64_OpDiv16u(v)
+ case OpDiv32:
+ return rewriteValueARM64_OpDiv32(v)
+ case OpDiv32F:
+ v.Op = OpARM64FDIVS
+ return true
+ case OpDiv32u:
+ v.Op = OpARM64UDIVW
+ return true
+ case OpDiv64:
+ return rewriteValueARM64_OpDiv64(v)
+ case OpDiv64F:
+ v.Op = OpARM64FDIVD
+ return true
+ case OpDiv64u:
+ v.Op = OpARM64UDIV
+ return true
+ case OpDiv8:
+ return rewriteValueARM64_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValueARM64_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValueARM64_OpEq16(v)
+ case OpEq32:
+ return rewriteValueARM64_OpEq32(v)
+ case OpEq32F:
+ return rewriteValueARM64_OpEq32F(v)
+ case OpEq64:
+ return rewriteValueARM64_OpEq64(v)
+ case OpEq64F:
+ return rewriteValueARM64_OpEq64F(v)
+ case OpEq8:
+ return rewriteValueARM64_OpEq8(v)
+ case OpEqB:
+ return rewriteValueARM64_OpEqB(v)
+ case OpEqPtr:
+ return rewriteValueARM64_OpEqPtr(v)
+ case OpFMA:
+ return rewriteValueARM64_OpFMA(v)
+ case OpFloor:
+ v.Op = OpARM64FRINTMD
+ return true
+ case OpGetCallerPC:
+ v.Op = OpARM64LoweredGetCallerPC
+ return true
+ case OpGetCallerSP:
+ v.Op = OpARM64LoweredGetCallerSP
+ return true
+ case OpGetClosurePtr:
+ v.Op = OpARM64LoweredGetClosurePtr
+ return true
+ case OpHmul32:
+ return rewriteValueARM64_OpHmul32(v)
+ case OpHmul32u:
+ return rewriteValueARM64_OpHmul32u(v)
+ case OpHmul64:
+ v.Op = OpARM64MULH
+ return true
+ case OpHmul64u:
+ v.Op = OpARM64UMULH
+ return true
+ case OpInterCall:
+ v.Op = OpARM64CALLinter
+ return true
+ case OpIsInBounds:
+ return rewriteValueARM64_OpIsInBounds(v)
+ case OpIsNonNil:
+ return rewriteValueARM64_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ return rewriteValueARM64_OpIsSliceInBounds(v)
+ case OpLeq16:
+ return rewriteValueARM64_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValueARM64_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValueARM64_OpLeq32(v)
+ case OpLeq32F:
+ return rewriteValueARM64_OpLeq32F(v)
+ case OpLeq32U:
+ return rewriteValueARM64_OpLeq32U(v)
+ case OpLeq64:
+ return rewriteValueARM64_OpLeq64(v)
+ case OpLeq64F:
+ return rewriteValueARM64_OpLeq64F(v)
+ case OpLeq64U:
+ return rewriteValueARM64_OpLeq64U(v)
+ case OpLeq8:
+ return rewriteValueARM64_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValueARM64_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValueARM64_OpLess16(v)
+ case OpLess16U:
+ return rewriteValueARM64_OpLess16U(v)
+ case OpLess32:
+ return rewriteValueARM64_OpLess32(v)
+ case OpLess32F:
+ return rewriteValueARM64_OpLess32F(v)
+ case OpLess32U:
+ return rewriteValueARM64_OpLess32U(v)
+ case OpLess64:
+ return rewriteValueARM64_OpLess64(v)
+ case OpLess64F:
+ return rewriteValueARM64_OpLess64F(v)
+ case OpLess64U:
+ return rewriteValueARM64_OpLess64U(v)
+ case OpLess8:
+ return rewriteValueARM64_OpLess8(v)
+ case OpLess8U:
+ return rewriteValueARM64_OpLess8U(v)
+ case OpLoad:
+ return rewriteValueARM64_OpLoad(v)
+ case OpLocalAddr:
+ return rewriteValueARM64_OpLocalAddr(v)
+ case OpLsh16x16:
+ return rewriteValueARM64_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValueARM64_OpLsh16x32(v)
+ case OpLsh16x64:
+ return rewriteValueARM64_OpLsh16x64(v)
+ case OpLsh16x8:
+ return rewriteValueARM64_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValueARM64_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValueARM64_OpLsh32x32(v)
+ case OpLsh32x64:
+ return rewriteValueARM64_OpLsh32x64(v)
+ case OpLsh32x8:
+ return rewriteValueARM64_OpLsh32x8(v)
+ case OpLsh64x16:
+ return rewriteValueARM64_OpLsh64x16(v)
+ case OpLsh64x32:
+ return rewriteValueARM64_OpLsh64x32(v)
+ case OpLsh64x64:
+ return rewriteValueARM64_OpLsh64x64(v)
+ case OpLsh64x8:
+ return rewriteValueARM64_OpLsh64x8(v)
+ case OpLsh8x16:
+ return rewriteValueARM64_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValueARM64_OpLsh8x32(v)
+ case OpLsh8x64:
+ return rewriteValueARM64_OpLsh8x64(v)
+ case OpLsh8x8:
+ return rewriteValueARM64_OpLsh8x8(v)
+ case OpMod16:
+ return rewriteValueARM64_OpMod16(v)
+ case OpMod16u:
+ return rewriteValueARM64_OpMod16u(v)
+ case OpMod32:
+ return rewriteValueARM64_OpMod32(v)
+ case OpMod32u:
+ v.Op = OpARM64UMODW
+ return true
+ case OpMod64:
+ return rewriteValueARM64_OpMod64(v)
+ case OpMod64u:
+ v.Op = OpARM64UMOD
+ return true
+ case OpMod8:
+ return rewriteValueARM64_OpMod8(v)
+ case OpMod8u:
+ return rewriteValueARM64_OpMod8u(v)
+ case OpMove:
+ return rewriteValueARM64_OpMove(v)
+ case OpMul16:
+ v.Op = OpARM64MULW
+ return true
+ case OpMul32:
+ v.Op = OpARM64MULW
+ return true
+ case OpMul32F:
+ v.Op = OpARM64FMULS
+ return true
+ case OpMul64:
+ v.Op = OpARM64MUL
+ return true
+ case OpMul64F:
+ v.Op = OpARM64FMULD
+ return true
+ case OpMul64uhilo:
+ v.Op = OpARM64LoweredMuluhilo
+ return true
+ case OpMul8:
+ v.Op = OpARM64MULW
+ return true
+ case OpNeg16:
+ v.Op = OpARM64NEG
+ return true
+ case OpNeg32:
+ v.Op = OpARM64NEG
+ return true
+ case OpNeg32F:
+ v.Op = OpARM64FNEGS
+ return true
+ case OpNeg64:
+ v.Op = OpARM64NEG
+ return true
+ case OpNeg64F:
+ v.Op = OpARM64FNEGD
+ return true
+ case OpNeg8:
+ v.Op = OpARM64NEG
+ return true
+ case OpNeq16:
+ return rewriteValueARM64_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValueARM64_OpNeq32(v)
+ case OpNeq32F:
+ return rewriteValueARM64_OpNeq32F(v)
+ case OpNeq64:
+ return rewriteValueARM64_OpNeq64(v)
+ case OpNeq64F:
+ return rewriteValueARM64_OpNeq64F(v)
+ case OpNeq8:
+ return rewriteValueARM64_OpNeq8(v)
+ case OpNeqB:
+ v.Op = OpARM64XOR
+ return true
+ case OpNeqPtr:
+ return rewriteValueARM64_OpNeqPtr(v)
+ case OpNilCheck:
+ v.Op = OpARM64LoweredNilCheck
+ return true
+ case OpNot:
+ return rewriteValueARM64_OpNot(v)
+ case OpOffPtr:
+ return rewriteValueARM64_OpOffPtr(v)
+ case OpOr16:
+ v.Op = OpARM64OR
+ return true
+ case OpOr32:
+ v.Op = OpARM64OR
+ return true
+ case OpOr64:
+ v.Op = OpARM64OR
+ return true
+ case OpOr8:
+ v.Op = OpARM64OR
+ return true
+ case OpOrB:
+ v.Op = OpARM64OR
+ return true
+ case OpPanicBounds:
+ return rewriteValueARM64_OpPanicBounds(v)
+ case OpPopCount16:
+ return rewriteValueARM64_OpPopCount16(v)
+ case OpPopCount32:
+ return rewriteValueARM64_OpPopCount32(v)
+ case OpPopCount64:
+ return rewriteValueARM64_OpPopCount64(v)
+ case OpRotateLeft16:
+ return rewriteValueARM64_OpRotateLeft16(v)
+ case OpRotateLeft32:
+ return rewriteValueARM64_OpRotateLeft32(v)
+ case OpRotateLeft64:
+ return rewriteValueARM64_OpRotateLeft64(v)
+ case OpRotateLeft8:
+ return rewriteValueARM64_OpRotateLeft8(v)
+ case OpRound:
+ v.Op = OpARM64FRINTAD
+ return true
+ case OpRound32F:
+ v.Op = OpARM64LoweredRound32F
+ return true
+ case OpRound64F:
+ v.Op = OpARM64LoweredRound64F
+ return true
+ case OpRoundToEven:
+ v.Op = OpARM64FRINTND
+ return true
+ case OpRsh16Ux16:
+ return rewriteValueARM64_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValueARM64_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValueARM64_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValueARM64_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValueARM64_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValueARM64_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValueARM64_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValueARM64_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValueARM64_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValueARM64_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValueARM64_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValueARM64_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValueARM64_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValueARM64_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValueARM64_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValueARM64_OpRsh32x8(v)
+ case OpRsh64Ux16:
+ return rewriteValueARM64_OpRsh64Ux16(v)
+ case OpRsh64Ux32:
+ return rewriteValueARM64_OpRsh64Ux32(v)
+ case OpRsh64Ux64:
+ return rewriteValueARM64_OpRsh64Ux64(v)
+ case OpRsh64Ux8:
+ return rewriteValueARM64_OpRsh64Ux8(v)
+ case OpRsh64x16:
+ return rewriteValueARM64_OpRsh64x16(v)
+ case OpRsh64x32:
+ return rewriteValueARM64_OpRsh64x32(v)
+ case OpRsh64x64:
+ return rewriteValueARM64_OpRsh64x64(v)
+ case OpRsh64x8:
+ return rewriteValueARM64_OpRsh64x8(v)
+ case OpRsh8Ux16:
+ return rewriteValueARM64_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValueARM64_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValueARM64_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValueARM64_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValueARM64_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValueARM64_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValueARM64_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValueARM64_OpRsh8x8(v)
+ case OpSelect0:
+ return rewriteValueARM64_OpSelect0(v)
+ case OpSelect1:
+ return rewriteValueARM64_OpSelect1(v)
+ case OpSignExt16to32:
+ v.Op = OpARM64MOVHreg
+ return true
+ case OpSignExt16to64:
+ v.Op = OpARM64MOVHreg
+ return true
+ case OpSignExt32to64:
+ v.Op = OpARM64MOVWreg
+ return true
+ case OpSignExt8to16:
+ v.Op = OpARM64MOVBreg
+ return true
+ case OpSignExt8to32:
+ v.Op = OpARM64MOVBreg
+ return true
+ case OpSignExt8to64:
+ v.Op = OpARM64MOVBreg
+ return true
+ case OpSlicemask:
+ return rewriteValueARM64_OpSlicemask(v)
+ case OpSqrt:
+ v.Op = OpARM64FSQRTD
+ return true
+ case OpStaticCall:
+ v.Op = OpARM64CALLstatic
+ return true
+ case OpStore:
+ return rewriteValueARM64_OpStore(v)
+ case OpSub16:
+ v.Op = OpARM64SUB
+ return true
+ case OpSub32:
+ v.Op = OpARM64SUB
+ return true
+ case OpSub32F:
+ v.Op = OpARM64FSUBS
+ return true
+ case OpSub64:
+ v.Op = OpARM64SUB
+ return true
+ case OpSub64F:
+ v.Op = OpARM64FSUBD
+ return true
+ case OpSub8:
+ v.Op = OpARM64SUB
+ return true
+ case OpSubPtr:
+ v.Op = OpARM64SUB
+ return true
+ case OpTrunc:
+ v.Op = OpARM64FRINTZD
+ return true
+ case OpTrunc16to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to32:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to8:
+ v.Op = OpCopy
+ return true
+ case OpWB:
+ v.Op = OpARM64LoweredWB
+ return true
+ case OpXor16:
+ v.Op = OpARM64XOR
+ return true
+ case OpXor32:
+ v.Op = OpARM64XOR
+ return true
+ case OpXor64:
+ v.Op = OpARM64XOR
+ return true
+ case OpXor8:
+ v.Op = OpARM64XOR
+ return true
+ case OpZero:
+ return rewriteValueARM64_OpZero(v)
+ case OpZeroExt16to32:
+ v.Op = OpARM64MOVHUreg
+ return true
+ case OpZeroExt16to64:
+ v.Op = OpARM64MOVHUreg
+ return true
+ case OpZeroExt32to64:
+ v.Op = OpARM64MOVWUreg
+ return true
+ case OpZeroExt8to16:
+ v.Op = OpARM64MOVBUreg
+ return true
+ case OpZeroExt8to32:
+ v.Op = OpARM64MOVBUreg
+ return true
+ case OpZeroExt8to64:
+ v.Op = OpARM64MOVBUreg
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ADCSflags(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] (ADCzerocarry <typ.UInt64> c))))
+ // result: (ADCSflags x y c)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpSelect1 || v_2.Type != types.TypeFlags {
+ break
+ }
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpARM64ADDSconstflags || auxIntToInt64(v_2_0.AuxInt) != -1 {
+ break
+ }
+ v_2_0_0 := v_2_0.Args[0]
+ if v_2_0_0.Op != OpARM64ADCzerocarry || v_2_0_0.Type != typ.UInt64 {
+ break
+ }
+ c := v_2_0_0.Args[0]
+ v.reset(OpARM64ADCSflags)
+ v.AddArg3(x, y, c)
+ return true
+ }
+ // match: (ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] (MOVDconst [0]))))
+ // result: (ADDSflags x y)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpSelect1 || v_2.Type != types.TypeFlags {
+ break
+ }
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpARM64ADDSconstflags || auxIntToInt64(v_2_0.AuxInt) != -1 {
+ break
+ }
+ v_2_0_0 := v_2_0.Args[0]
+ if v_2_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_2_0_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpARM64ADDSflags)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ADD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ADD x (MOVDconst [c]))
+ // result: (ADDconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADD a l:(MUL x y))
+ // cond: l.Uses==1 && clobber(l)
+ // result: (MADD a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ l := v_1
+ if l.Op != OpARM64MUL {
+ continue
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1 && clobber(l)) {
+ continue
+ }
+ v.reset(OpARM64MADD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD a l:(MNEG x y))
+ // cond: l.Uses==1 && clobber(l)
+ // result: (MSUB a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ l := v_1
+ if l.Op != OpARM64MNEG {
+ continue
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1 && clobber(l)) {
+ continue
+ }
+ v.reset(OpARM64MSUB)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD a l:(MULW x y))
+ // cond: a.Type.Size() != 8 && l.Uses==1 && clobber(l)
+ // result: (MADDW a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ l := v_1
+ if l.Op != OpARM64MULW {
+ continue
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(a.Type.Size() != 8 && l.Uses == 1 && clobber(l)) {
+ continue
+ }
+ v.reset(OpARM64MADDW)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD a l:(MNEGW x y))
+ // cond: a.Type.Size() != 8 && l.Uses==1 && clobber(l)
+ // result: (MSUBW a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ l := v_1
+ if l.Op != OpARM64MNEGW {
+ continue
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(a.Type.Size() != 8 && l.Uses == 1 && clobber(l)) {
+ continue
+ }
+ v.reset(OpARM64MSUBW)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (NEG y))
+ // result: (SUB x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64NEG {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpARM64SUB)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ADDshiftLL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ADDshiftRL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64ADDshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ADDshiftRA x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64ADDshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SLL x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> [cc] (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (ROR x (NEG <t> y))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt64 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL || v_1_0.Type != typ.UInt64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 63 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 63 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64ROR)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SRL <typ.UInt64> x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> [cc] (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (ROR x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SRL || v_0.Type != typ.UInt64 {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt64 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 63 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 63 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SLL x (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> [cc] (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (RORW x (NEG <t> y))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt32 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL || v_1_0.Type != typ.UInt32 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpARM64MOVWUreg || x != v_1_0_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 31 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 31 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64RORW)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> [cc] (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (RORW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SRL || v_0.Type != typ.UInt32 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64MOVWUreg {
+ continue
+ }
+ x := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt32 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 31 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 31 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ADDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDconst [off1] (MOVDaddr [off2] {sym} ptr))
+ // cond: is32Bit(off1+int64(off2))
+ // result: (MOVDaddr [int32(off1)+off2] {sym} ptr)
+ for {
+ off1 := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ if !(is32Bit(off1 + int64(off2))) {
+ break
+ }
+ v.reset(OpARM64MOVDaddr)
+ v.AuxInt = int32ToAuxInt(int32(off1) + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (ADDconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ADDconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [c+d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c + d)
+ return true
+ }
+ // match: (ADDconst [c] (ADDconst [d] x))
+ // result: (ADDconst [c+d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [c] (SUBconst [d] x))
+ // result: (ADDconst [c-d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SUBconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ADDshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ADDshiftLL (MOVDconst [c]) x [d])
+ // result: (ADDconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDshiftLL x (MOVDconst [c]) [d])
+ // result: (ADDconst x [int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDshiftLL [c] (SRLconst x [64-c]) x)
+ // result: (RORconst [64-c] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != 64-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64RORconst)
+ v.AuxInt = int64ToAuxInt(64 - c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDshiftLL <t> [c] (UBFX [bfc] x) x)
+ // cond: c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ // result: (RORWconst [32-c] x)
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFX {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if x != v_1 || !(c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)) {
+ break
+ }
+ v.reset(OpARM64RORWconst)
+ v.AuxInt = int64ToAuxInt(32 - c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDshiftLL <typ.UInt16> [8] (UBFX <typ.UInt16> [armBFAuxInt(8, 8)] x) x)
+ // result: (REV16W x)
+ for {
+ if v.Type != typ.UInt16 || auxIntToInt64(v.AuxInt) != 8 || v_0.Op != OpARM64UBFX || v_0.Type != typ.UInt16 || auxIntToArm64BitField(v_0.AuxInt) != armBFAuxInt(8, 8) {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64REV16W)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDshiftLL [c] (SRLconst x [64-c]) x2)
+ // result: (EXTRconst [64-c] x2 x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != 64-c {
+ break
+ }
+ x := v_0.Args[0]
+ x2 := v_1
+ v.reset(OpARM64EXTRconst)
+ v.AuxInt = int64ToAuxInt(64 - c)
+ v.AddArg2(x2, x)
+ return true
+ }
+ // match: (ADDshiftLL <t> [c] (UBFX [bfc] x) x2)
+ // cond: c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ // result: (EXTRWconst [32-c] x2 x)
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFX {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ x2 := v_1
+ if !(c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)) {
+ break
+ }
+ v.reset(OpARM64EXTRWconst)
+ v.AuxInt = int64ToAuxInt(32 - c)
+ v.AddArg2(x2, x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ADDshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDshiftRA (MOVDconst [c]) x [d])
+ // result: (ADDconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDshiftRA x (MOVDconst [c]) [d])
+ // result: (ADDconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ADDshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDshiftRL (MOVDconst [c]) x [d])
+ // result: (ADDconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADDshiftRL x (MOVDconst [c]) [d])
+ // result: (ADDconst x [int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDshiftRL [c] (SLLconst x [64-c]) x)
+ // result: (RORconst [ c] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 64-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64RORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x))
+ // cond: c < 32 && t.Size() == 4
+ // result: (RORWconst [c] x)
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 32-c {
+ break
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpARM64MOVWUreg || x != v_1.Args[0] || !(c < 32 && t.Size() == 4) {
+ break
+ }
+ v.reset(OpARM64RORWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64AND(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AND x (MOVDconst [c]))
+ // result: (ANDconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (AND x (MVN y))
+ // result: (BIC x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MVN {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpARM64BIC)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (AND x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ANDshiftLL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64ANDshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (AND x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ANDshiftRL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64ANDshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (AND x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ANDshiftRA x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64ANDshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ANDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ANDconst [0] _)
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ANDconst [-1] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [c&d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c & d)
+ return true
+ }
+ // match: (ANDconst [c] (ANDconst [d] x))
+ // result: (ANDconst [c&d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVWUreg x))
+ // result: (ANDconst [c&(1<<32-1)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & (1<<32 - 1))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVHUreg x))
+ // result: (ANDconst [c&(1<<16-1)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVHUreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & (1<<16 - 1))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVBUreg x))
+ // result: (ANDconst [c&(1<<8-1)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVBUreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & (1<<8 - 1))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [ac] (SLLconst [sc] x))
+ // cond: isARM64BFMask(sc, ac, sc)
+ // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x)
+ for {
+ ac := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, ac, sc)) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(ac, sc)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [ac] (SRLconst [sc] x))
+ // cond: isARM64BFMask(sc, ac, 0)
+ // result: (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x)
+ for {
+ ac := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, ac, 0)) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(ac, 0)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ANDshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDshiftLL (MOVDconst [c]) x [d])
+ // result: (ANDconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ANDshiftLL x (MOVDconst [c]) [d])
+ // result: (ANDconst x [int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDshiftLL y:(SLLconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ y := v_0
+ if y.Op != OpARM64SLLconst || auxIntToInt64(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ANDshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDshiftRA (MOVDconst [c]) x [d])
+ // result: (ANDconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ANDshiftRA x (MOVDconst [c]) [d])
+ // result: (ANDconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDshiftRA y:(SRAconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ y := v_0
+ if y.Op != OpARM64SRAconst || auxIntToInt64(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ANDshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDshiftRL (MOVDconst [c]) x [d])
+ // result: (ANDconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ANDshiftRL x (MOVDconst [c]) [d])
+ // result: (ANDconst x [int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDshiftRL y:(SRLconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ y := v_0
+ if y.Op != OpARM64SRLconst || auxIntToInt64(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64BIC(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BIC x (MOVDconst [c]))
+ // result: (ANDconst [^c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(^c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BIC x x)
+ // result: (MOVDconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (BIC x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (BICshiftLL x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64BICshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (BIC x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (BICshiftRL x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64BICshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (BIC x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (BICshiftRA x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64BICshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64BICshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BICshiftLL x (MOVDconst [c]) [d])
+ // result: (ANDconst x [^int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(^int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BICshiftLL (SLLconst x [c]) x [c])
+ // result: (MOVDconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64BICshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BICshiftRA x (MOVDconst [c]) [d])
+ // result: (ANDconst x [^(c>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(^(c >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BICshiftRA (SRAconst x [c]) x [c])
+ // result: (MOVDconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRAconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64BICshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (BICshiftRL x (MOVDconst [c]) [d])
+ // result: (ANDconst x [^int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(^int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BICshiftRL (SRLconst x [c]) x [c])
+ // result: (MOVDconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMN(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMN x (MOVDconst [c]))
+ // result: (CMNconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (CMN x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (CMNshiftLL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64CMNshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (CMN x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (CMNshiftRL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64CMNshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (CMN x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (CMNshiftRA x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64CMNshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMNW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMNW x (MOVDconst [c]))
+ // result: (CMNWconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64CMNWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMNWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMNWconst (MOVDconst [x]) [y])
+ // result: (FlagConstant [addFlags32(int32(x),y)])
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(addFlags32(int32(x), y))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMNconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMNconst (MOVDconst [x]) [y])
+ // result: (FlagConstant [addFlags64(x,y)])
+ for {
+ y := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(addFlags64(x, y))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMNshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMNshiftLL (MOVDconst [c]) x [d])
+ // result: (CMNconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftLL x (MOVDconst [c]) [d])
+ // result: (CMNconst x [int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMNshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMNshiftRA (MOVDconst [c]) x [d])
+ // result: (CMNconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftRA x (MOVDconst [c]) [d])
+ // result: (CMNconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = int64ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMNshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMNshiftRL (MOVDconst [c]) x [d])
+ // result: (CMNconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftRL x (MOVDconst [c]) [d])
+ // result: (CMNconst x [int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMP(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMP x (MOVDconst [c]))
+ // result: (CMPconst [c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64CMPconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMP (MOVDconst [c]) x)
+ // result: (InvertFlags (CMPconst [c] x))
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMP y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (CMPshiftLL x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64CMPshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (CMP x0:(SLLconst [c] y) x1)
+ // cond: clobberIfDead(x0)
+ // result: (InvertFlags (CMPshiftLL x1 y [c]))
+ for {
+ x0 := v_0
+ if x0.Op != OpARM64SLLconst {
+ break
+ }
+ c := auxIntToInt64(x0.AuxInt)
+ y := x0.Args[0]
+ x1 := v_1
+ if !(clobberIfDead(x0)) {
+ break
+ }
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPshiftLL, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg2(x1, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (CMPshiftRL x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64CMPshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (CMP x0:(SRLconst [c] y) x1)
+ // cond: clobberIfDead(x0)
+ // result: (InvertFlags (CMPshiftRL x1 y [c]))
+ for {
+ x0 := v_0
+ if x0.Op != OpARM64SRLconst {
+ break
+ }
+ c := auxIntToInt64(x0.AuxInt)
+ y := x0.Args[0]
+ x1 := v_1
+ if !(clobberIfDead(x0)) {
+ break
+ }
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPshiftRL, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg2(x1, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (CMPshiftRA x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64CMPshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (CMP x0:(SRAconst [c] y) x1)
+ // cond: clobberIfDead(x0)
+ // result: (InvertFlags (CMPshiftRA x1 y [c]))
+ for {
+ x0 := v_0
+ if x0.Op != OpARM64SRAconst {
+ break
+ }
+ c := auxIntToInt64(x0.AuxInt)
+ y := x0.Args[0]
+ x1 := v_1
+ if !(clobberIfDead(x0)) {
+ break
+ }
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPshiftRA, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg2(x1, y)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMPW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPW x (MOVDconst [c]))
+ // result: (CMPWconst [int32(c)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64CMPWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPW (MOVDconst [c]) x)
+ // result: (InvertFlags (CMPWconst [int32(c)] x))
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPW x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPW y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMPWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPWconst (MOVDconst [x]) [y])
+ // result: (FlagConstant [subFlags32(int32(x),y)])
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags32(int32(x), y))
+ return true
+ }
+ // match: (CMPWconst (MOVBUreg _) [c])
+ // cond: 0xff < c
+ // result: (FlagConstant [subFlags64(0,1)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARM64MOVBUreg || !(0xff < c) {
+ break
+ }
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags64(0, 1))
+ return true
+ }
+ // match: (CMPWconst (MOVHUreg _) [c])
+ // cond: 0xffff < c
+ // result: (FlagConstant [subFlags64(0,1)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARM64MOVHUreg || !(0xffff < c) {
+ break
+ }
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags64(0, 1))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMPconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPconst (MOVDconst [x]) [y])
+ // result: (FlagConstant [subFlags64(x,y)])
+ for {
+ y := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags64(x, y))
+ return true
+ }
+ // match: (CMPconst (MOVBUreg _) [c])
+ // cond: 0xff < c
+ // result: (FlagConstant [subFlags64(0,1)])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVBUreg || !(0xff < c) {
+ break
+ }
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags64(0, 1))
+ return true
+ }
+ // match: (CMPconst (MOVHUreg _) [c])
+ // cond: 0xffff < c
+ // result: (FlagConstant [subFlags64(0,1)])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVHUreg || !(0xffff < c) {
+ break
+ }
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags64(0, 1))
+ return true
+ }
+ // match: (CMPconst (MOVWUreg _) [c])
+ // cond: 0xffffffff < c
+ // result: (FlagConstant [subFlags64(0,1)])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVWUreg || !(0xffffffff < c) {
+ break
+ }
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags64(0, 1))
+ return true
+ }
+ // match: (CMPconst (ANDconst _ [m]) [n])
+ // cond: 0 <= m && m < n
+ // result: (FlagConstant [subFlags64(0,1)])
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ if !(0 <= m && m < n) {
+ break
+ }
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags64(0, 1))
+ return true
+ }
+ // match: (CMPconst (SRLconst _ [c]) [n])
+ // cond: 0 <= n && 0 < c && c <= 63 && (1<<uint64(64-c)) <= uint64(n)
+ // result: (FlagConstant [subFlags64(0,1)])
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(0 <= n && 0 < c && c <= 63 && (1<<uint64(64-c)) <= uint64(n)) {
+ break
+ }
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(subFlags64(0, 1))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMPshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPshiftLL (MOVDconst [c]) x [d])
+ // result: (InvertFlags (CMPconst [c] (SLLconst <x.Type> x [d])))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v1 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v1.AuxInt = int64ToAuxInt(d)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPshiftLL x (MOVDconst [c]) [d])
+ // result: (CMPconst x [int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64CMPconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMPshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPshiftRA (MOVDconst [c]) x [d])
+ // result: (InvertFlags (CMPconst [c] (SRAconst <x.Type> x [d])))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v1 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type)
+ v1.AuxInt = int64ToAuxInt(d)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPshiftRA x (MOVDconst [c]) [d])
+ // result: (CMPconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64CMPconst)
+ v.AuxInt = int64ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMPshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPshiftRL (MOVDconst [c]) x [d])
+ // result: (InvertFlags (CMPconst [c] (SRLconst <x.Type> x [d])))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v1 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type)
+ v1.AuxInt = int64ToAuxInt(d)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPshiftRL x (MOVDconst [c]) [d])
+ // result: (CMPconst x [int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64CMPconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CSEL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CSEL [cc] x (MOVDconst [0]) flag)
+ // result: (CSEL0 [cc] x flag)
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ flag := v_2
+ v.reset(OpARM64CSEL0)
+ v.AuxInt = opToAuxInt(cc)
+ v.AddArg2(x, flag)
+ return true
+ }
+ // match: (CSEL [cc] (MOVDconst [0]) y flag)
+ // result: (CSEL0 [arm64Negate(cc)] y flag)
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ y := v_1
+ flag := v_2
+ v.reset(OpARM64CSEL0)
+ v.AuxInt = opToAuxInt(arm64Negate(cc))
+ v.AddArg2(y, flag)
+ return true
+ }
+ // match: (CSEL [cc] x y (InvertFlags cmp))
+ // result: (CSEL [arm64Invert(cc)] x y cmp)
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARM64InvertFlags {
+ break
+ }
+ cmp := v_2.Args[0]
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(arm64Invert(cc))
+ v.AddArg3(x, y, cmp)
+ return true
+ }
+ // match: (CSEL [cc] x _ flag)
+ // cond: ccARM64Eval(cc, flag) > 0
+ // result: x
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ x := v_0
+ flag := v_2
+ if !(ccARM64Eval(cc, flag) > 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CSEL [cc] _ y flag)
+ // cond: ccARM64Eval(cc, flag) < 0
+ // result: y
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ y := v_1
+ flag := v_2
+ if !(ccARM64Eval(cc, flag) < 0) {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (CSEL [cc] x y (CMPWconst [0] boolval))
+ // cond: cc == OpARM64NotEqual && flagArg(boolval) != nil
+ // result: (CSEL [boolval.Op] x y flagArg(boolval))
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARM64CMPWconst || auxIntToInt32(v_2.AuxInt) != 0 {
+ break
+ }
+ boolval := v_2.Args[0]
+ if !(cc == OpARM64NotEqual && flagArg(boolval) != nil) {
+ break
+ }
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(boolval.Op)
+ v.AddArg3(x, y, flagArg(boolval))
+ return true
+ }
+ // match: (CSEL [cc] x y (CMPWconst [0] boolval))
+ // cond: cc == OpARM64Equal && flagArg(boolval) != nil
+ // result: (CSEL [arm64Negate(boolval.Op)] x y flagArg(boolval))
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ x := v_0
+ y := v_1
+ if v_2.Op != OpARM64CMPWconst || auxIntToInt32(v_2.AuxInt) != 0 {
+ break
+ }
+ boolval := v_2.Args[0]
+ if !(cc == OpARM64Equal && flagArg(boolval) != nil) {
+ break
+ }
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(arm64Negate(boolval.Op))
+ v.AddArg3(x, y, flagArg(boolval))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CSEL0(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CSEL0 [cc] x (InvertFlags cmp))
+ // result: (CSEL0 [arm64Invert(cc)] x cmp)
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64InvertFlags {
+ break
+ }
+ cmp := v_1.Args[0]
+ v.reset(OpARM64CSEL0)
+ v.AuxInt = opToAuxInt(arm64Invert(cc))
+ v.AddArg2(x, cmp)
+ return true
+ }
+ // match: (CSEL0 [cc] x flag)
+ // cond: ccARM64Eval(cc, flag) > 0
+ // result: x
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ x := v_0
+ flag := v_1
+ if !(ccARM64Eval(cc, flag) > 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (CSEL0 [cc] _ flag)
+ // cond: ccARM64Eval(cc, flag) < 0
+ // result: (MOVDconst [0])
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ flag := v_1
+ if !(ccARM64Eval(cc, flag) < 0) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (CSEL0 [cc] x (CMPWconst [0] boolval))
+ // cond: cc == OpARM64NotEqual && flagArg(boolval) != nil
+ // result: (CSEL0 [boolval.Op] x flagArg(boolval))
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64CMPWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ boolval := v_1.Args[0]
+ if !(cc == OpARM64NotEqual && flagArg(boolval) != nil) {
+ break
+ }
+ v.reset(OpARM64CSEL0)
+ v.AuxInt = opToAuxInt(boolval.Op)
+ v.AddArg2(x, flagArg(boolval))
+ return true
+ }
+ // match: (CSEL0 [cc] x (CMPWconst [0] boolval))
+ // cond: cc == OpARM64Equal && flagArg(boolval) != nil
+ // result: (CSEL0 [arm64Negate(boolval.Op)] x flagArg(boolval))
+ for {
+ cc := auxIntToOp(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64CMPWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ boolval := v_1.Args[0]
+ if !(cc == OpARM64Equal && flagArg(boolval) != nil) {
+ break
+ }
+ v.reset(OpARM64CSEL0)
+ v.AuxInt = opToAuxInt(arm64Negate(boolval.Op))
+ v.AddArg2(x, flagArg(boolval))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64DIV(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (DIV (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
+ // result: (MOVDconst [c/d])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c / d)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64DIVW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (DIVW (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
+ // result: (MOVDconst [int64(int32(c)/int32(d))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(c) / int32(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64EON(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (EON x (MOVDconst [c]))
+ // result: (XORconst [^c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(^c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (EON x x)
+ // result: (MOVDconst [-1])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (EON x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (EONshiftLL x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64EONshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (EON x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (EONshiftRL x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64EONshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (EON x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (EONshiftRA x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64EONshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64EONshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (EONshiftLL x (MOVDconst [c]) [d])
+ // result: (XORconst x [^int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(^int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (EONshiftLL (SLLconst x [c]) x [c])
+ // result: (MOVDconst [-1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64EONshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (EONshiftRA x (MOVDconst [c]) [d])
+ // result: (XORconst x [^(c>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(^(c >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (EONshiftRA (SRAconst x [c]) x [c])
+ // result: (MOVDconst [-1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRAconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64EONshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (EONshiftRL x (MOVDconst [c]) [d])
+ // result: (XORconst x [^int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(^int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (EONshiftRL (SRLconst x [c]) x [c])
+ // result: (MOVDconst [-1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64Equal(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Equal (FlagConstant [fc]))
+ // result: (MOVDconst [b2i(fc.eq())])
+ for {
+ if v_0.Op != OpARM64FlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(fc.eq()))
+ return true
+ }
+ // match: (Equal (InvertFlags x))
+ // result: (Equal x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64Equal)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FADDD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FADDD a (FMULD x y))
+ // result: (FMADDD a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ if v_1.Op != OpARM64FMULD {
+ continue
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ v.reset(OpARM64FMADDD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ // match: (FADDD a (FNMULD x y))
+ // result: (FMSUBD a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ if v_1.Op != OpARM64FNMULD {
+ continue
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ v.reset(OpARM64FMSUBD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FADDS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FADDS a (FMULS x y))
+ // result: (FMADDS a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ if v_1.Op != OpARM64FMULS {
+ continue
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ v.reset(OpARM64FMADDS)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ // match: (FADDS a (FNMULS x y))
+ // result: (FMSUBS a x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ a := v_0
+ if v_1.Op != OpARM64FNMULS {
+ continue
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ v.reset(OpARM64FMSUBS)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FCMPD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (FCMPD x (FMOVDconst [0]))
+ // result: (FCMPD0 x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64FMOVDconst || auxIntToFloat64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpARM64FCMPD0)
+ v.AddArg(x)
+ return true
+ }
+ // match: (FCMPD (FMOVDconst [0]) x)
+ // result: (InvertFlags (FCMPD0 x))
+ for {
+ if v_0.Op != OpARM64FMOVDconst || auxIntToFloat64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64FCMPD0, types.TypeFlags)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FCMPS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (FCMPS x (FMOVSconst [0]))
+ // result: (FCMPS0 x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64FMOVSconst || auxIntToFloat64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpARM64FCMPS0)
+ v.AddArg(x)
+ return true
+ }
+ // match: (FCMPS (FMOVSconst [0]) x)
+ // result: (InvertFlags (FCMPS0 x))
+ for {
+ if v_0.Op != OpARM64FMOVSconst || auxIntToFloat64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpARM64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpARM64FCMPS0, types.TypeFlags)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMOVDfpgp(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (FMOVDfpgp <t> (Arg [off] {sym}))
+ // result: @b.Func.Entry (Arg <t> [off] {sym})
+ for {
+ t := v.Type
+ if v_0.Op != OpArg {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ b = b.Func.Entry
+ v0 := b.NewValue0(v.Pos, OpArg, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMOVDgpfp(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (FMOVDgpfp <t> (Arg [off] {sym}))
+ // result: @b.Func.Entry (Arg <t> [off] {sym})
+ for {
+ t := v.Type
+ if v_0.Op != OpArg {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ b = b.Func.Entry
+ v0 := b.NewValue0(v.Pos, OpArg, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMOVDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (FMOVDload [off] {sym} ptr (MOVDstore [off] {sym} ptr val _))
+ // result: (FMOVDgpfp val)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ val := v_1.Args[1]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ v.reset(OpARM64FMOVDgpfp)
+ v.AddArg(val)
+ return true
+ }
+ // match: (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (FMOVDload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64FMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (FMOVDload [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (FMOVDloadidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64FMOVDloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64FMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMOVDloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVDloadidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (FMOVDload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64FMOVDload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (FMOVDloadidx (MOVDconst [c]) ptr mem)
+ // cond: is32Bit(c)
+ // result: (FMOVDload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64FMOVDload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMOVDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (FMOVDstore [off] {sym} ptr (FMOVDgpfp val) mem)
+ // result: (MOVDstore [off] {sym} ptr val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64FMOVDgpfp {
+ break
+ }
+ val := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (FMOVDstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64FMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (FMOVDstore [off] {sym} (ADD ptr idx) val mem)
+ // cond: off == 0 && sym == nil
+ // result: (FMOVDstoreidx ptr idx val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64FMOVDstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64FMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMOVDstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVDstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is32Bit(c)
+ // result: (FMOVDstore [int32(c)] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64FMOVDstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (FMOVDstoreidx (MOVDconst [c]) idx val mem)
+ // cond: is32Bit(c)
+ // result: (FMOVDstore [int32(c)] idx val mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ idx := v_1
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64FMOVDstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(idx, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMOVSload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (FMOVSload [off] {sym} ptr (MOVWstore [off] {sym} ptr val _))
+ // result: (FMOVSgpfp val)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVWstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ val := v_1.Args[1]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ v.reset(OpARM64FMOVSgpfp)
+ v.AddArg(val)
+ return true
+ }
+ // match: (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (FMOVSload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64FMOVSload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (FMOVSload [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (FMOVSloadidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64FMOVSloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64FMOVSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMOVSloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVSloadidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (FMOVSload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64FMOVSload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (FMOVSloadidx (MOVDconst [c]) ptr mem)
+ // cond: is32Bit(c)
+ // result: (FMOVSload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64FMOVSload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMOVSstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (FMOVSstore [off] {sym} ptr (FMOVSgpfp val) mem)
+ // result: (MOVWstore [off] {sym} ptr val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64FMOVSgpfp {
+ break
+ }
+ val := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (FMOVSstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64FMOVSstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (FMOVSstore [off] {sym} (ADD ptr idx) val mem)
+ // cond: off == 0 && sym == nil
+ // result: (FMOVSstoreidx ptr idx val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64FMOVSstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64FMOVSstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMOVSstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVSstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is32Bit(c)
+ // result: (FMOVSstore [int32(c)] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64FMOVSstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (FMOVSstoreidx (MOVDconst [c]) idx val mem)
+ // cond: is32Bit(c)
+ // result: (FMOVSstore [int32(c)] idx val mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ idx := v_1
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64FMOVSstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(idx, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMULD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMULD (FNEGD x) y)
+ // result: (FNMULD x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64FNEGD {
+ continue
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpARM64FNMULD)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FMULS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMULS (FNEGS x) y)
+ // result: (FNMULS x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64FNEGS {
+ continue
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpARM64FNMULS)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FNEGD(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (FNEGD (FMULD x y))
+ // result: (FNMULD x y)
+ for {
+ if v_0.Op != OpARM64FMULD {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpARM64FNMULD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (FNEGD (FNMULD x y))
+ // result: (FMULD x y)
+ for {
+ if v_0.Op != OpARM64FNMULD {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpARM64FMULD)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FNEGS(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (FNEGS (FMULS x y))
+ // result: (FNMULS x y)
+ for {
+ if v_0.Op != OpARM64FMULS {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpARM64FNMULS)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (FNEGS (FNMULS x y))
+ // result: (FMULS x y)
+ for {
+ if v_0.Op != OpARM64FNMULS {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpARM64FMULS)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FNMULD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FNMULD (FNEGD x) y)
+ // result: (FMULD x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64FNEGD {
+ continue
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpARM64FMULD)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FNMULS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FNMULS (FNEGS x) y)
+ // result: (FMULS x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64FNEGS {
+ continue
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpARM64FMULS)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FSUBD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FSUBD a (FMULD x y))
+ // result: (FMSUBD a x y)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64FMULD {
+ break
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ v.reset(OpARM64FMSUBD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (FSUBD (FMULD x y) a)
+ // result: (FNMSUBD a x y)
+ for {
+ if v_0.Op != OpARM64FMULD {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ a := v_1
+ v.reset(OpARM64FNMSUBD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (FSUBD a (FNMULD x y))
+ // result: (FMADDD a x y)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64FNMULD {
+ break
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ v.reset(OpARM64FMADDD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (FSUBD (FNMULD x y) a)
+ // result: (FNMADDD a x y)
+ for {
+ if v_0.Op != OpARM64FNMULD {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ a := v_1
+ v.reset(OpARM64FNMADDD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64FSUBS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FSUBS a (FMULS x y))
+ // result: (FMSUBS a x y)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64FMULS {
+ break
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ v.reset(OpARM64FMSUBS)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (FSUBS (FMULS x y) a)
+ // result: (FNMSUBS a x y)
+ for {
+ if v_0.Op != OpARM64FMULS {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ a := v_1
+ v.reset(OpARM64FNMSUBS)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (FSUBS a (FNMULS x y))
+ // result: (FMADDS a x y)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64FNMULS {
+ break
+ }
+ y := v_1.Args[1]
+ x := v_1.Args[0]
+ v.reset(OpARM64FMADDS)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (FSUBS (FNMULS x y) a)
+ // result: (FNMADDS a x y)
+ for {
+ if v_0.Op != OpARM64FNMULS {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ a := v_1
+ v.reset(OpARM64FNMADDS)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64GreaterEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (GreaterEqual (FlagConstant [fc]))
+ // result: (MOVDconst [b2i(fc.ge())])
+ for {
+ if v_0.Op != OpARM64FlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(fc.ge()))
+ return true
+ }
+ // match: (GreaterEqual (InvertFlags x))
+ // result: (LessEqual x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64LessEqual)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64GreaterEqualF(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (GreaterEqualF (InvertFlags x))
+ // result: (LessEqualF x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64LessEqualF)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64GreaterEqualU(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (GreaterEqualU (FlagConstant [fc]))
+ // result: (MOVDconst [b2i(fc.uge())])
+ for {
+ if v_0.Op != OpARM64FlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(fc.uge()))
+ return true
+ }
+ // match: (GreaterEqualU (InvertFlags x))
+ // result: (LessEqualU x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64LessEqualU)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64GreaterThan(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (GreaterThan (FlagConstant [fc]))
+ // result: (MOVDconst [b2i(fc.gt())])
+ for {
+ if v_0.Op != OpARM64FlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(fc.gt()))
+ return true
+ }
+ // match: (GreaterThan (InvertFlags x))
+ // result: (LessThan x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64LessThan)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64GreaterThanF(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (GreaterThanF (InvertFlags x))
+ // result: (LessThanF x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64LessThanF)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64GreaterThanU(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (GreaterThanU (FlagConstant [fc]))
+ // result: (MOVDconst [b2i(fc.ugt())])
+ for {
+ if v_0.Op != OpARM64FlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(fc.ugt()))
+ return true
+ }
+ // match: (GreaterThanU (InvertFlags x))
+ // result: (LessThanU x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64LessThanU)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64LessEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LessEqual (FlagConstant [fc]))
+ // result: (MOVDconst [b2i(fc.le())])
+ for {
+ if v_0.Op != OpARM64FlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(fc.le()))
+ return true
+ }
+ // match: (LessEqual (InvertFlags x))
+ // result: (GreaterEqual x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64GreaterEqual)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64LessEqualF(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LessEqualF (InvertFlags x))
+ // result: (GreaterEqualF x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64GreaterEqualF)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64LessEqualU(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LessEqualU (FlagConstant [fc]))
+ // result: (MOVDconst [b2i(fc.ule())])
+ for {
+ if v_0.Op != OpARM64FlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(fc.ule()))
+ return true
+ }
+ // match: (LessEqualU (InvertFlags x))
+ // result: (GreaterEqualU x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64GreaterEqualU)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64LessThan(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LessThan (FlagConstant [fc]))
+ // result: (MOVDconst [b2i(fc.lt())])
+ for {
+ if v_0.Op != OpARM64FlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(fc.lt()))
+ return true
+ }
+ // match: (LessThan (InvertFlags x))
+ // result: (GreaterThan x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64GreaterThan)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64LessThanF(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LessThanF (InvertFlags x))
+ // result: (GreaterThanF x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64GreaterThanF)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64LessThanU(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LessThanU (FlagConstant [fc]))
+ // result: (MOVDconst [b2i(fc.ult())])
+ for {
+ if v_0.Op != OpARM64FlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(fc.ult()))
+ return true
+ }
+ // match: (LessThanU (InvertFlags x))
+ // result: (GreaterThanU x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64GreaterThanU)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MADD(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MADD a x (MOVDconst [-1]))
+ // result: (SUB a x)
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != -1 {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADD a _ (MOVDconst [0]))
+ // result: a
+ for {
+ a := v_0
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(a)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [1]))
+ // result: (ADD a x)
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (ADDshiftLL a x [log64(c)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c-1) && c>=3
+ // result: (ADD a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c - 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c+1) && c>=7
+ // result: (SUB a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c + 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%3 == 0 && isPowerOfTwo64(c/3)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%5 == 0 && isPowerOfTwo64(c/5)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 5))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%7 == 0 && isPowerOfTwo64(c/7)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%9 == 0 && isPowerOfTwo64(c/9)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 9))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [-1]) x)
+ // result: (SUB a x)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 {
+ break
+ }
+ x := v_2
+ v.reset(OpARM64SUB)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADD a (MOVDconst [0]) _)
+ // result: a
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(a)
+ return true
+ }
+ // match: (MADD a (MOVDconst [1]) x)
+ // result: (ADD a x)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ x := v_2
+ v.reset(OpARM64ADD)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c)
+ // result: (ADDshiftLL a x [log64(c)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c-1) && c>=3
+ // result: (ADD a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c - 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c+1) && c>=7
+ // result: (SUB a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c + 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%3 == 0 && isPowerOfTwo64(c/3)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%5 == 0 && isPowerOfTwo64(c/5)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 5))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%7 == 0 && isPowerOfTwo64(c/7)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%9 == 0 && isPowerOfTwo64(c/9)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 9))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADD (MOVDconst [c]) x y)
+ // result: (ADDconst [c] (MUL <x.Type> x y))
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64MUL, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) (MOVDconst [d]))
+ // result: (ADDconst [c*d] a)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_2.AuxInt)
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c * d)
+ v.AddArg(a)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MADDW(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: int32(c)==-1
+ // result: (SUB a x)
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADDW a _ (MOVDconst [c]))
+ // cond: int32(c)==0
+ // result: a
+ for {
+ a := v_0
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(int32(c) == 0) {
+ break
+ }
+ v.copyOf(a)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: int32(c)==1
+ // result: (ADD a x)
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(int32(c) == 1) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (ADDshiftLL a x [log64(c)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c-1) && int32(c)>=3
+ // result: (ADD a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c-1) && int32(c) >= 3) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c - 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c+1) && int32(c)>=7
+ // result: (SUB a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c+1) && int32(c) >= 7) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c + 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 5))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 9))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: int32(c)==-1
+ // result: (SUB a x)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) _)
+ // cond: int32(c)==0
+ // result: a
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(int32(c) == 0) {
+ break
+ }
+ v.copyOf(a)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: int32(c)==1
+ // result: (ADD a x)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(int32(c) == 1) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c)
+ // result: (ADDshiftLL a x [log64(c)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c-1) && int32(c)>=3
+ // result: (ADD a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c-1) && int32(c) >= 3) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c - 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c+1) && int32(c)>=7
+ // result: (SUB a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c+1) && int32(c) >= 7) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c + 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 5))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 9))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MADDW (MOVDconst [c]) x y)
+ // result: (ADDconst [c] (MULW <x.Type> x y))
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64MULW, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) (MOVDconst [d]))
+ // result: (ADDconst [int64(int32(c)*int32(d))] a)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_2.AuxInt)
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(c) * int32(d)))
+ v.AddArg(a)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MNEG(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MNEG x (MOVDconst [-1]))
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (MNEG _ (MOVDconst [0]))
+ // result: (MOVDconst [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (MNEG x (MOVDconst [1]))
+ // result: (NEG x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MNEG x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (NEG (SLLconst <x.Type> [log64(c)] x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEG x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c-1) && c >= 3
+ // result: (NEG (ADDshiftLL <x.Type> x x [log64(c-1)]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c-1) && c >= 3) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c - 1))
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEG x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c+1) && c >= 7
+ // result: (NEG (ADDshiftLL <x.Type> (NEG <x.Type> x) x [log64(c+1)]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c+1) && c >= 7) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c + 1))
+ v1 := b.NewValue0(v.Pos, OpARM64NEG, x.Type)
+ v1.AddArg(x)
+ v0.AddArg2(v1, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEG x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3)
+ // result: (SLLconst <x.Type> [log64(c/3)] (SUBshiftLL <x.Type> x x [2]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%3 == 0 && isPowerOfTwo64(c/3)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.Type = x.Type
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEG x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5)
+ // result: (NEG (SLLconst <x.Type> [log64(c/5)] (ADDshiftLL <x.Type> x x [2])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%5 == 0 && isPowerOfTwo64(c/5)) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c / 5))
+ v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v1.AuxInt = int64ToAuxInt(2)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEG x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7)
+ // result: (SLLconst <x.Type> [log64(c/7)] (SUBshiftLL <x.Type> x x [3]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%7 == 0 && isPowerOfTwo64(c/7)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.Type = x.Type
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEG x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9)
+ // result: (NEG (SLLconst <x.Type> [log64(c/9)] (ADDshiftLL <x.Type> x x [3])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%9 == 0 && isPowerOfTwo64(c/9)) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c / 9))
+ v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v1.AuxInt = int64ToAuxInt(3)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEG (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [-c*d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-c * d)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MNEGW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MNEGW x (MOVDconst [c]))
+ // cond: int32(c)==-1
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(int32(c) == -1) {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (MNEGW _ (MOVDconst [c]))
+ // cond: int32(c)==0
+ // result: (MOVDconst [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(int32(c) == 0) {
+ continue
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (MNEGW x (MOVDconst [c]))
+ // cond: int32(c)==1
+ // result: (NEG x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(int32(c) == 1) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MNEGW x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (NEG (SLLconst <x.Type> [log64(c)] x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEGW x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c-1) && int32(c) >= 3
+ // result: (NEG (ADDshiftLL <x.Type> x x [log64(c-1)]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c-1) && int32(c) >= 3) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c - 1))
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEGW x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c+1) && int32(c) >= 7
+ // result: (NEG (ADDshiftLL <x.Type> (NEG <x.Type> x) x [log64(c+1)]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c+1) && int32(c) >= 7) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c + 1))
+ v1 := b.NewValue0(v.Pos, OpARM64NEG, x.Type)
+ v1.AddArg(x)
+ v0.AddArg2(v1, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEGW x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)
+ // result: (SLLconst <x.Type> [log64(c/3)] (SUBshiftLL <x.Type> x x [2]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.Type = x.Type
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEGW x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)
+ // result: (NEG (SLLconst <x.Type> [log64(c/5)] (ADDshiftLL <x.Type> x x [2])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c / 5))
+ v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v1.AuxInt = int64ToAuxInt(2)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEGW x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)
+ // result: (SLLconst <x.Type> [log64(c/7)] (SUBshiftLL <x.Type> x x [3]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.Type = x.Type
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEGW x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)
+ // result: (NEG (SLLconst <x.Type> [log64(c/9)] (ADDshiftLL <x.Type> x x [3])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c / 9))
+ v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v1.AuxInt = int64ToAuxInt(3)
+ v1.AddArg2(x, x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MNEGW (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [-int64(int32(c)*int32(d))])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-int64(int32(c) * int32(d)))
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOD (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
+ // result: (MOVDconst [c%d])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c % d)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MODW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MODW (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
+ // result: (MOVDconst [int64(int32(c)%int32(d))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(c) % int32(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVBUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBUload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUload [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVBUloadidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVBUloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUload [off] {sym} ptr (MOVBstorezero [off2] {sym2} ptr2 _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVDconst [0])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVBstorezero {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (MOVBUload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVDconst [int64(read8(sym, int64(off)))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(read8(sym, int64(off))))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVBUloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBUloadidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVBUload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVBUload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUloadidx (MOVDconst [c]) ptr mem)
+ // cond: is32Bit(c)
+ // result: (MOVBUload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVBUload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUloadidx ptr idx (MOVBstorezeroidx ptr2 idx2 _))
+ // cond: (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2))
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVBstorezeroidx {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVBUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVBUreg x:(MOVBUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg x:(MOVBUloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg x:(MOVBUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg (ANDconst [c] x))
+ // result: (ANDconst [c&(1<<8-1)] x)
+ for {
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & (1<<8 - 1))
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(uint8(c))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ return true
+ }
+ // match: (MOVBUreg x)
+ // cond: x.Type.IsBoolean()
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if !(x.Type.IsBoolean()) {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg (SLLconst [sc] x))
+ // cond: isARM64BFMask(sc, 1<<8-1, sc)
+ // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))] x)
+ for {
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<8-1, sc)) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg (SRLconst [sc] x))
+ // cond: isARM64BFMask(sc, 1<<8-1, 0)
+ // result: (UBFX [armBFAuxInt(sc, 8)] x)
+ for {
+ if v_0.Op != OpARM64SRLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<8-1, 0)) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 8))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVBload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVBload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVBloadidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVBloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off] {sym} ptr (MOVBstorezero [off2] {sym2} ptr2 _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVDconst [0])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVBstorezero {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVBloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBloadidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVBload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVBload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBloadidx (MOVDconst [c]) ptr mem)
+ // cond: is32Bit(c)
+ // result: (MOVBload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVBload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBloadidx ptr idx (MOVBstorezeroidx ptr2 idx2 _))
+ // cond: (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2))
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVBstorezeroidx {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVBreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVBreg x:(MOVBload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg x:(MOVBloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg x:(MOVBreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(int8(c))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int8(c)))
+ return true
+ }
+ // match: (MOVBreg (SLLconst [lc] x))
+ // cond: lc < 8
+ // result: (SBFIZ [armBFAuxInt(lc, 8-lc)] x)
+ for {
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ lc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(lc < 8) {
+ break
+ }
+ v.reset(OpARM64SBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, 8-lc))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVBstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} (ADD ptr idx) val mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVBstoreidx ptr idx val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVBstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // result: (MOVBstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpARM64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVBreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVBUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVHUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVWUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} ptr0 (SRLconst [8] w) x:(MOVBstore [i-1] {s} ptr1 w mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [8] w) x:(MOVBstoreidx ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstoreidx ptr1 idx1 w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 8 {
+ continue
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr1, idx1, w, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr0 (UBFX [armBFAuxInt(8, 8)] w) x:(MOVBstore [i-1] {s} ptr1 w mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64UBFX || auxIntToArm64BitField(v_1.AuxInt) != armBFAuxInt(8, 8) {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr0 idx0) (UBFX [armBFAuxInt(8, 8)] w) x:(MOVBstoreidx ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstoreidx ptr1 idx1 w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64UBFX || auxIntToArm64BitField(v_1.AuxInt) != armBFAuxInt(8, 8) {
+ continue
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr1, idx1, w, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr0 (UBFX [armBFAuxInt(8, 24)] w) x:(MOVBstore [i-1] {s} ptr1 w mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64UBFX || auxIntToArm64BitField(v_1.AuxInt) != armBFAuxInt(8, 24) {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr0 idx0) (UBFX [armBFAuxInt(8, 24)] w) x:(MOVBstoreidx ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstoreidx ptr1 idx1 w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64UBFX || auxIntToArm64BitField(v_1.AuxInt) != armBFAuxInt(8, 24) {
+ continue
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr1, idx1, w, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr0 (SRLconst [8] (MOVDreg w)) x:(MOVBstore [i-1] {s} ptr1 w mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 8 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64MOVDreg {
+ break
+ }
+ w := v_1_0.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [8] (MOVDreg w)) x:(MOVBstoreidx ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstoreidx ptr1 idx1 w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 8 {
+ continue
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64MOVDreg {
+ continue
+ }
+ w := v_1_0.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr1, idx1, w, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr0 (SRLconst [j] w) x:(MOVBstore [i-1] {s} ptr1 w0:(SRLconst [j-8] w) mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64SRLconst {
+ break
+ }
+ j := auxIntToInt64(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != OpARM64SRLconst || auxIntToInt64(w0.AuxInt) != j-8 || w != w0.Args[0] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [j] w) x:(MOVBstoreidx ptr1 idx1 w0:(SRLconst [j-8] w) mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstoreidx ptr1 idx1 w0 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64SRLconst {
+ continue
+ }
+ j := auxIntToInt64(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ w0 := x.Args[2]
+ if w0.Op != OpARM64SRLconst || auxIntToInt64(w0.AuxInt) != j-8 || w != w0.Args[0] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr1, idx1, w0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr0 (UBFX [bfc] w) x:(MOVBstore [i-1] {s} ptr1 w0:(UBFX [bfc2] w) mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && bfc.getARM64BFwidth() == 32 - bfc.getARM64BFlsb() && bfc2.getARM64BFwidth() == 32 - bfc2.getARM64BFlsb() && bfc2.getARM64BFlsb() == bfc.getARM64BFlsb() - 8 && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64UBFX {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != OpARM64UBFX {
+ break
+ }
+ bfc2 := auxIntToArm64BitField(w0.AuxInt)
+ if w != w0.Args[0] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && bfc.getARM64BFwidth() == 32-bfc.getARM64BFlsb() && bfc2.getARM64BFwidth() == 32-bfc2.getARM64BFlsb() && bfc2.getARM64BFlsb() == bfc.getARM64BFlsb()-8 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr0 idx0) (UBFX [bfc] w) x:(MOVBstoreidx ptr1 idx1 w0:(UBFX [bfc2] w) mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && bfc.getARM64BFwidth() == 32 - bfc.getARM64BFlsb() && bfc2.getARM64BFwidth() == 32 - bfc2.getARM64BFlsb() && bfc2.getARM64BFlsb() == bfc.getARM64BFlsb() - 8 && clobber(x)
+ // result: (MOVHstoreidx ptr1 idx1 w0 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64UBFX {
+ continue
+ }
+ bfc := auxIntToArm64BitField(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ w0 := x.Args[2]
+ if w0.Op != OpARM64UBFX {
+ continue
+ }
+ bfc2 := auxIntToArm64BitField(w0.AuxInt)
+ if w != w0.Args[0] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && bfc.getARM64BFwidth() == 32-bfc.getARM64BFlsb() && bfc2.getARM64BFwidth() == 32-bfc2.getARM64BFlsb() && bfc2.getARM64BFlsb() == bfc.getARM64BFlsb()-8 && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr1, idx1, w0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr0 (SRLconst [j] (MOVDreg w)) x:(MOVBstore [i-1] {s} ptr1 w0:(SRLconst [j-8] (MOVDreg w)) mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64SRLconst {
+ break
+ }
+ j := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64MOVDreg {
+ break
+ }
+ w := v_1_0.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != OpARM64SRLconst || auxIntToInt64(w0.AuxInt) != j-8 {
+ break
+ }
+ w0_0 := w0.Args[0]
+ if w0_0.Op != OpARM64MOVDreg || w != w0_0.Args[0] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [j] (MOVDreg w)) x:(MOVBstoreidx ptr1 idx1 w0:(SRLconst [j-8] (MOVDreg w)) mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstoreidx ptr1 idx1 w0 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64SRLconst {
+ continue
+ }
+ j := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64MOVDreg {
+ continue
+ }
+ w := v_1_0.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ w0 := x.Args[2]
+ if w0.Op != OpARM64SRLconst || auxIntToInt64(w0.AuxInt) != j-8 {
+ continue
+ }
+ w0_0 := w0.Args[0]
+ if w0_0.Op != OpARM64MOVDreg || w != w0_0.Args[0] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr1, idx1, w0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr w x0:(MOVBstore [i-1] {s} ptr (SRLconst [8] w) x1:(MOVBstore [i-2] {s} ptr (SRLconst [16] w) x2:(MOVBstore [i-3] {s} ptr (SRLconst [24] w) x3:(MOVBstore [i-4] {s} ptr (SRLconst [32] w) x4:(MOVBstore [i-5] {s} ptr (SRLconst [40] w) x5:(MOVBstore [i-6] {s} ptr (SRLconst [48] w) x6:(MOVBstore [i-7] {s} ptr (SRLconst [56] w) mem))))))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && clobber(x0, x1, x2, x3, x4, x5, x6)
+ // result: (MOVDstore [i-7] {s} ptr (REV <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpARM64MOVBstore || auxIntToInt32(x0.AuxInt) != i-1 || auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if ptr != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64SRLconst || auxIntToInt64(x0_1.AuxInt) != 8 || w != x0_1.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpARM64MOVBstore || auxIntToInt32(x1.AuxInt) != i-2 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64SRLconst || auxIntToInt64(x1_1.AuxInt) != 16 || w != x1_1.Args[0] {
+ break
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpARM64MOVBstore || auxIntToInt32(x2.AuxInt) != i-3 || auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[2]
+ if ptr != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64SRLconst || auxIntToInt64(x2_1.AuxInt) != 24 || w != x2_1.Args[0] {
+ break
+ }
+ x3 := x2.Args[2]
+ if x3.Op != OpARM64MOVBstore || auxIntToInt32(x3.AuxInt) != i-4 || auxToSym(x3.Aux) != s {
+ break
+ }
+ _ = x3.Args[2]
+ if ptr != x3.Args[0] {
+ break
+ }
+ x3_1 := x3.Args[1]
+ if x3_1.Op != OpARM64SRLconst || auxIntToInt64(x3_1.AuxInt) != 32 || w != x3_1.Args[0] {
+ break
+ }
+ x4 := x3.Args[2]
+ if x4.Op != OpARM64MOVBstore || auxIntToInt32(x4.AuxInt) != i-5 || auxToSym(x4.Aux) != s {
+ break
+ }
+ _ = x4.Args[2]
+ if ptr != x4.Args[0] {
+ break
+ }
+ x4_1 := x4.Args[1]
+ if x4_1.Op != OpARM64SRLconst || auxIntToInt64(x4_1.AuxInt) != 40 || w != x4_1.Args[0] {
+ break
+ }
+ x5 := x4.Args[2]
+ if x5.Op != OpARM64MOVBstore || auxIntToInt32(x5.AuxInt) != i-6 || auxToSym(x5.Aux) != s {
+ break
+ }
+ _ = x5.Args[2]
+ if ptr != x5.Args[0] {
+ break
+ }
+ x5_1 := x5.Args[1]
+ if x5_1.Op != OpARM64SRLconst || auxIntToInt64(x5_1.AuxInt) != 48 || w != x5_1.Args[0] {
+ break
+ }
+ x6 := x5.Args[2]
+ if x6.Op != OpARM64MOVBstore || auxIntToInt32(x6.AuxInt) != i-7 || auxToSym(x6.Aux) != s {
+ break
+ }
+ mem := x6.Args[2]
+ if ptr != x6.Args[0] {
+ break
+ }
+ x6_1 := x6.Args[1]
+ if x6_1.Op != OpARM64SRLconst || auxIntToInt64(x6_1.AuxInt) != 56 || w != x6_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && clobber(x0, x1, x2, x3, x4, x5, x6)) {
+ break
+ }
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(i - 7)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x6.Pos, OpARM64REV, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [7] {s} p w x0:(MOVBstore [6] {s} p (SRLconst [8] w) x1:(MOVBstore [5] {s} p (SRLconst [16] w) x2:(MOVBstore [4] {s} p (SRLconst [24] w) x3:(MOVBstore [3] {s} p (SRLconst [32] w) x4:(MOVBstore [2] {s} p (SRLconst [40] w) x5:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (SRLconst [48] w) x6:(MOVBstoreidx ptr0 idx0 (SRLconst [56] w) mem))))))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, x5, x6)
+ // result: (MOVDstoreidx ptr0 idx0 (REV <w.Type> w) mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 7 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpARM64MOVBstore || auxIntToInt32(x0.AuxInt) != 6 || auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64SRLconst || auxIntToInt64(x0_1.AuxInt) != 8 || w != x0_1.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpARM64MOVBstore || auxIntToInt32(x1.AuxInt) != 5 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ if p != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64SRLconst || auxIntToInt64(x1_1.AuxInt) != 16 || w != x1_1.Args[0] {
+ break
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpARM64MOVBstore || auxIntToInt32(x2.AuxInt) != 4 || auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[2]
+ if p != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64SRLconst || auxIntToInt64(x2_1.AuxInt) != 24 || w != x2_1.Args[0] {
+ break
+ }
+ x3 := x2.Args[2]
+ if x3.Op != OpARM64MOVBstore || auxIntToInt32(x3.AuxInt) != 3 || auxToSym(x3.Aux) != s {
+ break
+ }
+ _ = x3.Args[2]
+ if p != x3.Args[0] {
+ break
+ }
+ x3_1 := x3.Args[1]
+ if x3_1.Op != OpARM64SRLconst || auxIntToInt64(x3_1.AuxInt) != 32 || w != x3_1.Args[0] {
+ break
+ }
+ x4 := x3.Args[2]
+ if x4.Op != OpARM64MOVBstore || auxIntToInt32(x4.AuxInt) != 2 || auxToSym(x4.Aux) != s {
+ break
+ }
+ _ = x4.Args[2]
+ if p != x4.Args[0] {
+ break
+ }
+ x4_1 := x4.Args[1]
+ if x4_1.Op != OpARM64SRLconst || auxIntToInt64(x4_1.AuxInt) != 40 || w != x4_1.Args[0] {
+ break
+ }
+ x5 := x4.Args[2]
+ if x5.Op != OpARM64MOVBstore || auxIntToInt32(x5.AuxInt) != 1 || auxToSym(x5.Aux) != s {
+ break
+ }
+ _ = x5.Args[2]
+ p1 := x5.Args[0]
+ if p1.Op != OpARM64ADD {
+ break
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p1_0, p1_1 = _i0+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ x5_1 := x5.Args[1]
+ if x5_1.Op != OpARM64SRLconst || auxIntToInt64(x5_1.AuxInt) != 48 || w != x5_1.Args[0] {
+ continue
+ }
+ x6 := x5.Args[2]
+ if x6.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x6.Args[3]
+ ptr0 := x6.Args[0]
+ idx0 := x6.Args[1]
+ x6_2 := x6.Args[2]
+ if x6_2.Op != OpARM64SRLconst || auxIntToInt64(x6_2.AuxInt) != 56 || w != x6_2.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, x5, x6)) {
+ continue
+ }
+ v.reset(OpARM64MOVDstoreidx)
+ v0 := b.NewValue0(x5.Pos, OpARM64REV, w.Type)
+ v0.AddArg(w)
+ v.AddArg4(ptr0, idx0, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr w x0:(MOVBstore [i-1] {s} ptr (UBFX [armBFAuxInt(8, 24)] w) x1:(MOVBstore [i-2] {s} ptr (UBFX [armBFAuxInt(16, 16)] w) x2:(MOVBstore [i-3] {s} ptr (UBFX [armBFAuxInt(24, 8)] w) mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)
+ // result: (MOVWstore [i-3] {s} ptr (REVW <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpARM64MOVBstore || auxIntToInt32(x0.AuxInt) != i-1 || auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if ptr != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64UBFX || auxIntToArm64BitField(x0_1.AuxInt) != armBFAuxInt(8, 24) || w != x0_1.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpARM64MOVBstore || auxIntToInt32(x1.AuxInt) != i-2 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64UBFX || auxIntToArm64BitField(x1_1.AuxInt) != armBFAuxInt(16, 16) || w != x1_1.Args[0] {
+ break
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpARM64MOVBstore || auxIntToInt32(x2.AuxInt) != i-3 || auxToSym(x2.Aux) != s {
+ break
+ }
+ mem := x2.Args[2]
+ if ptr != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64UBFX || auxIntToArm64BitField(x2_1.AuxInt) != armBFAuxInt(24, 8) || w != x2_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 3)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x2.Pos, OpARM64REVW, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [3] {s} p w x0:(MOVBstore [2] {s} p (UBFX [armBFAuxInt(8, 24)] w) x1:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (UBFX [armBFAuxInt(16, 16)] w) x2:(MOVBstoreidx ptr0 idx0 (UBFX [armBFAuxInt(24, 8)] w) mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2)
+ // result: (MOVWstoreidx ptr0 idx0 (REVW <w.Type> w) mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 3 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpARM64MOVBstore || auxIntToInt32(x0.AuxInt) != 2 || auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64UBFX || auxIntToArm64BitField(x0_1.AuxInt) != armBFAuxInt(8, 24) || w != x0_1.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpARM64MOVBstore || auxIntToInt32(x1.AuxInt) != 1 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADD {
+ break
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p1_0, p1_1 = _i0+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64UBFX || auxIntToArm64BitField(x1_1.AuxInt) != armBFAuxInt(16, 16) || w != x1_1.Args[0] {
+ continue
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x2.Args[3]
+ ptr0 := x2.Args[0]
+ idx0 := x2.Args[1]
+ x2_2 := x2.Args[2]
+ if x2_2.Op != OpARM64UBFX || auxIntToArm64BitField(x2_2.AuxInt) != armBFAuxInt(24, 8) || w != x2_2.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2)) {
+ continue
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v0 := b.NewValue0(x1.Pos, OpARM64REVW, w.Type)
+ v0.AddArg(w)
+ v.AddArg4(ptr0, idx0, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr w x0:(MOVBstore [i-1] {s} ptr (SRLconst [8] (MOVDreg w)) x1:(MOVBstore [i-2] {s} ptr (SRLconst [16] (MOVDreg w)) x2:(MOVBstore [i-3] {s} ptr (SRLconst [24] (MOVDreg w)) mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)
+ // result: (MOVWstore [i-3] {s} ptr (REVW <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpARM64MOVBstore || auxIntToInt32(x0.AuxInt) != i-1 || auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if ptr != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64SRLconst || auxIntToInt64(x0_1.AuxInt) != 8 {
+ break
+ }
+ x0_1_0 := x0_1.Args[0]
+ if x0_1_0.Op != OpARM64MOVDreg || w != x0_1_0.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpARM64MOVBstore || auxIntToInt32(x1.AuxInt) != i-2 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64SRLconst || auxIntToInt64(x1_1.AuxInt) != 16 {
+ break
+ }
+ x1_1_0 := x1_1.Args[0]
+ if x1_1_0.Op != OpARM64MOVDreg || w != x1_1_0.Args[0] {
+ break
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpARM64MOVBstore || auxIntToInt32(x2.AuxInt) != i-3 || auxToSym(x2.Aux) != s {
+ break
+ }
+ mem := x2.Args[2]
+ if ptr != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64SRLconst || auxIntToInt64(x2_1.AuxInt) != 24 {
+ break
+ }
+ x2_1_0 := x2_1.Args[0]
+ if x2_1_0.Op != OpARM64MOVDreg || w != x2_1_0.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 3)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x2.Pos, OpARM64REVW, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [3] {s} p w x0:(MOVBstore [2] {s} p (SRLconst [8] (MOVDreg w)) x1:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (SRLconst [16] (MOVDreg w)) x2:(MOVBstoreidx ptr0 idx0 (SRLconst [24] (MOVDreg w)) mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2)
+ // result: (MOVWstoreidx ptr0 idx0 (REVW <w.Type> w) mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 3 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpARM64MOVBstore || auxIntToInt32(x0.AuxInt) != 2 || auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64SRLconst || auxIntToInt64(x0_1.AuxInt) != 8 {
+ break
+ }
+ x0_1_0 := x0_1.Args[0]
+ if x0_1_0.Op != OpARM64MOVDreg || w != x0_1_0.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpARM64MOVBstore || auxIntToInt32(x1.AuxInt) != 1 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADD {
+ break
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p1_0, p1_1 = _i0+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64SRLconst || auxIntToInt64(x1_1.AuxInt) != 16 {
+ continue
+ }
+ x1_1_0 := x1_1.Args[0]
+ if x1_1_0.Op != OpARM64MOVDreg || w != x1_1_0.Args[0] {
+ continue
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x2.Args[3]
+ ptr0 := x2.Args[0]
+ idx0 := x2.Args[1]
+ x2_2 := x2.Args[2]
+ if x2_2.Op != OpARM64SRLconst || auxIntToInt64(x2_2.AuxInt) != 24 {
+ continue
+ }
+ x2_2_0 := x2_2.Args[0]
+ if x2_2_0.Op != OpARM64MOVDreg || w != x2_2_0.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2)) {
+ continue
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v0 := b.NewValue0(x1.Pos, OpARM64REVW, w.Type)
+ v0.AddArg(w)
+ v.AddArg4(ptr0, idx0, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr w x0:(MOVBstore [i-1] {s} ptr (SRLconst [8] w) x1:(MOVBstore [i-2] {s} ptr (SRLconst [16] w) x2:(MOVBstore [i-3] {s} ptr (SRLconst [24] w) mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)
+ // result: (MOVWstore [i-3] {s} ptr (REVW <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpARM64MOVBstore || auxIntToInt32(x0.AuxInt) != i-1 || auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if ptr != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64SRLconst || auxIntToInt64(x0_1.AuxInt) != 8 || w != x0_1.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpARM64MOVBstore || auxIntToInt32(x1.AuxInt) != i-2 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64SRLconst || auxIntToInt64(x1_1.AuxInt) != 16 || w != x1_1.Args[0] {
+ break
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpARM64MOVBstore || auxIntToInt32(x2.AuxInt) != i-3 || auxToSym(x2.Aux) != s {
+ break
+ }
+ mem := x2.Args[2]
+ if ptr != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64SRLconst || auxIntToInt64(x2_1.AuxInt) != 24 || w != x2_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 3)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x2.Pos, OpARM64REVW, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [3] {s} p w x0:(MOVBstore [2] {s} p (SRLconst [8] w) x1:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (SRLconst [16] w) x2:(MOVBstoreidx ptr0 idx0 (SRLconst [24] w) mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2)
+ // result: (MOVWstoreidx ptr0 idx0 (REVW <w.Type> w) mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 3 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpARM64MOVBstore || auxIntToInt32(x0.AuxInt) != 2 || auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64SRLconst || auxIntToInt64(x0_1.AuxInt) != 8 || w != x0_1.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpARM64MOVBstore || auxIntToInt32(x1.AuxInt) != 1 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADD {
+ break
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p1_0, p1_1 = _i0+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64SRLconst || auxIntToInt64(x1_1.AuxInt) != 16 || w != x1_1.Args[0] {
+ continue
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x2.Args[3]
+ ptr0 := x2.Args[0]
+ idx0 := x2.Args[1]
+ x2_2 := x2.Args[2]
+ if x2_2.Op != OpARM64SRLconst || auxIntToInt64(x2_2.AuxInt) != 24 || w != x2_2.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2)) {
+ continue
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v0 := b.NewValue0(x1.Pos, OpARM64REVW, w.Type)
+ v0.AddArg(w)
+ v.AddArg4(ptr0, idx0, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (SRLconst [8] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if ptr != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpARM64SRLconst || auxIntToInt64(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x.Pos, OpARM64REV16W, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (SRLconst [8] w) mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr1 := v_0_0
+ idx1 := v_0_1
+ w := v_1
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr0 := x.Args[0]
+ idx0 := x.Args[1]
+ x_2 := x.Args[2]
+ if x_2.Op != OpARM64SRLconst || auxIntToInt64(x_2.AuxInt) != 8 || w != x_2.Args[0] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64REV16W, w.Type)
+ v0.AddArg(w)
+ v.AddArg4(ptr0, idx0, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (UBFX [armBFAuxInt(8, 8)] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if ptr != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpARM64UBFX || auxIntToArm64BitField(x_1.AuxInt) != armBFAuxInt(8, 8) || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x.Pos, OpARM64REV16W, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (UBFX [armBFAuxInt(8, 8)] w) mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr1 := v_0_0
+ idx1 := v_0_1
+ w := v_1
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr0 := x.Args[0]
+ idx0 := x.Args[1]
+ x_2 := x.Args[2]
+ if x_2.Op != OpARM64UBFX || auxIntToArm64BitField(x_2.AuxInt) != armBFAuxInt(8, 8) || w != x_2.Args[0] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64REV16W, w.Type)
+ v0.AddArg(w)
+ v.AddArg4(ptr0, idx0, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (SRLconst [8] (MOVDreg w)) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if ptr != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpARM64SRLconst || auxIntToInt64(x_1.AuxInt) != 8 {
+ break
+ }
+ x_1_0 := x_1.Args[0]
+ if x_1_0.Op != OpARM64MOVDreg || w != x_1_0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x.Pos, OpARM64REV16W, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (SRLconst [8] (MOVDreg w)) mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr1 := v_0_0
+ idx1 := v_0_1
+ w := v_1
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr0 := x.Args[0]
+ idx0 := x.Args[1]
+ x_2 := x.Args[2]
+ if x_2.Op != OpARM64SRLconst || auxIntToInt64(x_2.AuxInt) != 8 {
+ continue
+ }
+ x_2_0 := x_2.Args[0]
+ if x_2_0.Op != OpARM64MOVDreg || w != x_2_0.Args[0] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64REV16W, w.Type)
+ v0.AddArg(w)
+ v.AddArg4(ptr0, idx0, v0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (UBFX [armBFAuxInt(8, 24)] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpARM64MOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if ptr != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpARM64UBFX || auxIntToArm64BitField(x_1.AuxInt) != armBFAuxInt(8, 24) || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x.Pos, OpARM64REV16W, w.Type)
+ v0.AddArg(w)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (UBFX [armBFAuxInt(8, 24)] w) mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr1 := v_0_0
+ idx1 := v_0_1
+ w := v_1
+ x := v_2
+ if x.Op != OpARM64MOVBstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr0 := x.Args[0]
+ idx0 := x.Args[1]
+ x_2 := x.Args[2]
+ if x_2.Op != OpARM64UBFX || auxIntToArm64BitField(x_2.AuxInt) != armBFAuxInt(8, 24) || w != x_2.Args[0] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64REV16W, w.Type)
+ v0.AddArg(w)
+ v.AddArg4(ptr0, idx0, v0, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVBstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVBstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is32Bit(c)
+ // result: (MOVBstore [int32(c)] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstoreidx (MOVDconst [c]) idx val mem)
+ // cond: is32Bit(c)
+ // result: (MOVBstore [int32(c)] idx val mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ idx := v_1
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(idx, val, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVDconst [0]) mem)
+ // result: (MOVBstorezeroidx ptr idx mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 {
+ break
+ }
+ mem := v_3
+ v.reset(OpARM64MOVBstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVBreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVBreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVBUreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVBUreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVHreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVHreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVHUreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVHUreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVWreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVWUreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr (ADDconst [1] idx) (SRLconst [8] w) x:(MOVBstoreidx ptr idx w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVHstoreidx ptr idx w mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ idx := v_1.Args[0]
+ if v_2.Op != OpARM64SRLconst || auxIntToInt64(v_2.AuxInt) != 8 {
+ break
+ }
+ w := v_2.Args[0]
+ x := v_3
+ if x.Op != OpARM64MOVBstoreidx {
+ break
+ }
+ mem := x.Args[3]
+ if ptr != x.Args[0] || idx != x.Args[1] || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr, idx, w, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr (ADDconst [3] idx) w x0:(MOVBstoreidx ptr (ADDconst [2] idx) (UBFX [armBFAuxInt(8, 24)] w) x1:(MOVBstoreidx ptr (ADDconst [1] idx) (UBFX [armBFAuxInt(16, 16)] w) x2:(MOVBstoreidx ptr idx (UBFX [armBFAuxInt(24, 8)] w) mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)
+ // result: (MOVWstoreidx ptr idx (REVW <w.Type> w) mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADDconst || auxIntToInt64(v_1.AuxInt) != 3 {
+ break
+ }
+ idx := v_1.Args[0]
+ w := v_2
+ x0 := v_3
+ if x0.Op != OpARM64MOVBstoreidx {
+ break
+ }
+ _ = x0.Args[3]
+ if ptr != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64ADDconst || auxIntToInt64(x0_1.AuxInt) != 2 || idx != x0_1.Args[0] {
+ break
+ }
+ x0_2 := x0.Args[2]
+ if x0_2.Op != OpARM64UBFX || auxIntToArm64BitField(x0_2.AuxInt) != armBFAuxInt(8, 24) || w != x0_2.Args[0] {
+ break
+ }
+ x1 := x0.Args[3]
+ if x1.Op != OpARM64MOVBstoreidx {
+ break
+ }
+ _ = x1.Args[3]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 1 || idx != x1_1.Args[0] {
+ break
+ }
+ x1_2 := x1.Args[2]
+ if x1_2.Op != OpARM64UBFX || auxIntToArm64BitField(x1_2.AuxInt) != armBFAuxInt(16, 16) || w != x1_2.Args[0] {
+ break
+ }
+ x2 := x1.Args[3]
+ if x2.Op != OpARM64MOVBstoreidx {
+ break
+ }
+ mem := x2.Args[3]
+ if ptr != x2.Args[0] || idx != x2.Args[1] {
+ break
+ }
+ x2_2 := x2.Args[2]
+ if x2_2.Op != OpARM64UBFX || auxIntToArm64BitField(x2_2.AuxInt) != armBFAuxInt(24, 8) || w != x2_2.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)) {
+ break
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64REVW, w.Type)
+ v0.AddArg(w)
+ v.AddArg4(ptr, idx, v0, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx w x0:(MOVBstoreidx ptr (ADDconst [1] idx) (UBFX [armBFAuxInt(8, 24)] w) x1:(MOVBstoreidx ptr (ADDconst [2] idx) (UBFX [armBFAuxInt(16, 16)] w) x2:(MOVBstoreidx ptr (ADDconst [3] idx) (UBFX [armBFAuxInt(24, 8)] w) mem))))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)
+ // result: (MOVWstoreidx ptr idx w mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ w := v_2
+ x0 := v_3
+ if x0.Op != OpARM64MOVBstoreidx {
+ break
+ }
+ _ = x0.Args[3]
+ if ptr != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64ADDconst || auxIntToInt64(x0_1.AuxInt) != 1 || idx != x0_1.Args[0] {
+ break
+ }
+ x0_2 := x0.Args[2]
+ if x0_2.Op != OpARM64UBFX || auxIntToArm64BitField(x0_2.AuxInt) != armBFAuxInt(8, 24) || w != x0_2.Args[0] {
+ break
+ }
+ x1 := x0.Args[3]
+ if x1.Op != OpARM64MOVBstoreidx {
+ break
+ }
+ _ = x1.Args[3]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 2 || idx != x1_1.Args[0] {
+ break
+ }
+ x1_2 := x1.Args[2]
+ if x1_2.Op != OpARM64UBFX || auxIntToArm64BitField(x1_2.AuxInt) != armBFAuxInt(16, 16) || w != x1_2.Args[0] {
+ break
+ }
+ x2 := x1.Args[3]
+ if x2.Op != OpARM64MOVBstoreidx {
+ break
+ }
+ mem := x2.Args[3]
+ if ptr != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64ADDconst || auxIntToInt64(x2_1.AuxInt) != 3 || idx != x2_1.Args[0] {
+ break
+ }
+ x2_2 := x2.Args[2]
+ if x2_2.Op != OpARM64UBFX || auxIntToArm64BitField(x2_2.AuxInt) != armBFAuxInt(24, 8) || w != x2_2.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)) {
+ break
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v.AddArg4(ptr, idx, w, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr (ADDconst [1] idx) w x:(MOVBstoreidx ptr idx (UBFX [armBFAuxInt(8, 8)] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVHstoreidx ptr idx (REV16W <w.Type> w) mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ idx := v_1.Args[0]
+ w := v_2
+ x := v_3
+ if x.Op != OpARM64MOVBstoreidx {
+ break
+ }
+ mem := x.Args[3]
+ if ptr != x.Args[0] || idx != x.Args[1] {
+ break
+ }
+ x_2 := x.Args[2]
+ if x_2.Op != OpARM64UBFX || auxIntToArm64BitField(x_2.AuxInt) != armBFAuxInt(8, 8) || w != x_2.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64REV16W, w.Type)
+ v0.AddArg(w)
+ v.AddArg4(ptr, idx, v0, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx w x:(MOVBstoreidx ptr (ADDconst [1] idx) (UBFX [armBFAuxInt(8, 8)] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVHstoreidx ptr idx w mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ w := v_2
+ x := v_3
+ if x.Op != OpARM64MOVBstoreidx {
+ break
+ }
+ mem := x.Args[3]
+ if ptr != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpARM64ADDconst || auxIntToInt64(x_1.AuxInt) != 1 || idx != x_1.Args[0] {
+ break
+ }
+ x_2 := x.Args[2]
+ if x_2.Op != OpARM64UBFX || auxIntToArm64BitField(x_2.AuxInt) != armBFAuxInt(8, 8) || w != x_2.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr, idx, w, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVBstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstorezero [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVBstorezeroidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVBstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVBstorezero [i] {s} ptr0 x:(MOVBstorezero [j] {s} ptr1 mem))
+ // cond: x.Uses == 1 && areAdjacentOffsets(int64(i),int64(j),1) && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVHstorezero [int32(min(int64(i),int64(j)))] {s} ptr0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ x := v_1
+ if x.Op != OpARM64MOVBstorezero {
+ break
+ }
+ j := auxIntToInt32(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ ptr1 := x.Args[0]
+ if !(x.Uses == 1 && areAdjacentOffsets(int64(i), int64(j), 1) && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(int32(min(int64(i), int64(j))))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr0, mem)
+ return true
+ }
+ // match: (MOVBstorezero [1] {s} (ADD ptr0 idx0) x:(MOVBstorezeroidx ptr1 idx1 mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVHstorezeroidx ptr1 idx1 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ x := v_1
+ if x.Op != OpARM64MOVBstorezeroidx {
+ continue
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVHstorezeroidx)
+ v.AddArg3(ptr1, idx1, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVBstorezeroidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstorezeroidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVBstorezero [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstorezeroidx (MOVDconst [c]) idx mem)
+ // cond: is32Bit(c)
+ // result: (MOVBstorezero [int32(c)] idx mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ idx := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(idx, mem)
+ return true
+ }
+ // match: (MOVBstorezeroidx ptr (ADDconst [1] idx) x:(MOVBstorezeroidx ptr idx mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVHstorezeroidx ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ idx := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVBstorezeroidx {
+ break
+ }
+ mem := x.Args[2]
+ if ptr != x.Args[0] || idx != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVHstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVDload [off] {sym} ptr (FMOVDstore [off] {sym} ptr val _))
+ // result: (FMOVDfpgp val)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64FMOVDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ val := v_1.Args[1]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ v.reset(OpARM64FMOVDfpgp)
+ v.AddArg(val)
+ return true
+ }
+ // match: (MOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVDload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDload [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVDloadidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVDloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVDload [off] {sym} (ADDshiftLL [3] ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVDloadidx8 ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 3 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVDloadidx8)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDload [off] {sym} ptr (MOVDstorezero [off2] {sym2} ptr2 _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVDconst [0])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDstorezero {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (MOVDload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVDconst [int64(read64(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(read64(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVDloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDloadidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVDload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVDload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDloadidx (MOVDconst [c]) ptr mem)
+ // cond: is32Bit(c)
+ // result: (MOVDload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVDload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDloadidx ptr (SLLconst [3] idx) mem)
+ // result: (MOVDloadidx8 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 3 {
+ break
+ }
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVDloadidx8)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVDloadidx (SLLconst [3] idx) ptr mem)
+ // result: (MOVDloadidx8 ptr idx mem)
+ for {
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 3 {
+ break
+ }
+ idx := v_0.Args[0]
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARM64MOVDloadidx8)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVDloadidx ptr idx (MOVDstorezeroidx ptr2 idx2 _))
+ // cond: (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2))
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVDstorezeroidx {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVDloadidx8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDloadidx8 ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c<<3)
+ // result: (MOVDload [int32(c)<<3] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c << 3)) {
+ break
+ }
+ v.reset(OpARM64MOVDload)
+ v.AuxInt = int32ToAuxInt(int32(c) << 3)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDloadidx8 ptr idx (MOVDstorezeroidx8 ptr2 idx2 _))
+ // cond: isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2)
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVDstorezeroidx8 {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVDreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVDreg x)
+ // cond: x.Uses == 1
+ // result: (MOVDnop x)
+ for {
+ x := v_0
+ if !(x.Uses == 1) {
+ break
+ }
+ v.reset(OpARM64MOVDnop)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVDreg (MOVDconst [c]))
+ // result: (MOVDconst [c])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVDstore [off] {sym} ptr (FMOVDfpgp val) mem)
+ // result: (FMOVDstore [off] {sym} ptr val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64FMOVDfpgp {
+ break
+ }
+ val := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64FMOVDstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVDstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off] {sym} (ADD ptr idx) val mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVDstoreidx ptr idx val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVDstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off] {sym} (ADDshiftLL [3] ptr idx) val mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVDstoreidx8 ptr idx val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 3 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVDstoreidx8)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // result: (MOVDstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpARM64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVDstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is32Bit(c)
+ // result: (MOVDstore [int32(c)] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstoreidx (MOVDconst [c]) idx val mem)
+ // cond: is32Bit(c)
+ // result: (MOVDstore [int32(c)] idx val mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ idx := v_1
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(idx, val, mem)
+ return true
+ }
+ // match: (MOVDstoreidx ptr (SLLconst [3] idx) val mem)
+ // result: (MOVDstoreidx8 ptr idx val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 3 {
+ break
+ }
+ idx := v_1.Args[0]
+ val := v_2
+ mem := v_3
+ v.reset(OpARM64MOVDstoreidx8)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVDstoreidx (SLLconst [3] idx) ptr val mem)
+ // result: (MOVDstoreidx8 ptr idx val mem)
+ for {
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 3 {
+ break
+ }
+ idx := v_0.Args[0]
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ v.reset(OpARM64MOVDstoreidx8)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVDstoreidx ptr idx (MOVDconst [0]) mem)
+ // result: (MOVDstorezeroidx ptr idx mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 {
+ break
+ }
+ mem := v_3
+ v.reset(OpARM64MOVDstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVDstoreidx8(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstoreidx8 ptr (MOVDconst [c]) val mem)
+ // cond: is32Bit(c<<3)
+ // result: (MOVDstore [int32(c)<<3] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c << 3)) {
+ break
+ }
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(int32(c) << 3)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstoreidx8 ptr idx (MOVDconst [0]) mem)
+ // result: (MOVDstorezeroidx8 ptr idx mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 {
+ break
+ }
+ mem := v_3
+ v.reset(OpARM64MOVDstorezeroidx8)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVDstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVDstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVDstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDstorezero [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVDstorezeroidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVDstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVDstorezero [off] {sym} (ADDshiftLL [3] ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVDstorezeroidx8 ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 3 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVDstorezeroidx8)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVDstorezero [i] {s} ptr0 x:(MOVDstorezero [j] {s} ptr1 mem))
+ // cond: x.Uses == 1 && areAdjacentOffsets(int64(i),int64(j),8) && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVQstorezero [int32(min(int64(i),int64(j)))] {s} ptr0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ x := v_1
+ if x.Op != OpARM64MOVDstorezero {
+ break
+ }
+ j := auxIntToInt32(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ ptr1 := x.Args[0]
+ if !(x.Uses == 1 && areAdjacentOffsets(int64(i), int64(j), 8) && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVQstorezero)
+ v.AuxInt = int32ToAuxInt(int32(min(int64(i), int64(j))))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr0, mem)
+ return true
+ }
+ // match: (MOVDstorezero [8] {s} p0:(ADD ptr0 idx0) x:(MOVDstorezeroidx ptr1 idx1 mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVQstorezero [0] {s} p0 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 8 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ p0 := v_0
+ if p0.Op != OpARM64ADD {
+ break
+ }
+ _ = p0.Args[1]
+ p0_0 := p0.Args[0]
+ p0_1 := p0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p0_0, p0_1 = _i0+1, p0_1, p0_0 {
+ ptr0 := p0_0
+ idx0 := p0_1
+ x := v_1
+ if x.Op != OpARM64MOVDstorezeroidx {
+ continue
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVQstorezero)
+ v.AuxInt = int32ToAuxInt(0)
+ v.Aux = symToAux(s)
+ v.AddArg2(p0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVDstorezero [8] {s} p0:(ADDshiftLL [3] ptr0 idx0) x:(MOVDstorezeroidx8 ptr1 idx1 mem))
+ // cond: x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)
+ // result: (MOVQstorezero [0] {s} p0 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 8 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ p0 := v_0
+ if p0.Op != OpARM64ADDshiftLL || auxIntToInt64(p0.AuxInt) != 3 {
+ break
+ }
+ idx0 := p0.Args[1]
+ ptr0 := p0.Args[0]
+ x := v_1
+ if x.Op != OpARM64MOVDstorezeroidx8 {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if !(x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVQstorezero)
+ v.AuxInt = int32ToAuxInt(0)
+ v.Aux = symToAux(s)
+ v.AddArg2(p0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVDstorezeroidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstorezeroidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVDstorezero [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDstorezeroidx (MOVDconst [c]) idx mem)
+ // cond: is32Bit(c)
+ // result: (MOVDstorezero [int32(c)] idx mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ idx := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(idx, mem)
+ return true
+ }
+ // match: (MOVDstorezeroidx ptr (SLLconst [3] idx) mem)
+ // result: (MOVDstorezeroidx8 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 3 {
+ break
+ }
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVDstorezeroidx8)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVDstorezeroidx (SLLconst [3] idx) ptr mem)
+ // result: (MOVDstorezeroidx8 ptr idx mem)
+ for {
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 3 {
+ break
+ }
+ idx := v_0.Args[0]
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARM64MOVDstorezeroidx8)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVDstorezeroidx8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstorezeroidx8 ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c<<3)
+ // result: (MOVDstorezero [int32(c<<3)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c << 3)) {
+ break
+ }
+ v.reset(OpARM64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c << 3))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVHUload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUload [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVHUloadidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVHUloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHUload [off] {sym} (ADDshiftLL [1] ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVHUloadidx2 ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVHUloadidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUload [off] {sym} ptr (MOVHstorezero [off2] {sym2} ptr2 _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVDconst [0])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVHstorezero {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (MOVHUload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVDconst [int64(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(read16(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHUloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHUloadidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVHUload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVHUload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUloadidx (MOVDconst [c]) ptr mem)
+ // cond: is32Bit(c)
+ // result: (MOVHUload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVHUload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUloadidx ptr (SLLconst [1] idx) mem)
+ // result: (MOVHUloadidx2 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVHUloadidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHUloadidx ptr (ADD idx idx) mem)
+ // result: (MOVHUloadidx2 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADD {
+ break
+ }
+ idx := v_1.Args[1]
+ if idx != v_1.Args[0] {
+ break
+ }
+ mem := v_2
+ v.reset(OpARM64MOVHUloadidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHUloadidx (ADD idx idx) ptr mem)
+ // result: (MOVHUloadidx2 ptr idx mem)
+ for {
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ if idx != v_0.Args[0] {
+ break
+ }
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARM64MOVHUloadidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHUloadidx ptr idx (MOVHstorezeroidx ptr2 idx2 _))
+ // cond: (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2))
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVHstorezeroidx {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHUloadidx2(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHUloadidx2 ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c<<1)
+ // result: (MOVHUload [int32(c)<<1] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c << 1)) {
+ break
+ }
+ v.reset(OpARM64MOVHUload)
+ v.AuxInt = int32ToAuxInt(int32(c) << 1)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUloadidx2 ptr idx (MOVHstorezeroidx2 ptr2 idx2 _))
+ // cond: isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2)
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVHstorezeroidx2 {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVHUreg x:(MOVBUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVBUloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUloadidx2 _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUloadidx2 {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVBUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg (ANDconst [c] x))
+ // result: (ANDconst [c&(1<<16-1)] x)
+ for {
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & (1<<16 - 1))
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(uint16(c))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ return true
+ }
+ // match: (MOVHUreg (SLLconst [sc] x))
+ // cond: isARM64BFMask(sc, 1<<16-1, sc)
+ // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))] x)
+ for {
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<16-1, sc)) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg (SRLconst [sc] x))
+ // cond: isARM64BFMask(sc, 1<<16-1, 0)
+ // result: (UBFX [armBFAuxInt(sc, 16)] x)
+ for {
+ if v_0.Op != OpARM64SRLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<16-1, 0)) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 16))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVHload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVHload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHload [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVHloadidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVHloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHload [off] {sym} (ADDshiftLL [1] ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVHloadidx2 ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVHloadidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHload [off] {sym} ptr (MOVHstorezero [off2] {sym2} ptr2 _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVDconst [0])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVHstorezero {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHloadidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVHload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVHload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHloadidx (MOVDconst [c]) ptr mem)
+ // cond: is32Bit(c)
+ // result: (MOVHload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVHload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHloadidx ptr (SLLconst [1] idx) mem)
+ // result: (MOVHloadidx2 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVHloadidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHloadidx ptr (ADD idx idx) mem)
+ // result: (MOVHloadidx2 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADD {
+ break
+ }
+ idx := v_1.Args[1]
+ if idx != v_1.Args[0] {
+ break
+ }
+ mem := v_2
+ v.reset(OpARM64MOVHloadidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHloadidx (ADD idx idx) ptr mem)
+ // result: (MOVHloadidx2 ptr idx mem)
+ for {
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ if idx != v_0.Args[0] {
+ break
+ }
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARM64MOVHloadidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHloadidx ptr idx (MOVHstorezeroidx ptr2 idx2 _))
+ // cond: (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2))
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVHstorezeroidx {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHloadidx2(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHloadidx2 ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c<<1)
+ // result: (MOVHload [int32(c)<<1] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c << 1)) {
+ break
+ }
+ v.reset(OpARM64MOVHload)
+ v.AuxInt = int32ToAuxInt(int32(c) << 1)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHloadidx2 ptr idx (MOVHstorezeroidx2 ptr2 idx2 _))
+ // cond: isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2)
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVHstorezeroidx2 {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVHreg x:(MOVBload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHloadidx2 _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHloadidx2 {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(int16(c))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int16(c)))
+ return true
+ }
+ // match: (MOVHreg (SLLconst [lc] x))
+ // cond: lc < 16
+ // result: (SBFIZ [armBFAuxInt(lc, 16-lc)] x)
+ for {
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ lc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(lc < 16) {
+ break
+ }
+ v.reset(OpARM64SBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, 16-lc))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVHstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} (ADD ptr idx) val mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVHstoreidx ptr idx val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} (ADDshiftLL [1] ptr idx) val mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVHstoreidx2 ptr idx val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVHstoreidx2)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // result: (MOVHstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpARM64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHUreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVHUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVWUreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [i] {s} ptr0 (SRLconst [16] w) x:(MOVHstore [i-2] {s} ptr1 w mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVWstore [i-2] {s} ptr0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w, mem)
+ return true
+ }
+ // match: (MOVHstore [2] {s} (ADD ptr0 idx0) (SRLconst [16] w) x:(MOVHstoreidx ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVWstoreidx ptr1 idx1 w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 16 {
+ continue
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v.AddArg4(ptr1, idx1, w, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (SRLconst [16] w) x:(MOVHstoreidx2 ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)
+ // result: (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx0 := v_0.Args[1]
+ ptr0 := v_0.Args[0]
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstoreidx2 {
+ break
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, idx1.Type)
+ v0.AuxInt = int64ToAuxInt(1)
+ v0.AddArg(idx1)
+ v.AddArg4(ptr1, v0, w, mem)
+ return true
+ }
+ // match: (MOVHstore [i] {s} ptr0 (UBFX [armBFAuxInt(16, 16)] w) x:(MOVHstore [i-2] {s} ptr1 w mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVWstore [i-2] {s} ptr0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64UBFX || auxIntToArm64BitField(v_1.AuxInt) != armBFAuxInt(16, 16) {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w, mem)
+ return true
+ }
+ // match: (MOVHstore [2] {s} (ADD ptr0 idx0) (UBFX [armBFAuxInt(16, 16)] w) x:(MOVHstoreidx ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVWstoreidx ptr1 idx1 w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64UBFX || auxIntToArm64BitField(v_1.AuxInt) != armBFAuxInt(16, 16) {
+ continue
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v.AddArg4(ptr1, idx1, w, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (UBFX [armBFAuxInt(16, 16)] w) x:(MOVHstoreidx2 ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)
+ // result: (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx0 := v_0.Args[1]
+ ptr0 := v_0.Args[0]
+ if v_1.Op != OpARM64UBFX || auxIntToArm64BitField(v_1.AuxInt) != armBFAuxInt(16, 16) {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstoreidx2 {
+ break
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, idx1.Type)
+ v0.AuxInt = int64ToAuxInt(1)
+ v0.AddArg(idx1)
+ v.AddArg4(ptr1, v0, w, mem)
+ return true
+ }
+ // match: (MOVHstore [i] {s} ptr0 (SRLconst [16] (MOVDreg w)) x:(MOVHstore [i-2] {s} ptr1 w mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVWstore [i-2] {s} ptr0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 16 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64MOVDreg {
+ break
+ }
+ w := v_1_0.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w, mem)
+ return true
+ }
+ // match: (MOVHstore [2] {s} (ADD ptr0 idx0) (SRLconst [16] (MOVDreg w)) x:(MOVHstoreidx ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVWstoreidx ptr1 idx1 w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 16 {
+ continue
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64MOVDreg {
+ continue
+ }
+ w := v_1_0.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v.AddArg4(ptr1, idx1, w, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (SRLconst [16] (MOVDreg w)) x:(MOVHstoreidx2 ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)
+ // result: (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx0 := v_0.Args[1]
+ ptr0 := v_0.Args[0]
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 16 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64MOVDreg {
+ break
+ }
+ w := v_1_0.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstoreidx2 {
+ break
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, idx1.Type)
+ v0.AuxInt = int64ToAuxInt(1)
+ v0.AddArg(idx1)
+ v.AddArg4(ptr1, v0, w, mem)
+ return true
+ }
+ // match: (MOVHstore [i] {s} ptr0 (SRLconst [j] w) x:(MOVHstore [i-2] {s} ptr1 w0:(SRLconst [j-16] w) mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVWstore [i-2] {s} ptr0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64SRLconst {
+ break
+ }
+ j := auxIntToInt64(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != OpARM64SRLconst || auxIntToInt64(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w0, mem)
+ return true
+ }
+ // match: (MOVHstore [2] {s} (ADD ptr0 idx0) (SRLconst [j] w) x:(MOVHstoreidx ptr1 idx1 w0:(SRLconst [j-16] w) mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVWstoreidx ptr1 idx1 w0 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64SRLconst {
+ continue
+ }
+ j := auxIntToInt64(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ w0 := x.Args[2]
+ if w0.Op != OpARM64SRLconst || auxIntToInt64(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v.AddArg4(ptr1, idx1, w0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (SRLconst [j] w) x:(MOVHstoreidx2 ptr1 idx1 w0:(SRLconst [j-16] w) mem))
+ // cond: x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)
+ // result: (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w0 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx0 := v_0.Args[1]
+ ptr0 := v_0.Args[0]
+ if v_1.Op != OpARM64SRLconst {
+ break
+ }
+ j := auxIntToInt64(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstoreidx2 {
+ break
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ w0 := x.Args[2]
+ if w0.Op != OpARM64SRLconst || auxIntToInt64(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, idx1.Type)
+ v0.AuxInt = int64ToAuxInt(1)
+ v0.AddArg(idx1)
+ v.AddArg4(ptr1, v0, w0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is32Bit(c)
+ // result: (MOVHstore [int32(c)] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstoreidx (MOVDconst [c]) idx val mem)
+ // cond: is32Bit(c)
+ // result: (MOVHstore [int32(c)] idx val mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ idx := v_1
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(idx, val, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr (SLLconst [1] idx) val mem)
+ // result: (MOVHstoreidx2 ptr idx val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ idx := v_1.Args[0]
+ val := v_2
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx2)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr (ADD idx idx) val mem)
+ // result: (MOVHstoreidx2 ptr idx val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADD {
+ break
+ }
+ idx := v_1.Args[1]
+ if idx != v_1.Args[0] {
+ break
+ }
+ val := v_2
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx2)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVHstoreidx (SLLconst [1] idx) ptr val mem)
+ // result: (MOVHstoreidx2 ptr idx val mem)
+ for {
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx := v_0.Args[0]
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx2)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVHstoreidx (ADD idx idx) ptr val mem)
+ // result: (MOVHstoreidx2 ptr idx val mem)
+ for {
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ if idx != v_0.Args[0] {
+ break
+ }
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx2)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr idx (MOVDconst [0]) mem)
+ // result: (MOVHstorezeroidx ptr idx mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 {
+ break
+ }
+ mem := v_3
+ v.reset(OpARM64MOVHstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr idx (MOVHreg x) mem)
+ // result: (MOVHstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVHreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr idx (MOVHUreg x) mem)
+ // result: (MOVHstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVHUreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr idx (MOVWreg x) mem)
+ // result: (MOVHstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr idx (MOVWUreg x) mem)
+ // result: (MOVHstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr (ADDconst [2] idx) (SRLconst [16] w) x:(MOVHstoreidx ptr idx w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstoreidx ptr idx w mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADDconst || auxIntToInt64(v_1.AuxInt) != 2 {
+ break
+ }
+ idx := v_1.Args[0]
+ if v_2.Op != OpARM64SRLconst || auxIntToInt64(v_2.AuxInt) != 16 {
+ break
+ }
+ w := v_2.Args[0]
+ x := v_3
+ if x.Op != OpARM64MOVHstoreidx {
+ break
+ }
+ mem := x.Args[3]
+ if ptr != x.Args[0] || idx != x.Args[1] || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v.AddArg4(ptr, idx, w, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHstoreidx2(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstoreidx2 ptr (MOVDconst [c]) val mem)
+ // cond: is32Bit(c<<1)
+ // result: (MOVHstore [int32(c)<<1] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c << 1)) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(int32(c) << 1)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstoreidx2 ptr idx (MOVDconst [0]) mem)
+ // result: (MOVHstorezeroidx2 ptr idx mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 {
+ break
+ }
+ mem := v_3
+ v.reset(OpARM64MOVHstorezeroidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHstoreidx2 ptr idx (MOVHreg x) mem)
+ // result: (MOVHstoreidx2 ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVHreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx2)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVHstoreidx2 ptr idx (MOVHUreg x) mem)
+ // result: (MOVHstoreidx2 ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVHUreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx2)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVHstoreidx2 ptr idx (MOVWreg x) mem)
+ // result: (MOVHstoreidx2 ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx2)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVHstoreidx2 ptr idx (MOVWUreg x) mem)
+ // result: (MOVHstoreidx2 ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVHstoreidx2)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVHstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVHstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstorezero [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVHstorezeroidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVHstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHstorezero [off] {sym} (ADDshiftLL [1] ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVHstorezeroidx2 ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVHstorezeroidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHstorezero [i] {s} ptr0 x:(MOVHstorezero [j] {s} ptr1 mem))
+ // cond: x.Uses == 1 && areAdjacentOffsets(int64(i),int64(j),2) && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVWstorezero [int32(min(int64(i),int64(j)))] {s} ptr0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ x := v_1
+ if x.Op != OpARM64MOVHstorezero {
+ break
+ }
+ j := auxIntToInt32(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ ptr1 := x.Args[0]
+ if !(x.Uses == 1 && areAdjacentOffsets(int64(i), int64(j), 2) && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(int32(min(int64(i), int64(j))))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr0, mem)
+ return true
+ }
+ // match: (MOVHstorezero [2] {s} (ADD ptr0 idx0) x:(MOVHstorezeroidx ptr1 idx1 mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVWstorezeroidx ptr1 idx1 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ x := v_1
+ if x.Op != OpARM64MOVHstorezeroidx {
+ continue
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVWstorezeroidx)
+ v.AddArg3(ptr1, idx1, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVHstorezero [2] {s} (ADDshiftLL [1] ptr0 idx0) x:(MOVHstorezeroidx2 ptr1 idx1 mem))
+ // cond: x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)
+ // result: (MOVWstorezeroidx ptr1 (SLLconst <idx1.Type> [1] idx1) mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx0 := v_0.Args[1]
+ ptr0 := v_0.Args[0]
+ x := v_1
+ if x.Op != OpARM64MOVHstorezeroidx2 {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if !(x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstorezeroidx)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, idx1.Type)
+ v0.AuxInt = int64ToAuxInt(1)
+ v0.AddArg(idx1)
+ v.AddArg3(ptr1, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHstorezeroidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstorezeroidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVHstorezero [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstorezeroidx (MOVDconst [c]) idx mem)
+ // cond: is32Bit(c)
+ // result: (MOVHstorezero [int32(c)] idx mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ idx := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(idx, mem)
+ return true
+ }
+ // match: (MOVHstorezeroidx ptr (SLLconst [1] idx) mem)
+ // result: (MOVHstorezeroidx2 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVHstorezeroidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHstorezeroidx ptr (ADD idx idx) mem)
+ // result: (MOVHstorezeroidx2 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADD {
+ break
+ }
+ idx := v_1.Args[1]
+ if idx != v_1.Args[0] {
+ break
+ }
+ mem := v_2
+ v.reset(OpARM64MOVHstorezeroidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHstorezeroidx (SLLconst [1] idx) ptr mem)
+ // result: (MOVHstorezeroidx2 ptr idx mem)
+ for {
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ idx := v_0.Args[0]
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARM64MOVHstorezeroidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHstorezeroidx (ADD idx idx) ptr mem)
+ // result: (MOVHstorezeroidx2 ptr idx mem)
+ for {
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ if idx != v_0.Args[0] {
+ break
+ }
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARM64MOVHstorezeroidx2)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVHstorezeroidx ptr (ADDconst [2] idx) x:(MOVHstorezeroidx ptr idx mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWstorezeroidx ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADDconst || auxIntToInt64(v_1.AuxInt) != 2 {
+ break
+ }
+ idx := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVHstorezeroidx {
+ break
+ }
+ mem := x.Args[2]
+ if ptr != x.Args[0] || idx != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVWstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVHstorezeroidx2(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstorezeroidx2 ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c<<1)
+ // result: (MOVHstorezero [int32(c<<1)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c << 1)) {
+ break
+ }
+ v.reset(OpARM64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c << 1))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVQstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVQstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVQstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVQstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVQstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVQstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVQstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVWUload [off] {sym} ptr (FMOVSstore [off] {sym} ptr val _))
+ // result: (FMOVSfpgp val)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64FMOVSstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ val := v_1.Args[1]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ v.reset(OpARM64FMOVSfpgp)
+ v.AddArg(val)
+ return true
+ }
+ // match: (MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWUload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVWUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWUload [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVWUloadidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVWUloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWUload [off] {sym} (ADDshiftLL [2] ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVWUloadidx4 ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVWUloadidx4)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVWUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWUload [off] {sym} ptr (MOVWstorezero [off2] {sym2} ptr2 _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVDconst [0])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVWstorezero {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (MOVWUload [off] {sym} (SB) _)
+ // cond: symIsRO(sym)
+ // result: (MOVDconst [int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpSB || !(symIsRO(sym)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWUloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWUloadidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVWUload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVWUload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWUloadidx (MOVDconst [c]) ptr mem)
+ // cond: is32Bit(c)
+ // result: (MOVWUload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVWUload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWUloadidx ptr (SLLconst [2] idx) mem)
+ // result: (MOVWUloadidx4 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 2 {
+ break
+ }
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVWUloadidx4)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWUloadidx (SLLconst [2] idx) ptr mem)
+ // result: (MOVWUloadidx4 ptr idx mem)
+ for {
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx := v_0.Args[0]
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARM64MOVWUloadidx4)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWUloadidx ptr idx (MOVWstorezeroidx ptr2 idx2 _))
+ // cond: (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2))
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWstorezeroidx {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWUloadidx4(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWUloadidx4 ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c<<2)
+ // result: (MOVWUload [int32(c)<<2] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c << 2)) {
+ break
+ }
+ v.reset(OpARM64MOVWUload)
+ v.AuxInt = int32ToAuxInt(int32(c) << 2)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWUloadidx4 ptr idx (MOVWstorezeroidx4 ptr2 idx2 _))
+ // cond: isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2)
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWstorezeroidx4 {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVWUreg x:(MOVBUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVHUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVWUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVWUload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVBUloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVHUloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVWUloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVWUloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVHUloadidx2 _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUloadidx2 {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVWUloadidx4 _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVWUloadidx4 {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVBUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVHUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVWUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVWUreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg (ANDconst [c] x))
+ // result: (ANDconst [c&(1<<32-1)] x)
+ for {
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & (1<<32 - 1))
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(uint32(c))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ return true
+ }
+ // match: (MOVWUreg (SLLconst [sc] x))
+ // cond: isARM64BFMask(sc, 1<<32-1, sc)
+ // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))] x)
+ for {
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<32-1, sc)) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg (SRLconst [sc] x))
+ // cond: isARM64BFMask(sc, 1<<32-1, 0)
+ // result: (UBFX [armBFAuxInt(sc, 32)] x)
+ for {
+ if v_0.Op != OpARM64SRLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<32-1, 0)) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 32))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVWload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVWloadidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVWloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWload [off] {sym} (ADDshiftLL [2] ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVWloadidx4 ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVWloadidx4)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off] {sym} ptr (MOVWstorezero [off2] {sym2} ptr2 _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVDconst [0])
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVWstorezero {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWloadidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVWload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVWload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWloadidx (MOVDconst [c]) ptr mem)
+ // cond: is32Bit(c)
+ // result: (MOVWload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVWload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWloadidx ptr (SLLconst [2] idx) mem)
+ // result: (MOVWloadidx4 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 2 {
+ break
+ }
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVWloadidx4)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWloadidx (SLLconst [2] idx) ptr mem)
+ // result: (MOVWloadidx4 ptr idx mem)
+ for {
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx := v_0.Args[0]
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARM64MOVWloadidx4)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWloadidx ptr idx (MOVWstorezeroidx ptr2 idx2 _))
+ // cond: (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2))
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWstorezeroidx {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWloadidx4(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWloadidx4 ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c<<2)
+ // result: (MOVWload [int32(c)<<2] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c << 2)) {
+ break
+ }
+ v.reset(OpARM64MOVWload)
+ v.AuxInt = int32ToAuxInt(int32(c) << 2)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWloadidx4 ptr idx (MOVWstorezeroidx4 ptr2 idx2 _))
+ // cond: isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2)
+ // result: (MOVDconst [0])
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWstorezeroidx4 {
+ break
+ }
+ idx2 := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2)) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVWreg x:(MOVBload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVWload {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBUloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHUloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWloadidx _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVWloadidx {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHloadidx2 _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHloadidx2 {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHUloadidx2 _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHUloadidx2 {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWloadidx4 _ _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVWloadidx4 {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVBUreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVHreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpARM64MOVWreg {
+ break
+ }
+ v.reset(OpARM64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(int32(c))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(c)))
+ return true
+ }
+ // match: (MOVWreg (SLLconst [lc] x))
+ // cond: lc < 32
+ // result: (SBFIZ [armBFAuxInt(lc, 32-lc)] x)
+ for {
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ lc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(lc < 32) {
+ break
+ }
+ v.reset(OpARM64SBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, 32-lc))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVWstore [off] {sym} ptr (FMOVSfpgp val) mem)
+ // result: (FMOVSstore [off] {sym} ptr val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64FMOVSfpgp {
+ break
+ }
+ val := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64FMOVSstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} (ADD ptr idx) val mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVWstoreidx ptr idx val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVWstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} (ADDshiftLL [2] ptr idx) val mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVWstoreidx4 ptr idx val mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVWstoreidx4)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // result: (MOVWstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpARM64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWUreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} ptr0 (SRLconst [32] w) x:(MOVWstore [i-4] {s} ptr1 w mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVDstore [i-4] {s} ptr0 w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 32 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVWstore || auxIntToInt32(x.AuxInt) != i-4 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ if w != x.Args[1] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(i - 4)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w, mem)
+ return true
+ }
+ // match: (MOVWstore [4] {s} (ADD ptr0 idx0) (SRLconst [32] w) x:(MOVWstoreidx ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVDstoreidx ptr1 idx1 w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 32 {
+ continue
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVWstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVDstoreidx)
+ v.AddArg4(ptr1, idx1, w, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVWstore [4] {s} (ADDshiftLL [2] ptr0 idx0) (SRLconst [32] w) x:(MOVWstoreidx4 ptr1 idx1 w mem))
+ // cond: x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)
+ // result: (MOVDstoreidx ptr1 (SLLconst <idx1.Type> [2] idx1) w mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx0 := v_0.Args[1]
+ ptr0 := v_0.Args[0]
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != 32 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVWstoreidx4 {
+ break
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if w != x.Args[2] || !(x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVDstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, idx1.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg(idx1)
+ v.AddArg4(ptr1, v0, w, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} ptr0 (SRLconst [j] w) x:(MOVWstore [i-4] {s} ptr1 w0:(SRLconst [j-32] w) mem))
+ // cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVDstore [i-4] {s} ptr0 w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ if v_1.Op != OpARM64SRLconst {
+ break
+ }
+ j := auxIntToInt64(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVWstore || auxIntToInt32(x.AuxInt) != i-4 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ w0 := x.Args[1]
+ if w0.Op != OpARM64SRLconst || auxIntToInt64(w0.AuxInt) != j-32 || w != w0.Args[0] || !(x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(i - 4)
+ v.Aux = symToAux(s)
+ v.AddArg3(ptr0, w0, mem)
+ return true
+ }
+ // match: (MOVWstore [4] {s} (ADD ptr0 idx0) (SRLconst [j] w) x:(MOVWstoreidx ptr1 idx1 w0:(SRLconst [j-32] w) mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVDstoreidx ptr1 idx1 w0 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ if v_1.Op != OpARM64SRLconst {
+ continue
+ }
+ j := auxIntToInt64(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVWstoreidx {
+ continue
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ w0 := x.Args[2]
+ if w0.Op != OpARM64SRLconst || auxIntToInt64(w0.AuxInt) != j-32 || w != w0.Args[0] || !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVDstoreidx)
+ v.AddArg4(ptr1, idx1, w0, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVWstore [4] {s} (ADDshiftLL [2] ptr0 idx0) (SRLconst [j] w) x:(MOVWstoreidx4 ptr1 idx1 w0:(SRLconst [j-32] w) mem))
+ // cond: x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)
+ // result: (MOVDstoreidx ptr1 (SLLconst <idx1.Type> [2] idx1) w0 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx0 := v_0.Args[1]
+ ptr0 := v_0.Args[0]
+ if v_1.Op != OpARM64SRLconst {
+ break
+ }
+ j := auxIntToInt64(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVWstoreidx4 {
+ break
+ }
+ mem := x.Args[3]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ w0 := x.Args[2]
+ if w0.Op != OpARM64SRLconst || auxIntToInt64(w0.AuxInt) != j-32 || w != w0.Args[0] || !(x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVDstoreidx)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, idx1.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg(idx1)
+ v.AddArg4(ptr1, v0, w0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is32Bit(c)
+ // result: (MOVWstore [int32(c)] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx (MOVDconst [c]) idx val mem)
+ // cond: is32Bit(c)
+ // result: (MOVWstore [int32(c)] idx val mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ idx := v_1
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(idx, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx ptr (SLLconst [2] idx) val mem)
+ // result: (MOVWstoreidx4 ptr idx val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 2 {
+ break
+ }
+ idx := v_1.Args[0]
+ val := v_2
+ mem := v_3
+ v.reset(OpARM64MOVWstoreidx4)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx (SLLconst [2] idx) ptr val mem)
+ // result: (MOVWstoreidx4 ptr idx val mem)
+ for {
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx := v_0.Args[0]
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ v.reset(OpARM64MOVWstoreidx4)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx ptr idx (MOVDconst [0]) mem)
+ // result: (MOVWstorezeroidx ptr idx mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 {
+ break
+ }
+ mem := v_3
+ v.reset(OpARM64MOVWstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWstoreidx ptr idx (MOVWreg x) mem)
+ // result: (MOVWstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVWstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVWstoreidx ptr idx (MOVWUreg x) mem)
+ // result: (MOVWstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVWstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVWstoreidx ptr (ADDconst [4] idx) (SRLconst [32] w) x:(MOVWstoreidx ptr idx w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVDstoreidx ptr idx w mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADDconst || auxIntToInt64(v_1.AuxInt) != 4 {
+ break
+ }
+ idx := v_1.Args[0]
+ if v_2.Op != OpARM64SRLconst || auxIntToInt64(v_2.AuxInt) != 32 {
+ break
+ }
+ w := v_2.Args[0]
+ x := v_3
+ if x.Op != OpARM64MOVWstoreidx {
+ break
+ }
+ mem := x.Args[3]
+ if ptr != x.Args[0] || idx != x.Args[1] || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVDstoreidx)
+ v.AddArg4(ptr, idx, w, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWstoreidx4(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstoreidx4 ptr (MOVDconst [c]) val mem)
+ // cond: is32Bit(c<<2)
+ // result: (MOVWstore [int32(c)<<2] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is32Bit(c << 2)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(int32(c) << 2)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx4 ptr idx (MOVDconst [0]) mem)
+ // result: (MOVWstorezeroidx4 ptr idx mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 {
+ break
+ }
+ mem := v_3
+ v.reset(OpARM64MOVWstorezeroidx4)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWstoreidx4 ptr idx (MOVWreg x) mem)
+ // result: (MOVWstoreidx4 ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVWstoreidx4)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVWstoreidx4 ptr idx (MOVWUreg x) mem)
+ // result: (MOVWstoreidx4 ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpARM64MOVWstoreidx4)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVWstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstorezero [off] {sym} (ADD ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVWstorezeroidx ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVWstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWstorezero [off] {sym} (ADDshiftLL [2] ptr idx) mem)
+ // cond: off == 0 && sym == nil
+ // result: (MOVWstorezeroidx4 ptr idx mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx := v_0.Args[1]
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(off == 0 && sym == nil) {
+ break
+ }
+ v.reset(OpARM64MOVWstorezeroidx4)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWstorezero [i] {s} ptr0 x:(MOVWstorezero [j] {s} ptr1 mem))
+ // cond: x.Uses == 1 && areAdjacentOffsets(int64(i),int64(j),4) && isSamePtr(ptr0, ptr1) && clobber(x)
+ // result: (MOVDstorezero [int32(min(int64(i),int64(j)))] {s} ptr0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ ptr0 := v_0
+ x := v_1
+ if x.Op != OpARM64MOVWstorezero {
+ break
+ }
+ j := auxIntToInt32(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ ptr1 := x.Args[0]
+ if !(x.Uses == 1 && areAdjacentOffsets(int64(i), int64(j), 4) && isSamePtr(ptr0, ptr1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(int32(min(int64(i), int64(j))))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr0, mem)
+ return true
+ }
+ // match: (MOVWstorezero [4] {s} (ADD ptr0 idx0) x:(MOVWstorezeroidx ptr1 idx1 mem))
+ // cond: x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)
+ // result: (MOVDstorezeroidx ptr1 idx1 mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ ptr0 := v_0_0
+ idx0 := v_0_1
+ x := v_1
+ if x.Op != OpARM64MOVWstorezeroidx {
+ continue
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if !(x.Uses == 1 && s == nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x)) {
+ continue
+ }
+ v.reset(OpARM64MOVDstorezeroidx)
+ v.AddArg3(ptr1, idx1, mem)
+ return true
+ }
+ break
+ }
+ // match: (MOVWstorezero [4] {s} (ADDshiftLL [2] ptr0 idx0) x:(MOVWstorezeroidx4 ptr1 idx1 mem))
+ // cond: x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)
+ // result: (MOVDstorezeroidx ptr1 (SLLconst <idx1.Type> [2] idx1) mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 {
+ break
+ }
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDshiftLL || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx0 := v_0.Args[1]
+ ptr0 := v_0.Args[0]
+ x := v_1
+ if x.Op != OpARM64MOVWstorezeroidx4 {
+ break
+ }
+ mem := x.Args[2]
+ ptr1 := x.Args[0]
+ idx1 := x.Args[1]
+ if !(x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVDstorezeroidx)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, idx1.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg(idx1)
+ v.AddArg3(ptr1, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWstorezeroidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstorezeroidx ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (MOVWstorezero [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstorezeroidx (MOVDconst [c]) idx mem)
+ // cond: is32Bit(c)
+ // result: (MOVWstorezero [int32(c)] idx mem)
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ idx := v_1
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(idx, mem)
+ return true
+ }
+ // match: (MOVWstorezeroidx ptr (SLLconst [2] idx) mem)
+ // result: (MOVWstorezeroidx4 ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64SLLconst || auxIntToInt64(v_1.AuxInt) != 2 {
+ break
+ }
+ idx := v_1.Args[0]
+ mem := v_2
+ v.reset(OpARM64MOVWstorezeroidx4)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWstorezeroidx (SLLconst [2] idx) ptr mem)
+ // result: (MOVWstorezeroidx4 ptr idx mem)
+ for {
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 2 {
+ break
+ }
+ idx := v_0.Args[0]
+ ptr := v_1
+ mem := v_2
+ v.reset(OpARM64MOVWstorezeroidx4)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (MOVWstorezeroidx ptr (ADDconst [4] idx) x:(MOVWstorezeroidx ptr idx mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVDstorezeroidx ptr idx mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64ADDconst || auxIntToInt64(v_1.AuxInt) != 4 {
+ break
+ }
+ idx := v_1.Args[0]
+ x := v_2
+ if x.Op != OpARM64MOVWstorezeroidx {
+ break
+ }
+ mem := x.Args[2]
+ if ptr != x.Args[0] || idx != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpARM64MOVDstorezeroidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWstorezeroidx4(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstorezeroidx4 ptr (MOVDconst [c]) mem)
+ // cond: is32Bit(c<<2)
+ // result: (MOVWstorezero [int32(c<<2)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c << 2)) {
+ break
+ }
+ v.reset(OpARM64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(int32(c << 2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MSUB(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MSUB a x (MOVDconst [-1]))
+ // result: (ADD a x)
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != -1 {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUB a _ (MOVDconst [0]))
+ // result: a
+ for {
+ a := v_0
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(a)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [1]))
+ // result: (SUB a x)
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (SUBshiftLL a x [log64(c)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c-1) && c>=3
+ // result: (SUB a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c - 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c+1) && c>=7
+ // result: (ADD a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c + 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%3 == 0 && isPowerOfTwo64(c/3)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%5 == 0 && isPowerOfTwo64(c/5)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 5))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%7 == 0 && isPowerOfTwo64(c/7)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%9 == 0 && isPowerOfTwo64(c/9)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 9))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [-1]) x)
+ // result: (ADD a x)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 {
+ break
+ }
+ x := v_2
+ v.reset(OpARM64ADD)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [0]) _)
+ // result: a
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(a)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [1]) x)
+ // result: (SUB a x)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ x := v_2
+ v.reset(OpARM64SUB)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c)
+ // result: (SUBshiftLL a x [log64(c)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c-1) && c>=3
+ // result: (SUB a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c - 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c+1) && c>=7
+ // result: (ADD a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c + 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%3 == 0 && isPowerOfTwo64(c/3)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%5 == 0 && isPowerOfTwo64(c/5)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 5))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%7 == 0 && isPowerOfTwo64(c/7)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%9 == 0 && isPowerOfTwo64(c/9)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 9))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUB (MOVDconst [c]) x y)
+ // result: (ADDconst [c] (MNEG <x.Type> x y))
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64MNEG, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) (MOVDconst [d]))
+ // result: (SUBconst [c*d] a)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_2.AuxInt)
+ v.reset(OpARM64SUBconst)
+ v.AuxInt = int64ToAuxInt(c * d)
+ v.AddArg(a)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MSUBW(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: int32(c)==-1
+ // result: (ADD a x)
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUBW a _ (MOVDconst [c]))
+ // cond: int32(c)==0
+ // result: a
+ for {
+ a := v_0
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(int32(c) == 0) {
+ break
+ }
+ v.copyOf(a)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: int32(c)==1
+ // result: (SUB a x)
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(int32(c) == 1) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (SUBshiftLL a x [log64(c)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c-1) && int32(c)>=3
+ // result: (SUB a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c-1) && int32(c) >= 3) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c - 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c+1) && int32(c)>=7
+ // result: (ADD a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(isPowerOfTwo64(c+1) && int32(c) >= 7) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c + 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 5))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+ for {
+ a := v_0
+ x := v_1
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ if !(c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 9))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: int32(c)==-1
+ // result: (ADD a x)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) _)
+ // cond: int32(c)==0
+ // result: a
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(int32(c) == 0) {
+ break
+ }
+ v.copyOf(a)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: int32(c)==1
+ // result: (SUB a x)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(int32(c) == 1) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c)
+ // result: (SUBshiftLL a x [log64(c)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(a, x)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c-1) && int32(c)>=3
+ // result: (SUB a (ADDshiftLL <x.Type> x x [log64(c-1)]))
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c-1) && int32(c) >= 3) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c - 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo64(c+1) && int32(c)>=7
+ // result: (ADD a (SUBshiftLL <x.Type> x x [log64(c+1)]))
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(isPowerOfTwo64(c+1) && int32(c) >= 7) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(log64(c + 1))
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log64(c/3)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log64(c/5)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 5))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log64(c/7)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log64(c/9)])
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ x := v_2
+ if !(c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c / 9))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg2(a, v0)
+ return true
+ }
+ // match: (MSUBW (MOVDconst [c]) x y)
+ // result: (ADDconst [c] (MNEGW <x.Type> x y))
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ y := v_2
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64MNEGW, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) (MOVDconst [d]))
+ // result: (SUBconst [int64(int32(c)*int32(d))] a)
+ for {
+ a := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_2.AuxInt)
+ v.reset(OpARM64SUBconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(c) * int32(d)))
+ v.AddArg(a)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MUL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MUL (NEG x) y)
+ // result: (MNEG x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64NEG {
+ continue
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpARM64MNEG)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVDconst [-1]))
+ // result: (NEG x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MUL _ (MOVDconst [0]))
+ // result: (MOVDconst [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVDconst [1]))
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (SLLconst [log64(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c-1) && c >= 3
+ // result: (ADDshiftLL x x [log64(c-1)])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c-1) && c >= 3) {
+ continue
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c - 1))
+ v.AddArg2(x, x)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c+1) && c >= 7
+ // result: (ADDshiftLL (NEG <x.Type> x) x [log64(c+1)])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c+1) && c >= 7) {
+ continue
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c + 1))
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, x.Type)
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3)
+ // result: (SLLconst [log64(c/3)] (ADDshiftLL <x.Type> x x [1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%3 == 0 && isPowerOfTwo64(c/3)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(1)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5)
+ // result: (SLLconst [log64(c/5)] (ADDshiftLL <x.Type> x x [2]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%5 == 0 && isPowerOfTwo64(c/5)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(log64(c / 5))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7)
+ // result: (SLLconst [log64(c/7)] (ADDshiftLL <x.Type> (NEG <x.Type> x) x [3]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%7 == 0 && isPowerOfTwo64(c/7)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v1 := b.NewValue0(v.Pos, OpARM64NEG, x.Type)
+ v1.AddArg(x)
+ v0.AddArg2(v1, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MUL x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9)
+ // result: (SLLconst [log64(c/9)] (ADDshiftLL <x.Type> x x [3]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%9 == 0 && isPowerOfTwo64(c/9)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(log64(c / 9))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MUL (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [c*d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c * d)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MULW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MULW (NEG x) y)
+ // result: (MNEGW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64NEG {
+ continue
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpARM64MNEGW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (MULW x (MOVDconst [c]))
+ // cond: int32(c)==-1
+ // result: (NEG x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(int32(c) == -1) {
+ continue
+ }
+ v.reset(OpARM64NEG)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MULW _ (MOVDconst [c]))
+ // cond: int32(c)==0
+ // result: (MOVDconst [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(int32(c) == 0) {
+ continue
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (MULW x (MOVDconst [c]))
+ // cond: int32(c)==1
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(int32(c) == 1) {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (MULW x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (SLLconst [log64(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MULW x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c-1) && int32(c) >= 3
+ // result: (ADDshiftLL x x [log64(c-1)])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c-1) && int32(c) >= 3) {
+ continue
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c - 1))
+ v.AddArg2(x, x)
+ return true
+ }
+ break
+ }
+ // match: (MULW x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c+1) && int32(c) >= 7
+ // result: (ADDshiftLL (NEG <x.Type> x) x [log64(c+1)])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c+1) && int32(c) >= 7) {
+ continue
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = int64ToAuxInt(log64(c + 1))
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, x.Type)
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+ break
+ }
+ // match: (MULW x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)
+ // result: (SLLconst [log64(c/3)] (ADDshiftLL <x.Type> x x [1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%3 == 0 && isPowerOfTwo64(c/3) && is32Bit(c)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(log64(c / 3))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(1)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MULW x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)
+ // result: (SLLconst [log64(c/5)] (ADDshiftLL <x.Type> x x [2]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%5 == 0 && isPowerOfTwo64(c/5) && is32Bit(c)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(log64(c / 5))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MULW x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)
+ // result: (SLLconst [log64(c/7)] (ADDshiftLL <x.Type> (NEG <x.Type> x) x [3]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%7 == 0 && isPowerOfTwo64(c/7) && is32Bit(c)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(log64(c / 7))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v1 := b.NewValue0(v.Pos, OpARM64NEG, x.Type)
+ v1.AddArg(x)
+ v0.AddArg2(v1, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MULW x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)
+ // result: (SLLconst [log64(c/9)] (ADDshiftLL <x.Type> x x [3]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%9 == 0 && isPowerOfTwo64(c/9) && is32Bit(c)) {
+ continue
+ }
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(log64(c / 9))
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(x, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MULW (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [int64(int32(c)*int32(d))])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(c) * int32(d)))
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MVN(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MVN (XOR x y))
+ // result: (EON x y)
+ for {
+ if v_0.Op != OpARM64XOR {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpARM64EON)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (MVN (MOVDconst [c]))
+ // result: (MOVDconst [^c])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(^c)
+ return true
+ }
+ // match: (MVN x:(SLLconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (MVNshiftLL [c] y)
+ for {
+ x := v_0
+ if x.Op != OpARM64SLLconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64MVNshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(y)
+ return true
+ }
+ // match: (MVN x:(SRLconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (MVNshiftRL [c] y)
+ for {
+ x := v_0
+ if x.Op != OpARM64SRLconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64MVNshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(y)
+ return true
+ }
+ // match: (MVN x:(SRAconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (MVNshiftRA [c] y)
+ for {
+ x := v_0
+ if x.Op != OpARM64SRAconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64MVNshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MVNshiftLL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MVNshiftLL (MOVDconst [c]) [d])
+ // result: (MOVDconst [^int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(^int64(uint64(c) << uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MVNshiftRA(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MVNshiftRA (MOVDconst [c]) [d])
+ // result: (MOVDconst [^(c>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(^(c >> uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MVNshiftRL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MVNshiftRL (MOVDconst [c]) [d])
+ // result: (MOVDconst [^int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(^int64(uint64(c) >> uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64NEG(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEG (MUL x y))
+ // result: (MNEG x y)
+ for {
+ if v_0.Op != OpARM64MUL {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpARM64MNEG)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (NEG (MULW x y))
+ // result: (MNEGW x y)
+ for {
+ if v_0.Op != OpARM64MULW {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpARM64MNEGW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (NEG (MOVDconst [c]))
+ // result: (MOVDconst [-c])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-c)
+ return true
+ }
+ // match: (NEG x:(SLLconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (NEGshiftLL [c] y)
+ for {
+ x := v_0
+ if x.Op != OpARM64SLLconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64NEGshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(y)
+ return true
+ }
+ // match: (NEG x:(SRLconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (NEGshiftRL [c] y)
+ for {
+ x := v_0
+ if x.Op != OpARM64SRLconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64NEGshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(y)
+ return true
+ }
+ // match: (NEG x:(SRAconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (NEGshiftRA [c] y)
+ for {
+ x := v_0
+ if x.Op != OpARM64SRAconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64NEGshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64NEGshiftLL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEGshiftLL (MOVDconst [c]) [d])
+ // result: (MOVDconst [-int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-int64(uint64(c) << uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64NEGshiftRA(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEGshiftRA (MOVDconst [c]) [d])
+ // result: (MOVDconst [-(c>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-(c >> uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64NEGshiftRL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEGshiftRL (MOVDconst [c]) [d])
+ // result: (MOVDconst [-int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-int64(uint64(c) >> uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64NotEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NotEqual (FlagConstant [fc]))
+ // result: (MOVDconst [b2i(fc.ne())])
+ for {
+ if v_0.Op != OpARM64FlagConstant {
+ break
+ }
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(fc.ne()))
+ return true
+ }
+ // match: (NotEqual (InvertFlags x))
+ // result: (NotEqual x)
+ for {
+ if v_0.Op != OpARM64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpARM64NotEqual)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64OR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (OR x (MOVDconst [c]))
+ // result: (ORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (OR x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (OR x (MVN y))
+ // result: (ORN x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MVN {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpARM64ORN)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (OR x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ORshiftLL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64ORshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (OR x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ORshiftRL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64ORshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (OR x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ORshiftRA x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64ORshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (OR (SLL x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> [cc] (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (ROR x (NEG <t> y))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt64 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL || v_1_0.Type != typ.UInt64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 63 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 63 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64ROR)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (OR (SRL <typ.UInt64> x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> [cc] (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (ROR x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SRL || v_0.Type != typ.UInt64 {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt64 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 63 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 63 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (OR (SLL x (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> [cc] (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (RORW x (NEG <t> y))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt32 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL || v_1_0.Type != typ.UInt32 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpARM64MOVWUreg || x != v_1_0_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 31 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 31 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64RORW)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (OR (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> [cc] (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (RORW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SRL || v_0.Type != typ.UInt32 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64MOVWUreg {
+ continue
+ }
+ x := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt32 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 31 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 31 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (OR (UBFIZ [bfc] x) (ANDconst [ac] y))
+ // cond: ac == ^((1<<uint(bfc.getARM64BFwidth())-1) << uint(bfc.getARM64BFlsb()))
+ // result: (BFI [bfc] y x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64UBFIZ {
+ continue
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpARM64ANDconst {
+ continue
+ }
+ ac := auxIntToInt64(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(ac == ^((1<<uint(bfc.getARM64BFwidth()) - 1) << uint(bfc.getARM64BFlsb()))) {
+ continue
+ }
+ v.reset(OpARM64BFI)
+ v.AuxInt = arm64BitFieldToAuxInt(bfc)
+ v.AddArg2(y, x)
+ return true
+ }
+ break
+ }
+ // match: (OR (UBFX [bfc] x) (ANDconst [ac] y))
+ // cond: ac == ^(1<<uint(bfc.getARM64BFwidth())-1)
+ // result: (BFXIL [bfc] y x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64UBFX {
+ continue
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpARM64ANDconst {
+ continue
+ }
+ ac := auxIntToInt64(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(ac == ^(1<<uint(bfc.getARM64BFwidth()) - 1)) {
+ continue
+ }
+ v.reset(OpARM64BFXIL)
+ v.AuxInt = arm64BitFieldToAuxInt(bfc)
+ v.AddArg2(y, x)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] y0:(MOVDnop x0:(MOVBUload [i3] {s} p mem))) y1:(MOVDnop x1:(MOVBUload [i2] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [i1] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [i0] {s} p mem)))
+ // cond: i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3) (MOVWUload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ s0 := o1.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 24 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUload {
+ continue
+ }
+ i3 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o1.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload {
+ continue
+ }
+ i2 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y2 := o0.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload {
+ continue
+ }
+ i1 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] {
+ continue
+ }
+ y3 := v_1
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload {
+ continue
+ }
+ i0 := auxIntToInt32(x3.AuxInt)
+ if auxToSym(x3.Aux) != s {
+ continue
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] || !(i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3) != nil && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3)
+ v0 := b.NewValue0(x3.Pos, OpARM64MOVWUload, t)
+ v.copyOf(v0)
+ v0.Aux = symToAux(s)
+ v1 := b.NewValue0(x3.Pos, OpOffPtr, p.Type)
+ v1.AuxInt = int64ToAuxInt(int64(i0))
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] y0:(MOVDnop x0:(MOVBUload [3] {s} p mem))) y1:(MOVDnop x1:(MOVBUload [2] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem))) y3:(MOVDnop x3:(MOVBUloadidx ptr0 idx0 mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3) (MOVWUloadidx <t> ptr0 idx0 mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ s0 := o1.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 24 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUload || auxIntToInt32(x0.AuxInt) != 3 {
+ continue
+ }
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o1.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 2 || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y2 := o0.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload || auxIntToInt32(x2.AuxInt) != 1 || auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ p1 := x2.Args[0]
+ if p1.Op != OpARM64ADD {
+ continue
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, p1_0, p1_1 = _i1+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ if mem != x2.Args[1] {
+ continue
+ }
+ y3 := v_1
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x3.Args[2]
+ ptr0 := x3.Args[0]
+ idx0 := x3.Args[1]
+ if mem != x3.Args[2] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3)
+ v0 := b.NewValue0(x2.Pos, OpARM64MOVWUloadidx, t)
+ v.copyOf(v0)
+ v0.AddArg3(ptr0, idx0, mem)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] y0:(MOVDnop x0:(MOVBUloadidx ptr (ADDconst [3] idx) mem))) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [2] idx) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [1] idx) mem))) y3:(MOVDnop x3:(MOVBUloadidx ptr idx mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3) (MOVWUloadidx <t> ptr idx mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ s0 := o1.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 24 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ mem := x0.Args[2]
+ ptr := x0.Args[0]
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64ADDconst || auxIntToInt64(x0_1.AuxInt) != 3 {
+ continue
+ }
+ idx := x0_1.Args[0]
+ y1 := o1.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ continue
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 2 || idx != x1_1.Args[0] || mem != x1.Args[2] {
+ continue
+ }
+ y2 := o0.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x2.Args[2]
+ if ptr != x2.Args[0] {
+ continue
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64ADDconst || auxIntToInt64(x2_1.AuxInt) != 1 || idx != x2_1.Args[0] || mem != x2.Args[2] {
+ continue
+ }
+ y3 := v_1
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x3.Args[2]
+ if ptr != x3.Args[0] || idx != x3.Args[1] || mem != x3.Args[2] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3) != nil && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVWUloadidx, t)
+ v.copyOf(v0)
+ v0.AddArg3(ptr, idx, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56] y0:(MOVDnop x0:(MOVBUload [i7] {s} p mem))) y1:(MOVDnop x1:(MOVBUload [i6] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [i5] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [i4] {s} p mem))) y4:(MOVDnop x4:(MOVBUload [i3] {s} p mem))) y5:(MOVDnop x5:(MOVBUload [i2] {s} p mem))) y6:(MOVDnop x6:(MOVBUload [i1] {s} p mem))) y7:(MOVDnop x7:(MOVBUload [i0] {s} p mem)))
+ // cond: i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVDload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 24 {
+ continue
+ }
+ _ = o2.Args[1]
+ o3 := o2.Args[0]
+ if o3.Op != OpARM64ORshiftLL || auxIntToInt64(o3.AuxInt) != 32 {
+ continue
+ }
+ _ = o3.Args[1]
+ o4 := o3.Args[0]
+ if o4.Op != OpARM64ORshiftLL || auxIntToInt64(o4.AuxInt) != 40 {
+ continue
+ }
+ _ = o4.Args[1]
+ o5 := o4.Args[0]
+ if o5.Op != OpARM64ORshiftLL || auxIntToInt64(o5.AuxInt) != 48 {
+ continue
+ }
+ _ = o5.Args[1]
+ s0 := o5.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 56 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUload {
+ continue
+ }
+ i7 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o5.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload {
+ continue
+ }
+ i6 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y2 := o4.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload {
+ continue
+ }
+ i5 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] {
+ continue
+ }
+ y3 := o3.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload {
+ continue
+ }
+ i4 := auxIntToInt32(x3.AuxInt)
+ if auxToSym(x3.Aux) != s {
+ continue
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] {
+ continue
+ }
+ y4 := o2.Args[1]
+ if y4.Op != OpARM64MOVDnop {
+ continue
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUload {
+ continue
+ }
+ i3 := auxIntToInt32(x4.AuxInt)
+ if auxToSym(x4.Aux) != s {
+ continue
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] {
+ continue
+ }
+ y5 := o1.Args[1]
+ if y5.Op != OpARM64MOVDnop {
+ continue
+ }
+ x5 := y5.Args[0]
+ if x5.Op != OpARM64MOVBUload {
+ continue
+ }
+ i2 := auxIntToInt32(x5.AuxInt)
+ if auxToSym(x5.Aux) != s {
+ continue
+ }
+ _ = x5.Args[1]
+ if p != x5.Args[0] || mem != x5.Args[1] {
+ continue
+ }
+ y6 := o0.Args[1]
+ if y6.Op != OpARM64MOVDnop {
+ continue
+ }
+ x6 := y6.Args[0]
+ if x6.Op != OpARM64MOVBUload {
+ continue
+ }
+ i1 := auxIntToInt32(x6.AuxInt)
+ if auxToSym(x6.Aux) != s {
+ continue
+ }
+ _ = x6.Args[1]
+ if p != x6.Args[0] || mem != x6.Args[1] {
+ continue
+ }
+ y7 := v_1
+ if y7.Op != OpARM64MOVDnop {
+ continue
+ }
+ x7 := y7.Args[0]
+ if x7.Op != OpARM64MOVBUload {
+ continue
+ }
+ i0 := auxIntToInt32(x7.AuxInt)
+ if auxToSym(x7.Aux) != s {
+ continue
+ }
+ _ = x7.Args[1]
+ if p != x7.Args[0] || mem != x7.Args[1] || !(i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7) != nil && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7)
+ v0 := b.NewValue0(x7.Pos, OpARM64MOVDload, t)
+ v.copyOf(v0)
+ v0.Aux = symToAux(s)
+ v1 := b.NewValue0(x7.Pos, OpOffPtr, p.Type)
+ v1.AuxInt = int64ToAuxInt(int64(i0))
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56] y0:(MOVDnop x0:(MOVBUload [7] {s} p mem))) y1:(MOVDnop x1:(MOVBUload [6] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [5] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [4] {s} p mem))) y4:(MOVDnop x4:(MOVBUload [3] {s} p mem))) y5:(MOVDnop x5:(MOVBUload [2] {s} p mem))) y6:(MOVDnop x6:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem))) y7:(MOVDnop x7:(MOVBUloadidx ptr0 idx0 mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVDloadidx <t> ptr0 idx0 mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 24 {
+ continue
+ }
+ _ = o2.Args[1]
+ o3 := o2.Args[0]
+ if o3.Op != OpARM64ORshiftLL || auxIntToInt64(o3.AuxInt) != 32 {
+ continue
+ }
+ _ = o3.Args[1]
+ o4 := o3.Args[0]
+ if o4.Op != OpARM64ORshiftLL || auxIntToInt64(o4.AuxInt) != 40 {
+ continue
+ }
+ _ = o4.Args[1]
+ o5 := o4.Args[0]
+ if o5.Op != OpARM64ORshiftLL || auxIntToInt64(o5.AuxInt) != 48 {
+ continue
+ }
+ _ = o5.Args[1]
+ s0 := o5.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 56 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUload || auxIntToInt32(x0.AuxInt) != 7 {
+ continue
+ }
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o5.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 6 || auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y2 := o4.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload || auxIntToInt32(x2.AuxInt) != 5 || auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] {
+ continue
+ }
+ y3 := o3.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload || auxIntToInt32(x3.AuxInt) != 4 || auxToSym(x3.Aux) != s {
+ continue
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] {
+ continue
+ }
+ y4 := o2.Args[1]
+ if y4.Op != OpARM64MOVDnop {
+ continue
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUload || auxIntToInt32(x4.AuxInt) != 3 || auxToSym(x4.Aux) != s {
+ continue
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] {
+ continue
+ }
+ y5 := o1.Args[1]
+ if y5.Op != OpARM64MOVDnop {
+ continue
+ }
+ x5 := y5.Args[0]
+ if x5.Op != OpARM64MOVBUload || auxIntToInt32(x5.AuxInt) != 2 || auxToSym(x5.Aux) != s {
+ continue
+ }
+ _ = x5.Args[1]
+ if p != x5.Args[0] || mem != x5.Args[1] {
+ continue
+ }
+ y6 := o0.Args[1]
+ if y6.Op != OpARM64MOVDnop {
+ continue
+ }
+ x6 := y6.Args[0]
+ if x6.Op != OpARM64MOVBUload || auxIntToInt32(x6.AuxInt) != 1 || auxToSym(x6.Aux) != s {
+ continue
+ }
+ _ = x6.Args[1]
+ p1 := x6.Args[0]
+ if p1.Op != OpARM64ADD {
+ continue
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, p1_0, p1_1 = _i1+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ if mem != x6.Args[1] {
+ continue
+ }
+ y7 := v_1
+ if y7.Op != OpARM64MOVDnop {
+ continue
+ }
+ x7 := y7.Args[0]
+ if x7.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x7.Args[2]
+ ptr0 := x7.Args[0]
+ idx0 := x7.Args[1]
+ if mem != x7.Args[2] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7)
+ v0 := b.NewValue0(x6.Pos, OpARM64MOVDloadidx, t)
+ v.copyOf(v0)
+ v0.AddArg3(ptr0, idx0, mem)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56] y0:(MOVDnop x0:(MOVBUloadidx ptr (ADDconst [7] idx) mem))) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [6] idx) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [5] idx) mem))) y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [4] idx) mem))) y4:(MOVDnop x4:(MOVBUloadidx ptr (ADDconst [3] idx) mem))) y5:(MOVDnop x5:(MOVBUloadidx ptr (ADDconst [2] idx) mem))) y6:(MOVDnop x6:(MOVBUloadidx ptr (ADDconst [1] idx) mem))) y7:(MOVDnop x7:(MOVBUloadidx ptr idx mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVDloadidx <t> ptr idx mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 24 {
+ continue
+ }
+ _ = o2.Args[1]
+ o3 := o2.Args[0]
+ if o3.Op != OpARM64ORshiftLL || auxIntToInt64(o3.AuxInt) != 32 {
+ continue
+ }
+ _ = o3.Args[1]
+ o4 := o3.Args[0]
+ if o4.Op != OpARM64ORshiftLL || auxIntToInt64(o4.AuxInt) != 40 {
+ continue
+ }
+ _ = o4.Args[1]
+ o5 := o4.Args[0]
+ if o5.Op != OpARM64ORshiftLL || auxIntToInt64(o5.AuxInt) != 48 {
+ continue
+ }
+ _ = o5.Args[1]
+ s0 := o5.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 56 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ mem := x0.Args[2]
+ ptr := x0.Args[0]
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64ADDconst || auxIntToInt64(x0_1.AuxInt) != 7 {
+ continue
+ }
+ idx := x0_1.Args[0]
+ y1 := o5.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ continue
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 6 || idx != x1_1.Args[0] || mem != x1.Args[2] {
+ continue
+ }
+ y2 := o4.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x2.Args[2]
+ if ptr != x2.Args[0] {
+ continue
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64ADDconst || auxIntToInt64(x2_1.AuxInt) != 5 || idx != x2_1.Args[0] || mem != x2.Args[2] {
+ continue
+ }
+ y3 := o3.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x3.Args[2]
+ if ptr != x3.Args[0] {
+ continue
+ }
+ x3_1 := x3.Args[1]
+ if x3_1.Op != OpARM64ADDconst || auxIntToInt64(x3_1.AuxInt) != 4 || idx != x3_1.Args[0] || mem != x3.Args[2] {
+ continue
+ }
+ y4 := o2.Args[1]
+ if y4.Op != OpARM64MOVDnop {
+ continue
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x4.Args[2]
+ if ptr != x4.Args[0] {
+ continue
+ }
+ x4_1 := x4.Args[1]
+ if x4_1.Op != OpARM64ADDconst || auxIntToInt64(x4_1.AuxInt) != 3 || idx != x4_1.Args[0] || mem != x4.Args[2] {
+ continue
+ }
+ y5 := o1.Args[1]
+ if y5.Op != OpARM64MOVDnop {
+ continue
+ }
+ x5 := y5.Args[0]
+ if x5.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x5.Args[2]
+ if ptr != x5.Args[0] {
+ continue
+ }
+ x5_1 := x5.Args[1]
+ if x5_1.Op != OpARM64ADDconst || auxIntToInt64(x5_1.AuxInt) != 2 || idx != x5_1.Args[0] || mem != x5.Args[2] {
+ continue
+ }
+ y6 := o0.Args[1]
+ if y6.Op != OpARM64MOVDnop {
+ continue
+ }
+ x6 := y6.Args[0]
+ if x6.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x6.Args[2]
+ if ptr != x6.Args[0] {
+ continue
+ }
+ x6_1 := x6.Args[1]
+ if x6_1.Op != OpARM64ADDconst || auxIntToInt64(x6_1.AuxInt) != 1 || idx != x6_1.Args[0] || mem != x6.Args[2] {
+ continue
+ }
+ y7 := v_1
+ if y7.Op != OpARM64MOVDnop {
+ continue
+ }
+ x7 := y7.Args[0]
+ if x7.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x7.Args[2]
+ if ptr != x7.Args[0] || idx != x7.Args[1] || mem != x7.Args[2] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7) != nil && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDloadidx, t)
+ v.copyOf(v0)
+ v0.AddArg3(ptr, idx, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] y0:(MOVDnop x0:(MOVBUload [i0] {s} p mem))) y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [i2] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [i3] {s} p mem)))
+ // cond: i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ s0 := o1.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 24 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o1.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y2 := o0.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload {
+ continue
+ }
+ i2 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] {
+ continue
+ }
+ y3 := v_1
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload {
+ continue
+ }
+ i3 := auxIntToInt32(x3.AuxInt)
+ if auxToSym(x3.Aux) != s {
+ continue
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] || !(i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3) != nil && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3)
+ v0 := b.NewValue0(x3.Pos, OpARM64REVW, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x3.Pos, OpARM64MOVWUload, t)
+ v1.Aux = symToAux(s)
+ v2 := b.NewValue0(x3.Pos, OpOffPtr, p.Type)
+ v2.AuxInt = int64ToAuxInt(int64(i0))
+ v2.AddArg(p)
+ v1.AddArg2(v2, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] y0:(MOVDnop x0:(MOVBUloadidx ptr0 idx0 mem))) y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem))) y2:(MOVDnop x2:(MOVBUload [2] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [3] {s} p mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUloadidx <t> ptr0 idx0 mem))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ s0 := o1.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 24 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ mem := x0.Args[2]
+ ptr0 := x0.Args[0]
+ idx0 := x0.Args[1]
+ y1 := o1.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 1 {
+ continue
+ }
+ s := auxToSym(x1.Aux)
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADD {
+ continue
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, p1_0, p1_1 = _i1+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ if mem != x1.Args[1] {
+ continue
+ }
+ y2 := o0.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload || auxIntToInt32(x2.AuxInt) != 2 || auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ p := x2.Args[0]
+ if mem != x2.Args[1] {
+ continue
+ }
+ y3 := v_1
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload || auxIntToInt32(x3.AuxInt) != 3 || auxToSym(x3.Aux) != s {
+ continue
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3)
+ v0 := b.NewValue0(x3.Pos, OpARM64REVW, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x3.Pos, OpARM64MOVWUloadidx, t)
+ v1.AddArg3(ptr0, idx0, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] y0:(MOVDnop x0:(MOVBUloadidx ptr idx mem))) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [2] idx) mem))) y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUloadidx <t> ptr idx mem))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ s0 := o1.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 24 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ mem := x0.Args[2]
+ ptr := x0.Args[0]
+ idx := x0.Args[1]
+ y1 := o1.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ continue
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 1 || idx != x1_1.Args[0] || mem != x1.Args[2] {
+ continue
+ }
+ y2 := o0.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x2.Args[2]
+ if ptr != x2.Args[0] {
+ continue
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64ADDconst || auxIntToInt64(x2_1.AuxInt) != 2 || idx != x2_1.Args[0] || mem != x2.Args[2] {
+ continue
+ }
+ y3 := v_1
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x3.Args[2]
+ if ptr != x3.Args[0] {
+ continue
+ }
+ x3_1 := x3.Args[1]
+ if x3_1.Op != OpARM64ADDconst || auxIntToInt64(x3_1.AuxInt) != 3 || idx != x3_1.Args[0] || mem != x3.Args[2] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3) != nil && clobber(x0, x1, x2, x3, y0, y1, y2, y3, o0, o1, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3)
+ v0 := b.NewValue0(v.Pos, OpARM64REVW, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVWUloadidx, t)
+ v1.AddArg3(ptr, idx, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56] y0:(MOVDnop x0:(MOVBUload [i0] {s} p mem))) y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [i2] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [i3] {s} p mem))) y4:(MOVDnop x4:(MOVBUload [i4] {s} p mem))) y5:(MOVDnop x5:(MOVBUload [i5] {s} p mem))) y6:(MOVDnop x6:(MOVBUload [i6] {s} p mem))) y7:(MOVDnop x7:(MOVBUload [i7] {s} p mem)))
+ // cond: i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 24 {
+ continue
+ }
+ _ = o2.Args[1]
+ o3 := o2.Args[0]
+ if o3.Op != OpARM64ORshiftLL || auxIntToInt64(o3.AuxInt) != 32 {
+ continue
+ }
+ _ = o3.Args[1]
+ o4 := o3.Args[0]
+ if o4.Op != OpARM64ORshiftLL || auxIntToInt64(o4.AuxInt) != 40 {
+ continue
+ }
+ _ = o4.Args[1]
+ o5 := o4.Args[0]
+ if o5.Op != OpARM64ORshiftLL || auxIntToInt64(o5.AuxInt) != 48 {
+ continue
+ }
+ _ = o5.Args[1]
+ s0 := o5.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 56 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o5.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y2 := o4.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload {
+ continue
+ }
+ i2 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] {
+ continue
+ }
+ y3 := o3.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload {
+ continue
+ }
+ i3 := auxIntToInt32(x3.AuxInt)
+ if auxToSym(x3.Aux) != s {
+ continue
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] {
+ continue
+ }
+ y4 := o2.Args[1]
+ if y4.Op != OpARM64MOVDnop {
+ continue
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUload {
+ continue
+ }
+ i4 := auxIntToInt32(x4.AuxInt)
+ if auxToSym(x4.Aux) != s {
+ continue
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] {
+ continue
+ }
+ y5 := o1.Args[1]
+ if y5.Op != OpARM64MOVDnop {
+ continue
+ }
+ x5 := y5.Args[0]
+ if x5.Op != OpARM64MOVBUload {
+ continue
+ }
+ i5 := auxIntToInt32(x5.AuxInt)
+ if auxToSym(x5.Aux) != s {
+ continue
+ }
+ _ = x5.Args[1]
+ if p != x5.Args[0] || mem != x5.Args[1] {
+ continue
+ }
+ y6 := o0.Args[1]
+ if y6.Op != OpARM64MOVDnop {
+ continue
+ }
+ x6 := y6.Args[0]
+ if x6.Op != OpARM64MOVBUload {
+ continue
+ }
+ i6 := auxIntToInt32(x6.AuxInt)
+ if auxToSym(x6.Aux) != s {
+ continue
+ }
+ _ = x6.Args[1]
+ if p != x6.Args[0] || mem != x6.Args[1] {
+ continue
+ }
+ y7 := v_1
+ if y7.Op != OpARM64MOVDnop {
+ continue
+ }
+ x7 := y7.Args[0]
+ if x7.Op != OpARM64MOVBUload {
+ continue
+ }
+ i7 := auxIntToInt32(x7.AuxInt)
+ if auxToSym(x7.Aux) != s {
+ continue
+ }
+ _ = x7.Args[1]
+ if p != x7.Args[0] || mem != x7.Args[1] || !(i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7) != nil && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7)
+ v0 := b.NewValue0(x7.Pos, OpARM64REV, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x7.Pos, OpARM64MOVDload, t)
+ v1.Aux = symToAux(s)
+ v2 := b.NewValue0(x7.Pos, OpOffPtr, p.Type)
+ v2.AuxInt = int64ToAuxInt(int64(i0))
+ v2.AddArg(p)
+ v1.AddArg2(v2, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56] y0:(MOVDnop x0:(MOVBUloadidx ptr0 idx0 mem))) y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem))) y2:(MOVDnop x2:(MOVBUload [2] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [3] {s} p mem))) y4:(MOVDnop x4:(MOVBUload [4] {s} p mem))) y5:(MOVDnop x5:(MOVBUload [5] {s} p mem))) y6:(MOVDnop x6:(MOVBUload [6] {s} p mem))) y7:(MOVDnop x7:(MOVBUload [7] {s} p mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDloadidx <t> ptr0 idx0 mem))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 24 {
+ continue
+ }
+ _ = o2.Args[1]
+ o3 := o2.Args[0]
+ if o3.Op != OpARM64ORshiftLL || auxIntToInt64(o3.AuxInt) != 32 {
+ continue
+ }
+ _ = o3.Args[1]
+ o4 := o3.Args[0]
+ if o4.Op != OpARM64ORshiftLL || auxIntToInt64(o4.AuxInt) != 40 {
+ continue
+ }
+ _ = o4.Args[1]
+ o5 := o4.Args[0]
+ if o5.Op != OpARM64ORshiftLL || auxIntToInt64(o5.AuxInt) != 48 {
+ continue
+ }
+ _ = o5.Args[1]
+ s0 := o5.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 56 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ mem := x0.Args[2]
+ ptr0 := x0.Args[0]
+ idx0 := x0.Args[1]
+ y1 := o5.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 1 {
+ continue
+ }
+ s := auxToSym(x1.Aux)
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADD {
+ continue
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, p1_0, p1_1 = _i1+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ if mem != x1.Args[1] {
+ continue
+ }
+ y2 := o4.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload || auxIntToInt32(x2.AuxInt) != 2 || auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ p := x2.Args[0]
+ if mem != x2.Args[1] {
+ continue
+ }
+ y3 := o3.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload || auxIntToInt32(x3.AuxInt) != 3 || auxToSym(x3.Aux) != s {
+ continue
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] {
+ continue
+ }
+ y4 := o2.Args[1]
+ if y4.Op != OpARM64MOVDnop {
+ continue
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUload || auxIntToInt32(x4.AuxInt) != 4 || auxToSym(x4.Aux) != s {
+ continue
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] {
+ continue
+ }
+ y5 := o1.Args[1]
+ if y5.Op != OpARM64MOVDnop {
+ continue
+ }
+ x5 := y5.Args[0]
+ if x5.Op != OpARM64MOVBUload || auxIntToInt32(x5.AuxInt) != 5 || auxToSym(x5.Aux) != s {
+ continue
+ }
+ _ = x5.Args[1]
+ if p != x5.Args[0] || mem != x5.Args[1] {
+ continue
+ }
+ y6 := o0.Args[1]
+ if y6.Op != OpARM64MOVDnop {
+ continue
+ }
+ x6 := y6.Args[0]
+ if x6.Op != OpARM64MOVBUload || auxIntToInt32(x6.AuxInt) != 6 || auxToSym(x6.Aux) != s {
+ continue
+ }
+ _ = x6.Args[1]
+ if p != x6.Args[0] || mem != x6.Args[1] {
+ continue
+ }
+ y7 := v_1
+ if y7.Op != OpARM64MOVDnop {
+ continue
+ }
+ x7 := y7.Args[0]
+ if x7.Op != OpARM64MOVBUload || auxIntToInt32(x7.AuxInt) != 7 || auxToSym(x7.Aux) != s {
+ continue
+ }
+ _ = x7.Args[1]
+ if p != x7.Args[0] || mem != x7.Args[1] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7)
+ v0 := b.NewValue0(x7.Pos, OpARM64REV, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x7.Pos, OpARM64MOVDloadidx, t)
+ v1.AddArg3(ptr0, idx0, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56] y0:(MOVDnop x0:(MOVBUloadidx ptr idx mem))) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [2] idx) mem))) y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [3] idx) mem))) y4:(MOVDnop x4:(MOVBUloadidx ptr (ADDconst [4] idx) mem))) y5:(MOVDnop x5:(MOVBUloadidx ptr (ADDconst [5] idx) mem))) y6:(MOVDnop x6:(MOVBUloadidx ptr (ADDconst [6] idx) mem))) y7:(MOVDnop x7:(MOVBUloadidx ptr (ADDconst [7] idx) mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDloadidx <t> ptr idx mem))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 8 {
+ continue
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 16 {
+ continue
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 24 {
+ continue
+ }
+ _ = o2.Args[1]
+ o3 := o2.Args[0]
+ if o3.Op != OpARM64ORshiftLL || auxIntToInt64(o3.AuxInt) != 32 {
+ continue
+ }
+ _ = o3.Args[1]
+ o4 := o3.Args[0]
+ if o4.Op != OpARM64ORshiftLL || auxIntToInt64(o4.AuxInt) != 40 {
+ continue
+ }
+ _ = o4.Args[1]
+ o5 := o4.Args[0]
+ if o5.Op != OpARM64ORshiftLL || auxIntToInt64(o5.AuxInt) != 48 {
+ continue
+ }
+ _ = o5.Args[1]
+ s0 := o5.Args[0]
+ if s0.Op != OpARM64SLLconst || auxIntToInt64(s0.AuxInt) != 56 {
+ continue
+ }
+ y0 := s0.Args[0]
+ if y0.Op != OpARM64MOVDnop {
+ continue
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ mem := x0.Args[2]
+ ptr := x0.Args[0]
+ idx := x0.Args[1]
+ y1 := o5.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ continue
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 1 || idx != x1_1.Args[0] || mem != x1.Args[2] {
+ continue
+ }
+ y2 := o4.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x2.Args[2]
+ if ptr != x2.Args[0] {
+ continue
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64ADDconst || auxIntToInt64(x2_1.AuxInt) != 2 || idx != x2_1.Args[0] || mem != x2.Args[2] {
+ continue
+ }
+ y3 := o3.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x3.Args[2]
+ if ptr != x3.Args[0] {
+ continue
+ }
+ x3_1 := x3.Args[1]
+ if x3_1.Op != OpARM64ADDconst || auxIntToInt64(x3_1.AuxInt) != 3 || idx != x3_1.Args[0] || mem != x3.Args[2] {
+ continue
+ }
+ y4 := o2.Args[1]
+ if y4.Op != OpARM64MOVDnop {
+ continue
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x4.Args[2]
+ if ptr != x4.Args[0] {
+ continue
+ }
+ x4_1 := x4.Args[1]
+ if x4_1.Op != OpARM64ADDconst || auxIntToInt64(x4_1.AuxInt) != 4 || idx != x4_1.Args[0] || mem != x4.Args[2] {
+ continue
+ }
+ y5 := o1.Args[1]
+ if y5.Op != OpARM64MOVDnop {
+ continue
+ }
+ x5 := y5.Args[0]
+ if x5.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x5.Args[2]
+ if ptr != x5.Args[0] {
+ continue
+ }
+ x5_1 := x5.Args[1]
+ if x5_1.Op != OpARM64ADDconst || auxIntToInt64(x5_1.AuxInt) != 5 || idx != x5_1.Args[0] || mem != x5.Args[2] {
+ continue
+ }
+ y6 := o0.Args[1]
+ if y6.Op != OpARM64MOVDnop {
+ continue
+ }
+ x6 := y6.Args[0]
+ if x6.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x6.Args[2]
+ if ptr != x6.Args[0] {
+ continue
+ }
+ x6_1 := x6.Args[1]
+ if x6_1.Op != OpARM64ADDconst || auxIntToInt64(x6_1.AuxInt) != 6 || idx != x6_1.Args[0] || mem != x6.Args[2] {
+ continue
+ }
+ y7 := v_1
+ if y7.Op != OpARM64MOVDnop {
+ continue
+ }
+ x7 := y7.Args[0]
+ if x7.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x7.Args[2]
+ if ptr != x7.Args[0] {
+ continue
+ }
+ x7_1 := x7.Args[1]
+ if x7_1.Op != OpARM64ADDconst || auxIntToInt64(x7_1.AuxInt) != 7 || idx != x7_1.Args[0] || mem != x7.Args[2] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7) != nil && clobber(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7, o0, o1, o2, o3, o4, o5, s0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4, x5, x6, x7)
+ v0 := b.NewValue0(v.Pos, OpARM64REV, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVDloadidx, t)
+ v1.AddArg3(ptr, idx, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ORN(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ORN x (MOVDconst [c]))
+ // result: (ORconst [^c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(^c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORN x x)
+ // result: (MOVDconst [-1])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (ORN x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ORNshiftLL x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64ORNshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (ORN x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ORNshiftRL x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64ORNshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (ORN x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (ORNshiftRA x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64ORNshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ORNshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ORNshiftLL x (MOVDconst [c]) [d])
+ // result: (ORconst x [^int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(^int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORNshiftLL (SLLconst x [c]) x [c])
+ // result: (MOVDconst [-1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ORNshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ORNshiftRA x (MOVDconst [c]) [d])
+ // result: (ORconst x [^(c>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(^(c >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORNshiftRA (SRAconst x [c]) x [c])
+ // result: (MOVDconst [-1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRAconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ORNshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ORNshiftRL x (MOVDconst [c]) [d])
+ // result: (ORconst x [^int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(^int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORNshiftRL (SRLconst x [c]) x [c])
+ // result: (MOVDconst [-1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORconst [-1] _)
+ // result: (MOVDconst [-1])
+ for {
+ if auxIntToInt64(v.AuxInt) != -1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (ORconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [c|d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c | d)
+ return true
+ }
+ // match: (ORconst [c] (ORconst [d] x))
+ // result: (ORconst [c|d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64ORconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(c | d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORconst [c1] (ANDconst [c2] x))
+ // cond: c2|c1 == ^0
+ // result: (ORconst [c1] x)
+ for {
+ c1 := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ c2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c2|c1 == ^0) {
+ break
+ }
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(c1)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ORshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ORshiftLL (MOVDconst [c]) x [d])
+ // result: (ORconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ORshiftLL x (MOVDconst [c]) [d])
+ // result: (ORconst x [int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORshiftLL y:(SLLconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ y := v_0
+ if y.Op != OpARM64SLLconst || auxIntToInt64(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: ( ORshiftLL [c] (SRLconst x [64-c]) x)
+ // result: (RORconst [64-c] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != 64-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64RORconst)
+ v.AuxInt = int64ToAuxInt(64 - c)
+ v.AddArg(x)
+ return true
+ }
+ // match: ( ORshiftLL <t> [c] (UBFX [bfc] x) x)
+ // cond: c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ // result: (RORWconst [32-c] x)
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFX {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if x != v_1 || !(c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)) {
+ break
+ }
+ v.reset(OpARM64RORWconst)
+ v.AuxInt = int64ToAuxInt(32 - c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORshiftLL <typ.UInt16> [8] (UBFX <typ.UInt16> [armBFAuxInt(8, 8)] x) x)
+ // result: (REV16W x)
+ for {
+ if v.Type != typ.UInt16 || auxIntToInt64(v.AuxInt) != 8 || v_0.Op != OpARM64UBFX || v_0.Type != typ.UInt16 || auxIntToArm64BitField(v_0.AuxInt) != armBFAuxInt(8, 8) {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64REV16W)
+ v.AddArg(x)
+ return true
+ }
+ // match: ( ORshiftLL [c] (SRLconst x [64-c]) x2)
+ // result: (EXTRconst [64-c] x2 x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != 64-c {
+ break
+ }
+ x := v_0.Args[0]
+ x2 := v_1
+ v.reset(OpARM64EXTRconst)
+ v.AuxInt = int64ToAuxInt(64 - c)
+ v.AddArg2(x2, x)
+ return true
+ }
+ // match: ( ORshiftLL <t> [c] (UBFX [bfc] x) x2)
+ // cond: c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ // result: (EXTRWconst [32-c] x2 x)
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFX {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ x2 := v_1
+ if !(c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)) {
+ break
+ }
+ v.reset(OpARM64EXTRWconst)
+ v.AuxInt = int64ToAuxInt(32 - c)
+ v.AddArg2(x2, x)
+ return true
+ }
+ // match: (ORshiftLL [sc] (UBFX [bfc] x) (SRLconst [sc] y))
+ // cond: sc == bfc.getARM64BFwidth()
+ // result: (BFXIL [bfc] y x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFX {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpARM64SRLconst || auxIntToInt64(v_1.AuxInt) != sc {
+ break
+ }
+ y := v_1.Args[0]
+ if !(sc == bfc.getARM64BFwidth()) {
+ break
+ }
+ v.reset(OpARM64BFXIL)
+ v.AuxInt = arm64BitFieldToAuxInt(bfc)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (ORshiftLL <t> [8] y0:(MOVDnop x0:(MOVBUload [i0] {s} p mem)) y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem)))
+ // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, y0, y1)
+ // result: @mergePoint(b,x0,x1) (MOVHUload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ y0 := v_0
+ if y0.Op != OpARM64MOVDnop {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUload {
+ break
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := v_1
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload {
+ break
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, y0, y1)) {
+ break
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpARM64MOVHUload, t)
+ v.copyOf(v0)
+ v0.Aux = symToAux(s)
+ v1 := b.NewValue0(x1.Pos, OpOffPtr, p.Type)
+ v1.AuxInt = int64ToAuxInt(int64(i0))
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ // match: (ORshiftLL <t> [8] y0:(MOVDnop x0:(MOVBUloadidx ptr0 idx0 mem)) y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b,x0,x1) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x0, x1, y0, y1)
+ // result: @mergePoint(b,x0,x1) (MOVHUloadidx <t> ptr0 idx0 mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ y0 := v_0
+ if y0.Op != OpARM64MOVDnop {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ mem := x0.Args[2]
+ ptr0 := x0.Args[0]
+ idx0 := x0.Args[1]
+ y1 := v_1
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(x1.Aux)
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADD {
+ break
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p1_0, p1_1 = _i0+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ if mem != x1.Args[1] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b, x0, x1) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x0, x1, y0, y1)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpARM64MOVHUloadidx, t)
+ v.copyOf(v0)
+ v0.AddArg3(ptr0, idx0, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORshiftLL <t> [8] y0:(MOVDnop x0:(MOVBUloadidx ptr idx mem)) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, y0, y1)
+ // result: @mergePoint(b,x0,x1) (MOVHUloadidx <t> ptr idx mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ y0 := v_0
+ if y0.Op != OpARM64MOVDnop {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ mem := x0.Args[2]
+ ptr := x0.Args[0]
+ idx := x0.Args[1]
+ y1 := v_1
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 1 || idx != x1_1.Args[0] || mem != x1.Args[2] || !(x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, y0, y1)) {
+ break
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVHUloadidx, t)
+ v.copyOf(v0)
+ v0.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (ORshiftLL <t> [24] o0:(ORshiftLL [16] x0:(MOVHUload [i0] {s} p mem) y1:(MOVDnop x1:(MOVBUload [i2] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [i3] {s} p mem)))
+ // cond: i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b,x0,x1,x2) != nil && clobber(x0, x1, x2, y1, y2, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVWUload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 16 {
+ break
+ }
+ _ = o0.Args[1]
+ x0 := o0.Args[0]
+ if x0.Op != OpARM64MOVHUload {
+ break
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o0.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload {
+ break
+ }
+ i2 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ break
+ }
+ y2 := v_1
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload {
+ break
+ }
+ i3 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] || !(i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, y1, y2, o0)) {
+ break
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x2.Pos, OpARM64MOVWUload, t)
+ v.copyOf(v0)
+ v0.Aux = symToAux(s)
+ v1 := b.NewValue0(x2.Pos, OpOffPtr, p.Type)
+ v1.AuxInt = int64ToAuxInt(int64(i0))
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ // match: (ORshiftLL <t> [24] o0:(ORshiftLL [16] x0:(MOVHUloadidx ptr0 idx0 mem) y1:(MOVDnop x1:(MOVBUload [2] {s} p1:(ADD ptr1 idx1) mem))) y2:(MOVDnop x2:(MOVBUload [3] {s} p mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b,x0,x1,x2) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, y1, y2, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVWUloadidx <t> ptr0 idx0 mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 16 {
+ break
+ }
+ _ = o0.Args[1]
+ x0 := o0.Args[0]
+ if x0.Op != OpARM64MOVHUloadidx {
+ break
+ }
+ mem := x0.Args[2]
+ ptr0 := x0.Args[0]
+ idx0 := x0.Args[1]
+ y1 := o0.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(x1.Aux)
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADD {
+ break
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p1_0, p1_1 = _i0+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ if mem != x1.Args[1] {
+ continue
+ }
+ y2 := v_1
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload || auxIntToInt32(x2.AuxInt) != 3 || auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ p := x2.Args[0]
+ if mem != x2.Args[1] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, y1, y2, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x2.Pos, OpARM64MOVWUloadidx, t)
+ v.copyOf(v0)
+ v0.AddArg3(ptr0, idx0, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORshiftLL <t> [24] o0:(ORshiftLL [16] x0:(MOVHUloadidx ptr idx mem) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [2] idx) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b,x0,x1,x2) != nil && clobber(x0, x1, x2, y1, y2, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVWUloadidx <t> ptr idx mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 16 {
+ break
+ }
+ _ = o0.Args[1]
+ x0 := o0.Args[0]
+ if x0.Op != OpARM64MOVHUloadidx {
+ break
+ }
+ mem := x0.Args[2]
+ ptr := x0.Args[0]
+ idx := x0.Args[1]
+ y1 := o0.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 2 || idx != x1_1.Args[0] || mem != x1.Args[2] {
+ break
+ }
+ y2 := v_1
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x2.Args[2]
+ if ptr != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64ADDconst || auxIntToInt64(x2_1.AuxInt) != 3 || idx != x2_1.Args[0] || mem != x2.Args[2] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, y1, y2, o0)) {
+ break
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVWUloadidx, t)
+ v.copyOf(v0)
+ v0.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (ORshiftLL <t> [24] o0:(ORshiftLL [16] x0:(MOVHUloadidx2 ptr0 idx0 mem) y1:(MOVDnop x1:(MOVBUload [2] {s} p1:(ADDshiftLL [1] ptr1 idx1) mem))) y2:(MOVDnop x2:(MOVBUload [3] {s} p mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b,x0,x1,x2) != nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && isSamePtr(p1, p) && clobber(x0, x1, x2, y1, y2, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVWUloadidx <t> ptr0 (SLLconst <idx0.Type> [1] idx0) mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 16 {
+ break
+ }
+ _ = o0.Args[1]
+ x0 := o0.Args[0]
+ if x0.Op != OpARM64MOVHUloadidx2 {
+ break
+ }
+ mem := x0.Args[2]
+ ptr0 := x0.Args[0]
+ idx0 := x0.Args[1]
+ y1 := o0.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(x1.Aux)
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADDshiftLL || auxIntToInt64(p1.AuxInt) != 1 {
+ break
+ }
+ idx1 := p1.Args[1]
+ ptr1 := p1.Args[0]
+ if mem != x1.Args[1] {
+ break
+ }
+ y2 := v_1
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload || auxIntToInt32(x2.AuxInt) != 3 || auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[1]
+ p := x2.Args[0]
+ if mem != x2.Args[1] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && isSamePtr(p1, p) && clobber(x0, x1, x2, y1, y2, o0)) {
+ break
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x2.Pos, OpARM64MOVWUloadidx, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x2.Pos, OpARM64SLLconst, idx0.Type)
+ v1.AuxInt = int64ToAuxInt(1)
+ v1.AddArg(idx0)
+ v0.AddArg3(ptr0, v1, mem)
+ return true
+ }
+ // match: (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32] x0:(MOVWUload [i0] {s} p mem) y1:(MOVDnop x1:(MOVBUload [i4] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [i5] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [i6] {s} p mem))) y4:(MOVDnop x4:(MOVBUload [i7] {s} p mem)))
+ // cond: i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4) != nil && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4) (MOVDload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 56 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 48 {
+ break
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 40 {
+ break
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 32 {
+ break
+ }
+ _ = o2.Args[1]
+ x0 := o2.Args[0]
+ if x0.Op != OpARM64MOVWUload {
+ break
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o2.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload {
+ break
+ }
+ i4 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ break
+ }
+ y2 := o1.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload {
+ break
+ }
+ i5 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] {
+ break
+ }
+ y3 := o0.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ break
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload {
+ break
+ }
+ i6 := auxIntToInt32(x3.AuxInt)
+ if auxToSym(x3.Aux) != s {
+ break
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] {
+ break
+ }
+ y4 := v_1
+ if y4.Op != OpARM64MOVDnop {
+ break
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUload {
+ break
+ }
+ i7 := auxIntToInt32(x4.AuxInt)
+ if auxToSym(x4.Aux) != s {
+ break
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] || !(i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4) != nil && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)) {
+ break
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4)
+ v0 := b.NewValue0(x4.Pos, OpARM64MOVDload, t)
+ v.copyOf(v0)
+ v0.Aux = symToAux(s)
+ v1 := b.NewValue0(x4.Pos, OpOffPtr, p.Type)
+ v1.AuxInt = int64ToAuxInt(int64(i0))
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ // match: (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32] x0:(MOVWUloadidx ptr0 idx0 mem) y1:(MOVDnop x1:(MOVBUload [4] {s} p1:(ADD ptr1 idx1) mem))) y2:(MOVDnop x2:(MOVBUload [5] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [6] {s} p mem))) y4:(MOVDnop x4:(MOVBUload [7] {s} p mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4) (MOVDloadidx <t> ptr0 idx0 mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 56 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 48 {
+ break
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 40 {
+ break
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 32 {
+ break
+ }
+ _ = o2.Args[1]
+ x0 := o2.Args[0]
+ if x0.Op != OpARM64MOVWUloadidx {
+ break
+ }
+ mem := x0.Args[2]
+ ptr0 := x0.Args[0]
+ idx0 := x0.Args[1]
+ y1 := o2.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 4 {
+ break
+ }
+ s := auxToSym(x1.Aux)
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADD {
+ break
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p1_0, p1_1 = _i0+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ if mem != x1.Args[1] {
+ continue
+ }
+ y2 := o1.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload || auxIntToInt32(x2.AuxInt) != 5 || auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ p := x2.Args[0]
+ if mem != x2.Args[1] {
+ continue
+ }
+ y3 := o0.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ continue
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload || auxIntToInt32(x3.AuxInt) != 6 || auxToSym(x3.Aux) != s {
+ continue
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] {
+ continue
+ }
+ y4 := v_1
+ if y4.Op != OpARM64MOVDnop {
+ continue
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUload || auxIntToInt32(x4.AuxInt) != 7 || auxToSym(x4.Aux) != s {
+ continue
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4)
+ v0 := b.NewValue0(x4.Pos, OpARM64MOVDloadidx, t)
+ v.copyOf(v0)
+ v0.AddArg3(ptr0, idx0, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32] x0:(MOVWUloadidx4 ptr0 idx0 mem) y1:(MOVDnop x1:(MOVBUload [4] {s} p1:(ADDshiftLL [2] ptr1 idx1) mem))) y2:(MOVDnop x2:(MOVBUload [5] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [6] {s} p mem))) y4:(MOVDnop x4:(MOVBUload [7] {s} p mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4) != nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4) (MOVDloadidx <t> ptr0 (SLLconst <idx0.Type> [2] idx0) mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 56 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 48 {
+ break
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 40 {
+ break
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 32 {
+ break
+ }
+ _ = o2.Args[1]
+ x0 := o2.Args[0]
+ if x0.Op != OpARM64MOVWUloadidx4 {
+ break
+ }
+ mem := x0.Args[2]
+ ptr0 := x0.Args[0]
+ idx0 := x0.Args[1]
+ y1 := o2.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 4 {
+ break
+ }
+ s := auxToSym(x1.Aux)
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADDshiftLL || auxIntToInt64(p1.AuxInt) != 2 {
+ break
+ }
+ idx1 := p1.Args[1]
+ ptr1 := p1.Args[0]
+ if mem != x1.Args[1] {
+ break
+ }
+ y2 := o1.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload || auxIntToInt32(x2.AuxInt) != 5 || auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[1]
+ p := x2.Args[0]
+ if mem != x2.Args[1] {
+ break
+ }
+ y3 := o0.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ break
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload || auxIntToInt32(x3.AuxInt) != 6 || auxToSym(x3.Aux) != s {
+ break
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] {
+ break
+ }
+ y4 := v_1
+ if y4.Op != OpARM64MOVDnop {
+ break
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUload || auxIntToInt32(x4.AuxInt) != 7 || auxToSym(x4.Aux) != s {
+ break
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4) != nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)) {
+ break
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4)
+ v0 := b.NewValue0(x4.Pos, OpARM64MOVDloadidx, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x4.Pos, OpARM64SLLconst, idx0.Type)
+ v1.AuxInt = int64ToAuxInt(2)
+ v1.AddArg(idx0)
+ v0.AddArg3(ptr0, v1, mem)
+ return true
+ }
+ // match: (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32] x0:(MOVWUloadidx ptr idx mem) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [4] idx) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [5] idx) mem))) y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [6] idx) mem))) y4:(MOVDnop x4:(MOVBUloadidx ptr (ADDconst [7] idx) mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4) != nil && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4) (MOVDloadidx <t> ptr idx mem)
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 56 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 48 {
+ break
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 40 {
+ break
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 32 {
+ break
+ }
+ _ = o2.Args[1]
+ x0 := o2.Args[0]
+ if x0.Op != OpARM64MOVWUloadidx {
+ break
+ }
+ mem := x0.Args[2]
+ ptr := x0.Args[0]
+ idx := x0.Args[1]
+ y1 := o2.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 4 || idx != x1_1.Args[0] || mem != x1.Args[2] {
+ break
+ }
+ y2 := o1.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x2.Args[2]
+ if ptr != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64ADDconst || auxIntToInt64(x2_1.AuxInt) != 5 || idx != x2_1.Args[0] || mem != x2.Args[2] {
+ break
+ }
+ y3 := o0.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ break
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x3.Args[2]
+ if ptr != x3.Args[0] {
+ break
+ }
+ x3_1 := x3.Args[1]
+ if x3_1.Op != OpARM64ADDconst || auxIntToInt64(x3_1.AuxInt) != 6 || idx != x3_1.Args[0] || mem != x3.Args[2] {
+ break
+ }
+ y4 := v_1
+ if y4.Op != OpARM64MOVDnop {
+ break
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x4.Args[2]
+ if ptr != x4.Args[0] {
+ break
+ }
+ x4_1 := x4.Args[1]
+ if x4_1.Op != OpARM64ADDconst || auxIntToInt64(x4_1.AuxInt) != 7 || idx != x4_1.Args[0] || mem != x4.Args[2] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4) != nil && clobber(x0, x1, x2, x3, x4, y1, y2, y3, y4, o0, o1, o2)) {
+ break
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDloadidx, t)
+ v.copyOf(v0)
+ v0.AddArg3(ptr, idx, mem)
+ return true
+ }
+ // match: (ORshiftLL <t> [8] y0:(MOVDnop x0:(MOVBUload [i1] {s} p mem)) y1:(MOVDnop x1:(MOVBUload [i0] {s} p mem)))
+ // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, y0, y1)
+ // result: @mergePoint(b,x0,x1) (REV16W <t> (MOVHUload <t> [i0] {s} p mem))
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ y0 := v_0
+ if y0.Op != OpARM64MOVDnop {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUload {
+ break
+ }
+ i1 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := v_1
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload {
+ break
+ }
+ i0 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, y0, y1)) {
+ break
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpARM64REV16W, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpARM64MOVHUload, t)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ // match: (ORshiftLL <t> [8] y0:(MOVDnop x0:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)) y1:(MOVDnop x1:(MOVBUloadidx ptr0 idx0 mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b,x0,x1) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x0, x1, y0, y1)
+ // result: @mergePoint(b,x0,x1) (REV16W <t> (MOVHUloadidx <t> ptr0 idx0 mem))
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ y0 := v_0
+ if y0.Op != OpARM64MOVDnop {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUload || auxIntToInt32(x0.AuxInt) != 1 {
+ break
+ }
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p1 := x0.Args[0]
+ if p1.Op != OpARM64ADD {
+ break
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p1_0, p1_1 = _i0+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ y1 := v_1
+ if y1.Op != OpARM64MOVDnop {
+ continue
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x1.Args[2]
+ ptr0 := x1.Args[0]
+ idx0 := x1.Args[1]
+ if mem != x1.Args[2] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b, x0, x1) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && clobber(x0, x1, y0, y1)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpARM64REV16W, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpARM64MOVHUloadidx, t)
+ v1.AddArg3(ptr0, idx0, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORshiftLL <t> [8] y0:(MOVDnop x0:(MOVBUloadidx ptr (ADDconst [1] idx) mem)) y1:(MOVDnop x1:(MOVBUloadidx ptr idx mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, y0, y1)
+ // result: @mergePoint(b,x0,x1) (REV16W <t> (MOVHUloadidx <t> ptr idx mem))
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ y0 := v_0
+ if y0.Op != OpARM64MOVDnop {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ mem := x0.Args[2]
+ ptr := x0.Args[0]
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64ADDconst || auxIntToInt64(x0_1.AuxInt) != 1 {
+ break
+ }
+ idx := x0_1.Args[0]
+ y1 := v_1
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] || idx != x1.Args[1] || mem != x1.Args[2] || !(x0.Uses == 1 && x1.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, y0, y1)) {
+ break
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(v.Pos, OpARM64REV16W, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVHUloadidx, t)
+ v1.AddArg3(ptr, idx, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ // match: (ORshiftLL <t> [24] o0:(ORshiftLL [16] y0:(REV16W x0:(MOVHUload [i2] {s} p mem)) y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [i0] {s} p mem)))
+ // cond: i1 == i0+1 && i2 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b,x0,x1,x2) != nil && clobber(x0, x1, x2, y0, y1, y2, o0)
+ // result: @mergePoint(b,x0,x1,x2) (REVW <t> (MOVWUload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem))
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 16 {
+ break
+ }
+ _ = o0.Args[1]
+ y0 := o0.Args[0]
+ if y0.Op != OpARM64REV16W {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVHUload {
+ break
+ }
+ i2 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o0.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload {
+ break
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ break
+ }
+ y2 := v_1
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload {
+ break
+ }
+ i0 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] || !(i1 == i0+1 && i2 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, y0, y1, y2, o0)) {
+ break
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x2.Pos, OpARM64REVW, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x2.Pos, OpARM64MOVWUload, t)
+ v1.Aux = symToAux(s)
+ v2 := b.NewValue0(x2.Pos, OpOffPtr, p.Type)
+ v2.AuxInt = int64ToAuxInt(int64(i0))
+ v2.AddArg(p)
+ v1.AddArg2(v2, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ // match: (ORshiftLL <t> [24] o0:(ORshiftLL [16] y0:(REV16W x0:(MOVHUload [2] {s} p mem)) y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr0 idx0 mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b,x0,x1,x2) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, y0, y1, y2, o0)
+ // result: @mergePoint(b,x0,x1,x2) (REVW <t> (MOVWUloadidx <t> ptr0 idx0 mem))
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 16 {
+ break
+ }
+ _ = o0.Args[1]
+ y0 := o0.Args[0]
+ if y0.Op != OpARM64REV16W {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVHUload || auxIntToInt32(x0.AuxInt) != 2 {
+ break
+ }
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o0.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 1 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[1]
+ p1 := x1.Args[0]
+ if p1.Op != OpARM64ADD {
+ break
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p1_0, p1_1 = _i0+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ if mem != x1.Args[1] {
+ continue
+ }
+ y2 := v_1
+ if y2.Op != OpARM64MOVDnop {
+ continue
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x2.Args[2]
+ ptr0 := x2.Args[0]
+ idx0 := x2.Args[1]
+ if mem != x2.Args[2] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, y0, y1, y2, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x1.Pos, OpARM64REVW, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpARM64MOVWUloadidx, t)
+ v1.AddArg3(ptr0, idx0, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORshiftLL <t> [24] o0:(ORshiftLL [16] y0:(REV16W x0:(MOVHUloadidx ptr (ADDconst [2] idx) mem)) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr idx mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b,x0,x1,x2) != nil && clobber(x0, x1, x2, y0, y1, y2, o0)
+ // result: @mergePoint(b,x0,x1,x2) (REVW <t> (MOVWUloadidx <t> ptr idx mem))
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 16 {
+ break
+ }
+ _ = o0.Args[1]
+ y0 := o0.Args[0]
+ if y0.Op != OpARM64REV16W {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVHUloadidx {
+ break
+ }
+ mem := x0.Args[2]
+ ptr := x0.Args[0]
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64ADDconst || auxIntToInt64(x0_1.AuxInt) != 2 {
+ break
+ }
+ idx := x0_1.Args[0]
+ y1 := o0.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 1 || idx != x1_1.Args[0] || mem != x1.Args[2] {
+ break
+ }
+ y2 := v_1
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x2.Args[2]
+ if ptr != x2.Args[0] || idx != x2.Args[1] || mem != x2.Args[2] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && o0.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, y0, y1, y2, o0)) {
+ break
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(v.Pos, OpARM64REVW, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVWUloadidx, t)
+ v1.AddArg3(ptr, idx, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ // match: (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32] y0:(REVW x0:(MOVWUload [i4] {s} p mem)) y1:(MOVDnop x1:(MOVBUload [i3] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [i2] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [i1] {s} p mem))) y4:(MOVDnop x4:(MOVBUload [i0] {s} p mem)))
+ // cond: i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4) != nil && clobber(x0, x1, x2, x3, x4, y0, y1, y2, y3, y4, o0, o1, o2)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4) (REV <t> (MOVDload <t> {s} (OffPtr <p.Type> [int64(i0)] p) mem))
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 56 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 48 {
+ break
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 40 {
+ break
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 32 {
+ break
+ }
+ _ = o2.Args[1]
+ y0 := o2.Args[0]
+ if y0.Op != OpARM64REVW {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVWUload {
+ break
+ }
+ i4 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o2.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload {
+ break
+ }
+ i3 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ break
+ }
+ y2 := o1.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload {
+ break
+ }
+ i2 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] {
+ break
+ }
+ y3 := o0.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ break
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload {
+ break
+ }
+ i1 := auxIntToInt32(x3.AuxInt)
+ if auxToSym(x3.Aux) != s {
+ break
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] {
+ break
+ }
+ y4 := v_1
+ if y4.Op != OpARM64MOVDnop {
+ break
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUload {
+ break
+ }
+ i0 := auxIntToInt32(x4.AuxInt)
+ if auxToSym(x4.Aux) != s {
+ break
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] || !(i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4) != nil && clobber(x0, x1, x2, x3, x4, y0, y1, y2, y3, y4, o0, o1, o2)) {
+ break
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4)
+ v0 := b.NewValue0(x4.Pos, OpARM64REV, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x4.Pos, OpARM64MOVDload, t)
+ v1.Aux = symToAux(s)
+ v2 := b.NewValue0(x4.Pos, OpOffPtr, p.Type)
+ v2.AuxInt = int64ToAuxInt(int64(i0))
+ v2.AddArg(p)
+ v1.AddArg2(v2, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ // match: (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32] y0:(REVW x0:(MOVWUload [4] {s} p mem)) y1:(MOVDnop x1:(MOVBUload [3] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [2] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem))) y4:(MOVDnop x4:(MOVBUloadidx ptr0 idx0 mem)))
+ // cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, y0, y1, y2, y3, y4, o0, o1, o2)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4) (REV <t> (MOVDloadidx <t> ptr0 idx0 mem))
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 56 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 48 {
+ break
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 40 {
+ break
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 32 {
+ break
+ }
+ _ = o2.Args[1]
+ y0 := o2.Args[0]
+ if y0.Op != OpARM64REVW {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVWUload || auxIntToInt32(x0.AuxInt) != 4 {
+ break
+ }
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ y1 := o2.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUload || auxIntToInt32(x1.AuxInt) != 3 || auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ break
+ }
+ y2 := o1.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUload || auxIntToInt32(x2.AuxInt) != 2 || auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] {
+ break
+ }
+ y3 := o0.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ break
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUload || auxIntToInt32(x3.AuxInt) != 1 || auxToSym(x3.Aux) != s {
+ break
+ }
+ _ = x3.Args[1]
+ p1 := x3.Args[0]
+ if p1.Op != OpARM64ADD {
+ break
+ }
+ _ = p1.Args[1]
+ p1_0 := p1.Args[0]
+ p1_1 := p1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, p1_0, p1_1 = _i0+1, p1_1, p1_0 {
+ ptr1 := p1_0
+ idx1 := p1_1
+ if mem != x3.Args[1] {
+ continue
+ }
+ y4 := v_1
+ if y4.Op != OpARM64MOVDnop {
+ continue
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUloadidx {
+ continue
+ }
+ _ = x4.Args[2]
+ ptr0 := x4.Args[0]
+ idx0 := x4.Args[1]
+ if mem != x4.Args[2] || !(s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0, x1, x2, x3, x4, y0, y1, y2, y3, y4, o0, o1, o2)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4)
+ v0 := b.NewValue0(x3.Pos, OpARM64REV, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x3.Pos, OpARM64MOVDloadidx, t)
+ v1.AddArg3(ptr0, idx0, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32] y0:(REVW x0:(MOVWUloadidx ptr (ADDconst [4] idx) mem)) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [3] idx) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [2] idx) mem))) y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [1] idx) mem))) y4:(MOVDnop x4:(MOVBUloadidx ptr idx mem)))
+ // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4) != nil && clobber(x0, x1, x2, x3, x4, y0, y1, y2, y3, y4, o0, o1, o2)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4) (REV <t> (MOVDloadidx <t> ptr idx mem))
+ for {
+ t := v.Type
+ if auxIntToInt64(v.AuxInt) != 56 {
+ break
+ }
+ o0 := v_0
+ if o0.Op != OpARM64ORshiftLL || auxIntToInt64(o0.AuxInt) != 48 {
+ break
+ }
+ _ = o0.Args[1]
+ o1 := o0.Args[0]
+ if o1.Op != OpARM64ORshiftLL || auxIntToInt64(o1.AuxInt) != 40 {
+ break
+ }
+ _ = o1.Args[1]
+ o2 := o1.Args[0]
+ if o2.Op != OpARM64ORshiftLL || auxIntToInt64(o2.AuxInt) != 32 {
+ break
+ }
+ _ = o2.Args[1]
+ y0 := o2.Args[0]
+ if y0.Op != OpARM64REVW {
+ break
+ }
+ x0 := y0.Args[0]
+ if x0.Op != OpARM64MOVWUloadidx {
+ break
+ }
+ mem := x0.Args[2]
+ ptr := x0.Args[0]
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpARM64ADDconst || auxIntToInt64(x0_1.AuxInt) != 4 {
+ break
+ }
+ idx := x0_1.Args[0]
+ y1 := o2.Args[1]
+ if y1.Op != OpARM64MOVDnop {
+ break
+ }
+ x1 := y1.Args[0]
+ if x1.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x1.Args[2]
+ if ptr != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpARM64ADDconst || auxIntToInt64(x1_1.AuxInt) != 3 || idx != x1_1.Args[0] || mem != x1.Args[2] {
+ break
+ }
+ y2 := o1.Args[1]
+ if y2.Op != OpARM64MOVDnop {
+ break
+ }
+ x2 := y2.Args[0]
+ if x2.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x2.Args[2]
+ if ptr != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpARM64ADDconst || auxIntToInt64(x2_1.AuxInt) != 2 || idx != x2_1.Args[0] || mem != x2.Args[2] {
+ break
+ }
+ y3 := o0.Args[1]
+ if y3.Op != OpARM64MOVDnop {
+ break
+ }
+ x3 := y3.Args[0]
+ if x3.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x3.Args[2]
+ if ptr != x3.Args[0] {
+ break
+ }
+ x3_1 := x3.Args[1]
+ if x3_1.Op != OpARM64ADDconst || auxIntToInt64(x3_1.AuxInt) != 1 || idx != x3_1.Args[0] || mem != x3.Args[2] {
+ break
+ }
+ y4 := v_1
+ if y4.Op != OpARM64MOVDnop {
+ break
+ }
+ x4 := y4.Args[0]
+ if x4.Op != OpARM64MOVBUloadidx {
+ break
+ }
+ _ = x4.Args[2]
+ if ptr != x4.Args[0] || idx != x4.Args[1] || mem != x4.Args[2] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4) != nil && clobber(x0, x1, x2, x3, x4, y0, y1, y2, y3, y4, o0, o1, o2)) {
+ break
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4)
+ v0 := b.NewValue0(v.Pos, OpARM64REV, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVDloadidx, t)
+ v1.AddArg3(ptr, idx, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ORshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ORshiftRA (MOVDconst [c]) x [d])
+ // result: (ORconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ORshiftRA x (MOVDconst [c]) [d])
+ // result: (ORconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORshiftRA y:(SRAconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ y := v_0
+ if y.Op != OpARM64SRAconst || auxIntToInt64(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ORshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ORshiftRL (MOVDconst [c]) x [d])
+ // result: (ORconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ORshiftRL x (MOVDconst [c]) [d])
+ // result: (ORconst x [int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64ORconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORshiftRL y:(SRLconst x [c]) x [c])
+ // result: y
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ y := v_0
+ if y.Op != OpARM64SRLconst || auxIntToInt64(y.AuxInt) != c {
+ break
+ }
+ x := y.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: ( ORshiftRL [c] (SLLconst x [64-c]) x)
+ // result: (RORconst [ c] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 64-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64RORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: ( ORshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x))
+ // cond: c < 32 && t.Size() == 4
+ // result: (RORWconst [c] x)
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 32-c {
+ break
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpARM64MOVWUreg || x != v_1.Args[0] || !(c < 32 && t.Size() == 4) {
+ break
+ }
+ v.reset(OpARM64RORWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORshiftRL [rc] (ANDconst [ac] x) (SLLconst [lc] y))
+ // cond: lc > rc && ac == ^((1<<uint(64-lc)-1) << uint64(lc-rc))
+ // result: (BFI [armBFAuxInt(lc-rc, 64-lc)] x y)
+ for {
+ rc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ ac := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpARM64SLLconst {
+ break
+ }
+ lc := auxIntToInt64(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(lc > rc && ac == ^((1<<uint(64-lc)-1)<<uint64(lc-rc))) {
+ break
+ }
+ v.reset(OpARM64BFI)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc-rc, 64-lc))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ORshiftRL [rc] (ANDconst [ac] y) (SLLconst [lc] x))
+ // cond: lc < rc && ac == ^((1<<uint(64-rc)-1))
+ // result: (BFXIL [armBFAuxInt(rc-lc, 64-rc)] y x)
+ for {
+ rc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ ac := auxIntToInt64(v_0.AuxInt)
+ y := v_0.Args[0]
+ if v_1.Op != OpARM64SLLconst {
+ break
+ }
+ lc := auxIntToInt64(v_1.AuxInt)
+ x := v_1.Args[0]
+ if !(lc < rc && ac == ^(1<<uint(64-rc)-1)) {
+ break
+ }
+ v.reset(OpARM64BFXIL)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc-lc, 64-rc))
+ v.AddArg2(y, x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64RORWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (RORWconst [c] (RORWconst [d] x))
+ // result: (RORWconst [(c+d)&31] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64RORWconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64RORWconst)
+ v.AuxInt = int64ToAuxInt((c + d) & 31)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64RORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (RORconst [c] (RORconst [d] x))
+ // result: (RORconst [(c+d)&63] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64RORconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64RORconst)
+ v.AuxInt = int64ToAuxInt((c + d) & 63)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SBCSflags(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags (NEG <typ.UInt64> (NGCzerocarry <typ.UInt64> bo)))))
+ // result: (SBCSflags x y bo)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpSelect1 || v_2.Type != types.TypeFlags {
+ break
+ }
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpARM64NEGSflags {
+ break
+ }
+ v_2_0_0 := v_2_0.Args[0]
+ if v_2_0_0.Op != OpARM64NEG || v_2_0_0.Type != typ.UInt64 {
+ break
+ }
+ v_2_0_0_0 := v_2_0_0.Args[0]
+ if v_2_0_0_0.Op != OpARM64NGCzerocarry || v_2_0_0_0.Type != typ.UInt64 {
+ break
+ }
+ bo := v_2_0_0_0.Args[0]
+ v.reset(OpARM64SBCSflags)
+ v.AddArg3(x, y, bo)
+ return true
+ }
+ // match: (SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags (MOVDconst [0]))))
+ // result: (SUBSflags x y)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpSelect1 || v_2.Type != types.TypeFlags {
+ break
+ }
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpARM64NEGSflags {
+ break
+ }
+ v_2_0_0 := v_2_0.Args[0]
+ if v_2_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_2_0_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpARM64SUBSflags)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SLL x (MOVDconst [c]))
+ // result: (SLLconst x [c&63])
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64SLLconst)
+ v.AuxInt = int64ToAuxInt(c & 63)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SLLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SLLconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [d<<uint64(c)])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(d << uint64(c))
+ return true
+ }
+ // match: (SLLconst [c] (SRLconst [c] x))
+ // cond: 0 < c && c < 64
+ // result: (ANDconst [^(1<<uint(c)-1)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if !(0 < c && c < 64) {
+ break
+ }
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(^(1<<uint(c) - 1))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLLconst [sc] (ANDconst [ac] x))
+ // cond: isARM64BFMask(sc, ac, 0)
+ // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ ac := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, ac, 0)) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(ac, 0)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLLconst [sc] (MOVWUreg x))
+ // cond: isARM64BFMask(sc, 1<<32-1, 0)
+ // result: (UBFIZ [armBFAuxInt(sc, 32)] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<32-1, 0)) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 32))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLLconst [sc] (MOVHUreg x))
+ // cond: isARM64BFMask(sc, 1<<16-1, 0)
+ // result: (UBFIZ [armBFAuxInt(sc, 16)] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVHUreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<16-1, 0)) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 16))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLLconst [sc] (MOVBUreg x))
+ // cond: isARM64BFMask(sc, 1<<8-1, 0)
+ // result: (UBFIZ [armBFAuxInt(sc, 8)] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVBUreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<8-1, 0)) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 8))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLLconst [sc] (UBFIZ [bfc] x))
+ // cond: sc+bfc.getARM64BFwidth()+bfc.getARM64BFlsb() < 64
+ // result: (UBFIZ [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth())] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFIZ {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc+bfc.getARM64BFwidth()+bfc.getARM64BFlsb() < 64) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRA x (MOVDconst [c]))
+ // result: (SRAconst x [c&63])
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64SRAconst)
+ v.AuxInt = int64ToAuxInt(c & 63)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SRAconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRAconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [d>>uint64(c)])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(d >> uint64(c))
+ return true
+ }
+ // match: (SRAconst [rc] (SLLconst [lc] x))
+ // cond: lc > rc
+ // result: (SBFIZ [armBFAuxInt(lc-rc, 64-lc)] x)
+ for {
+ rc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ lc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(lc > rc) {
+ break
+ }
+ v.reset(OpARM64SBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc-rc, 64-lc))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAconst [rc] (SLLconst [lc] x))
+ // cond: lc <= rc
+ // result: (SBFX [armBFAuxInt(rc-lc, 64-rc)] x)
+ for {
+ rc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ lc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(lc <= rc) {
+ break
+ }
+ v.reset(OpARM64SBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc-lc, 64-rc))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAconst [rc] (MOVWreg x))
+ // cond: rc < 32
+ // result: (SBFX [armBFAuxInt(rc, 32-rc)] x)
+ for {
+ rc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(rc < 32) {
+ break
+ }
+ v.reset(OpARM64SBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 32-rc))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAconst [rc] (MOVHreg x))
+ // cond: rc < 16
+ // result: (SBFX [armBFAuxInt(rc, 16-rc)] x)
+ for {
+ rc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVHreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(rc < 16) {
+ break
+ }
+ v.reset(OpARM64SBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 16-rc))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAconst [rc] (MOVBreg x))
+ // cond: rc < 8
+ // result: (SBFX [armBFAuxInt(rc, 8-rc)] x)
+ for {
+ rc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVBreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(rc < 8) {
+ break
+ }
+ v.reset(OpARM64SBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 8-rc))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAconst [sc] (SBFIZ [bfc] x))
+ // cond: sc < bfc.getARM64BFlsb()
+ // result: (SBFIZ [armBFAuxInt(bfc.getARM64BFlsb()-sc, bfc.getARM64BFwidth())] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SBFIZ {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc < bfc.getARM64BFlsb()) {
+ break
+ }
+ v.reset(OpARM64SBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(bfc.getARM64BFlsb()-sc, bfc.getARM64BFwidth()))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAconst [sc] (SBFIZ [bfc] x))
+ // cond: sc >= bfc.getARM64BFlsb() && sc < bfc.getARM64BFlsb()+bfc.getARM64BFwidth()
+ // result: (SBFX [armBFAuxInt(sc-bfc.getARM64BFlsb(), bfc.getARM64BFlsb()+bfc.getARM64BFwidth()-sc)] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SBFIZ {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc >= bfc.getARM64BFlsb() && sc < bfc.getARM64BFlsb()+bfc.getARM64BFwidth()) {
+ break
+ }
+ v.reset(OpARM64SBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc-bfc.getARM64BFlsb(), bfc.getARM64BFlsb()+bfc.getARM64BFwidth()-sc))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRL x (MOVDconst [c]))
+ // result: (SRLconst x [c&63])
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64SRLconst)
+ v.AuxInt = int64ToAuxInt(c & 63)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SRLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRLconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [int64(uint64(d)>>uint64(c))])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(d) >> uint64(c)))
+ return true
+ }
+ // match: (SRLconst [c] (SLLconst [c] x))
+ // cond: 0 < c && c < 64
+ // result: (ANDconst [1<<uint(64-c)-1] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if !(0 < c && c < 64) {
+ break
+ }
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(1<<uint(64-c) - 1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRLconst [rc] (SLLconst [lc] x))
+ // cond: lc > rc
+ // result: (UBFIZ [armBFAuxInt(lc-rc, 64-lc)] x)
+ for {
+ rc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ lc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(lc > rc) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc-rc, 64-lc))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRLconst [sc] (ANDconst [ac] x))
+ // cond: isARM64BFMask(sc, ac, sc)
+ // result: (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ ac := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, ac, sc)) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(ac, sc)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRLconst [sc] (MOVWUreg x))
+ // cond: isARM64BFMask(sc, 1<<32-1, sc)
+ // result: (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<32-1, sc)) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRLconst [sc] (MOVHUreg x))
+ // cond: isARM64BFMask(sc, 1<<16-1, sc)
+ // result: (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVHUreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<16-1, sc)) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRLconst [sc] (MOVBUreg x))
+ // cond: isARM64BFMask(sc, 1<<8-1, sc)
+ // result: (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVBUreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(isARM64BFMask(sc, 1<<8-1, sc)) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRLconst [rc] (SLLconst [lc] x))
+ // cond: lc < rc
+ // result: (UBFX [armBFAuxInt(rc-lc, 64-rc)] x)
+ for {
+ rc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ lc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(lc < rc) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc-lc, 64-rc))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRLconst [sc] (UBFX [bfc] x))
+ // cond: sc < bfc.getARM64BFwidth()
+ // result: (UBFX [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()-sc)] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFX {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc < bfc.getARM64BFwidth()) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()-sc))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRLconst [sc] (UBFIZ [bfc] x))
+ // cond: sc == bfc.getARM64BFlsb()
+ // result: (ANDconst [1<<uint(bfc.getARM64BFwidth())-1] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFIZ {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc == bfc.getARM64BFlsb()) {
+ break
+ }
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(1<<uint(bfc.getARM64BFwidth()) - 1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRLconst [sc] (UBFIZ [bfc] x))
+ // cond: sc < bfc.getARM64BFlsb()
+ // result: (UBFIZ [armBFAuxInt(bfc.getARM64BFlsb()-sc, bfc.getARM64BFwidth())] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFIZ {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc < bfc.getARM64BFlsb()) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(bfc.getARM64BFlsb()-sc, bfc.getARM64BFwidth()))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRLconst [sc] (UBFIZ [bfc] x))
+ // cond: sc > bfc.getARM64BFlsb() && sc < bfc.getARM64BFlsb()+bfc.getARM64BFwidth()
+ // result: (UBFX [armBFAuxInt(sc-bfc.getARM64BFlsb(), bfc.getARM64BFlsb()+bfc.getARM64BFwidth()-sc)] x)
+ for {
+ sc := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFIZ {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc > bfc.getARM64BFlsb() && sc < bfc.getARM64BFlsb()+bfc.getARM64BFwidth()) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc-bfc.getARM64BFlsb(), bfc.getARM64BFlsb()+bfc.getARM64BFwidth()-sc))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64STP(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (STP [off1] {sym} (ADDconst [off2] ptr) val1 val2 mem)
+ // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (STP [off1+int32(off2)] {sym} ptr val1 val2 mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val1 := v_1
+ val2 := v_2
+ mem := v_3
+ if !(is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64STP)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg4(ptr, val1, val2, mem)
+ return true
+ }
+ // match: (STP [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val1 val2 mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
+ // result: (STP [off1+off2] {mergeSym(sym1,sym2)} ptr val1 val2 mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpARM64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val1 := v_1
+ val2 := v_2
+ mem := v_3
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)) {
+ break
+ }
+ v.reset(OpARM64STP)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg4(ptr, val1, val2, mem)
+ return true
+ }
+ // match: (STP [off] {sym} ptr (MOVDconst [0]) (MOVDconst [0]) mem)
+ // result: (MOVQstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 || v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 {
+ break
+ }
+ mem := v_3
+ v.reset(OpARM64MOVQstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SUB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUB x (MOVDconst [c]))
+ // result: (SUBconst [c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64SUBconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB a l:(MUL x y))
+ // cond: l.Uses==1 && clobber(l)
+ // result: (MSUB a x y)
+ for {
+ a := v_0
+ l := v_1
+ if l.Op != OpARM64MUL {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1 && clobber(l)) {
+ break
+ }
+ v.reset(OpARM64MSUB)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (SUB a l:(MNEG x y))
+ // cond: l.Uses==1 && clobber(l)
+ // result: (MADD a x y)
+ for {
+ a := v_0
+ l := v_1
+ if l.Op != OpARM64MNEG {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(l.Uses == 1 && clobber(l)) {
+ break
+ }
+ v.reset(OpARM64MADD)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (SUB a l:(MULW x y))
+ // cond: a.Type.Size() != 8 && l.Uses==1 && clobber(l)
+ // result: (MSUBW a x y)
+ for {
+ a := v_0
+ l := v_1
+ if l.Op != OpARM64MULW {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(a.Type.Size() != 8 && l.Uses == 1 && clobber(l)) {
+ break
+ }
+ v.reset(OpARM64MSUBW)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (SUB a l:(MNEGW x y))
+ // cond: a.Type.Size() != 8 && l.Uses==1 && clobber(l)
+ // result: (MADDW a x y)
+ for {
+ a := v_0
+ l := v_1
+ if l.Op != OpARM64MNEGW {
+ break
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ if !(a.Type.Size() != 8 && l.Uses == 1 && clobber(l)) {
+ break
+ }
+ v.reset(OpARM64MADDW)
+ v.AddArg3(a, x, y)
+ return true
+ }
+ // match: (SUB x x)
+ // result: (MOVDconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SUB x (SUB y z))
+ // result: (SUB (ADD <v.Type> x z) y)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64SUB {
+ break
+ }
+ z := v_1.Args[1]
+ y := v_1.Args[0]
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64ADD, v.Type)
+ v0.AddArg2(x, z)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (SUB (SUB x y) z)
+ // result: (SUB x (ADD <y.Type> y z))
+ for {
+ if v_0.Op != OpARM64SUB {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_1
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64ADD, y.Type)
+ v0.AddArg2(y, z)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SUB x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (SUBshiftLL x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (SUB x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (SUBshiftRL x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ // match: (SUB x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (SUBshiftRA x0 y [c])
+ for {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ break
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SUBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SUBconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUBconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [d-c])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(d - c)
+ return true
+ }
+ // match: (SUBconst [c] (SUBconst [d] x))
+ // result: (ADDconst [-c-d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SUBconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(-c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBconst [c] (ADDconst [d] x))
+ // result: (ADDconst [-c+d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64ADDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(-c + d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SUBshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBshiftLL x (MOVDconst [c]) [d])
+ // result: (SUBconst x [int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64SUBconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBshiftLL (SLLconst x [c]) x [c])
+ // result: (MOVDconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SUBshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBshiftRA x (MOVDconst [c]) [d])
+ // result: (SUBconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64SUBconst)
+ v.AuxInt = int64ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBshiftRA (SRAconst x [c]) x [c])
+ // result: (MOVDconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRAconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64SUBshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBshiftRL x (MOVDconst [c]) [d])
+ // result: (SUBconst x [int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64SUBconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBshiftRL (SRLconst x [c]) x [c])
+ // result: (MOVDconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64TST(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (TST x (MOVDconst [c]))
+ // result: (TSTconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (TST x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (TSTshiftLL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64TSTshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (TST x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (TSTshiftRL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64TSTshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (TST x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (TSTshiftRA x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64TSTshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64TSTW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (TSTW x (MOVDconst [c]))
+ // result: (TSTWconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64TSTWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64TSTWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (TSTWconst (MOVDconst [x]) [y])
+ // result: (FlagConstant [logicFlags32(int32(x)&y)])
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(logicFlags32(int32(x) & y))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64TSTconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (TSTconst (MOVDconst [x]) [y])
+ // result: (FlagConstant [logicFlags64(x&y)])
+ for {
+ y := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64FlagConstant)
+ v.AuxInt = flagConstantToAuxInt(logicFlags64(x & y))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64TSTshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TSTshiftLL (MOVDconst [c]) x [d])
+ // result: (TSTconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftLL x (MOVDconst [c]) [d])
+ // result: (TSTconst x [int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64TSTshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TSTshiftRA (MOVDconst [c]) x [d])
+ // result: (TSTconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftRA x (MOVDconst [c]) [d])
+ // result: (TSTconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = int64ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64TSTshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (TSTshiftRL (MOVDconst [c]) x [d])
+ // result: (TSTconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftRL x (MOVDconst [c]) [d])
+ // result: (TSTconst x [int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64UBFIZ(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (UBFIZ [bfc] (SLLconst [sc] x))
+ // cond: sc < bfc.getARM64BFwidth()
+ // result: (UBFIZ [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()-sc)] x)
+ for {
+ bfc := auxIntToArm64BitField(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc < bfc.getARM64BFwidth()) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()-sc))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64UBFX(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (UBFX [bfc] (SRLconst [sc] x))
+ // cond: sc+bfc.getARM64BFwidth()+bfc.getARM64BFlsb() < 64
+ // result: (UBFX [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth())] x)
+ for {
+ bfc := auxIntToArm64BitField(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc+bfc.getARM64BFwidth()+bfc.getARM64BFlsb() < 64) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()))
+ v.AddArg(x)
+ return true
+ }
+ // match: (UBFX [bfc] (SLLconst [sc] x))
+ // cond: sc == bfc.getARM64BFlsb()
+ // result: (ANDconst [1<<uint(bfc.getARM64BFwidth())-1] x)
+ for {
+ bfc := auxIntToArm64BitField(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc == bfc.getARM64BFlsb()) {
+ break
+ }
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(1<<uint(bfc.getARM64BFwidth()) - 1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (UBFX [bfc] (SLLconst [sc] x))
+ // cond: sc < bfc.getARM64BFlsb()
+ // result: (UBFX [armBFAuxInt(bfc.getARM64BFlsb()-sc, bfc.getARM64BFwidth())] x)
+ for {
+ bfc := auxIntToArm64BitField(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc < bfc.getARM64BFlsb()) {
+ break
+ }
+ v.reset(OpARM64UBFX)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(bfc.getARM64BFlsb()-sc, bfc.getARM64BFwidth()))
+ v.AddArg(x)
+ return true
+ }
+ // match: (UBFX [bfc] (SLLconst [sc] x))
+ // cond: sc > bfc.getARM64BFlsb() && sc < bfc.getARM64BFlsb()+bfc.getARM64BFwidth()
+ // result: (UBFIZ [armBFAuxInt(sc-bfc.getARM64BFlsb(), bfc.getARM64BFlsb()+bfc.getARM64BFwidth()-sc)] x)
+ for {
+ bfc := auxIntToArm64BitField(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst {
+ break
+ }
+ sc := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sc > bfc.getARM64BFlsb() && sc < bfc.getARM64BFlsb()+bfc.getARM64BFwidth()) {
+ break
+ }
+ v.reset(OpARM64UBFIZ)
+ v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc-bfc.getARM64BFlsb(), bfc.getARM64BFlsb()+bfc.getARM64BFwidth()-sc))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64UDIV(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (UDIV x (MOVDconst [1]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (UDIV x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (SRLconst [log64(c)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpARM64SRLconst)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (UDIV (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
+ // result: (MOVDconst [int64(uint64(c)/uint64(d))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64UDIVW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (UDIVW x (MOVDconst [c]))
+ // cond: uint32(c)==1
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) == 1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (UDIVW x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c) && is32Bit(c)
+ // result: (SRLconst [log64(c)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SRLconst)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (UDIVW (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
+ // result: (MOVDconst [int64(uint32(c)/uint32(d))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint32(c) / uint32(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64UMOD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (UMOD <typ.UInt64> x y)
+ // result: (MSUB <typ.UInt64> x y (UDIV <typ.UInt64> x y))
+ for {
+ if v.Type != typ.UInt64 {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpARM64MSUB)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpARM64UDIV, typ.UInt64)
+ v0.AddArg2(x, y)
+ v.AddArg3(x, y, v0)
+ return true
+ }
+ // match: (UMOD _ (MOVDconst [1]))
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (UMOD x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (ANDconst [c-1] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c - 1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (UMOD (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
+ // result: (MOVDconst [int64(uint64(c)%uint64(d))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64UMODW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (UMODW <typ.UInt32> x y)
+ // result: (MSUBW <typ.UInt32> x y (UDIVW <typ.UInt32> x y))
+ for {
+ if v.Type != typ.UInt32 {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpARM64MSUBW)
+ v.Type = typ.UInt32
+ v0 := b.NewValue0(v.Pos, OpARM64UDIVW, typ.UInt32)
+ v0.AddArg2(x, y)
+ v.AddArg3(x, y, v0)
+ return true
+ }
+ // match: (UMODW _ (MOVDconst [c]))
+ // cond: uint32(c)==1
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) == 1) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (UMODW x (MOVDconst [c]))
+ // cond: isPowerOfTwo64(c) && is32Bit(c)
+ // result: (ANDconst [c-1] x)
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ANDconst)
+ v.AuxInt = int64ToAuxInt(c - 1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (UMODW (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
+ // result: (MOVDconst [int64(uint32(c)%uint32(d))])
+ for {
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint32(c) % uint32(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64XOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (XOR x (MOVDconst [c]))
+ // result: (XORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR x x)
+ // result: (MOVDconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (XOR x (MVN y))
+ // result: (EON x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpARM64MVN {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpARM64EON)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (XORshiftLL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SLLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64XORshiftLL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (XORshiftRL x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRLconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64XORshiftRL)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (XORshiftRA x0 y [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ x1 := v_1
+ if x1.Op != OpARM64SRAconst {
+ continue
+ }
+ c := auxIntToInt64(x1.AuxInt)
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ continue
+ }
+ v.reset(OpARM64XORshiftRA)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x0, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR (SLL x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> [cc] (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (ROR x (NEG <t> y))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt64 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL || v_1_0.Type != typ.UInt64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 63 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 63 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64ROR)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (XOR (SRL <typ.UInt64> x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> [cc] (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (ROR x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SRL || v_0.Type != typ.UInt64 {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt64 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 63 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 63 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR (SLL x (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> [cc] (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (RORW x (NEG <t> y))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt32 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL || v_1_0.Type != typ.UInt32 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpARM64MOVWUreg || x != v_1_0_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 31 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 31 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64RORW)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (XOR (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> [cc] (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc == OpARM64LessThanU
+ // result: (RORW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpARM64SRL || v_0.Type != typ.UInt32 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64MOVWUreg {
+ continue
+ }
+ x := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ continue
+ }
+ t := v_0_1.Type
+ if auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpARM64CSEL0 || v_1.Type != typ.UInt32 {
+ continue
+ }
+ cc := auxIntToOp(v_1.AuxInt)
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ continue
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB || v_1_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_0_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst || v_1_0_1_1.Type != t || auxIntToInt64(v_1_0_1_1.AuxInt) != 31 || y != v_1_0_1_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB || v_1_1_0.Type != t {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_1_1_0_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst || v_1_1_0_1.Type != t || auxIntToInt64(v_1_1_0_1.AuxInt) != 31 || y != v_1_1_0_1.Args[0] || !(cc == OpARM64LessThanU) {
+ continue
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64XORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (XORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (XORconst [-1] x)
+ // result: (MVN x)
+ for {
+ if auxIntToInt64(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.reset(OpARM64MVN)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [c^d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c ^ d)
+ return true
+ }
+ // match: (XORconst [c] (XORconst [d] x))
+ // result: (XORconst [c^d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64XORconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(c ^ d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64XORshiftLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (XORshiftLL (MOVDconst [c]) x [d])
+ // result: (XORconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XORshiftLL x (MOVDconst [c]) [d])
+ // result: (XORconst x [int64(uint64(c)<<uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) << uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftLL (SLLconst x [c]) x [c])
+ // result: (MOVDconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (XORshiftLL [c] (SRLconst x [64-c]) x)
+ // result: (RORconst [64-c] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != 64-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64RORconst)
+ v.AuxInt = int64ToAuxInt(64 - c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftLL <t> [c] (UBFX [bfc] x) x)
+ // cond: c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ // result: (RORWconst [32-c] x)
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFX {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ if x != v_1 || !(c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)) {
+ break
+ }
+ v.reset(OpARM64RORWconst)
+ v.AuxInt = int64ToAuxInt(32 - c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftLL <typ.UInt16> [8] (UBFX <typ.UInt16> [armBFAuxInt(8, 8)] x) x)
+ // result: (REV16W x)
+ for {
+ if v.Type != typ.UInt16 || auxIntToInt64(v.AuxInt) != 8 || v_0.Op != OpARM64UBFX || v_0.Type != typ.UInt16 || auxIntToArm64BitField(v_0.AuxInt) != armBFAuxInt(8, 8) {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64REV16W)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftLL [c] (SRLconst x [64-c]) x2)
+ // result: (EXTRconst [64-c] x2 x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != 64-c {
+ break
+ }
+ x := v_0.Args[0]
+ x2 := v_1
+ v.reset(OpARM64EXTRconst)
+ v.AuxInt = int64ToAuxInt(64 - c)
+ v.AddArg2(x2, x)
+ return true
+ }
+ // match: (XORshiftLL <t> [c] (UBFX [bfc] x) x2)
+ // cond: c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
+ // result: (EXTRWconst [32-c] x2 x)
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64UBFX {
+ break
+ }
+ bfc := auxIntToArm64BitField(v_0.AuxInt)
+ x := v_0.Args[0]
+ x2 := v_1
+ if !(c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)) {
+ break
+ }
+ v.reset(OpARM64EXTRWconst)
+ v.AuxInt = int64ToAuxInt(32 - c)
+ v.AddArg2(x2, x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64XORshiftRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORshiftRA (MOVDconst [c]) x [d])
+ // result: (XORconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XORshiftRA x (MOVDconst [c]) [d])
+ // result: (XORconst x [c>>uint64(d)])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(c >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftRA (SRAconst x [c]) x [c])
+ // result: (MOVDconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRAconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64XORshiftRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORshiftRL (MOVDconst [c]) x [d])
+ // result: (XORconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type)
+ v0.AuxInt = int64ToAuxInt(d)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XORshiftRL x (MOVDconst [c]) [d])
+ // result: (XORconst x [int64(uint64(c)>>uint64(d))])
+ for {
+ d := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpARM64XORconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) >> uint64(d)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftRL (SRLconst x [c]) x [c])
+ // result: (MOVDconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (XORshiftRL [c] (SLLconst x [64-c]) x)
+ // result: (RORconst [ c] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 64-c {
+ break
+ }
+ x := v_0.Args[0]
+ if x != v_1 {
+ break
+ }
+ v.reset(OpARM64RORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x))
+ // cond: c < 32 && t.Size() == 4
+ // result: (RORWconst [c] x)
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != 32-c {
+ break
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpARM64MOVWUreg || x != v_1.Args[0] || !(c < 32 && t.Size() == 4) {
+ break
+ }
+ v.reset(OpARM64RORWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Addr {sym} base)
+ // result: (MOVDaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpARM64MOVDaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueARM64_OpAtomicAnd32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicAnd32 ptr val mem)
+ // result: (Select1 (LoweredAtomicAnd32 ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicAnd32, types.NewTuple(typ.UInt32, types.TypeMem))
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpAtomicAnd32Variant(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicAnd32Variant ptr val mem)
+ // result: (Select1 (LoweredAtomicAnd32Variant ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicAnd32Variant, types.NewTuple(typ.UInt32, types.TypeMem))
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpAtomicAnd8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicAnd8 ptr val mem)
+ // result: (Select1 (LoweredAtomicAnd8 ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicAnd8, types.NewTuple(typ.UInt8, types.TypeMem))
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpAtomicAnd8Variant(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicAnd8Variant ptr val mem)
+ // result: (Select1 (LoweredAtomicAnd8Variant ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicAnd8Variant, types.NewTuple(typ.UInt8, types.TypeMem))
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpAtomicOr32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicOr32 ptr val mem)
+ // result: (Select1 (LoweredAtomicOr32 ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicOr32, types.NewTuple(typ.UInt32, types.TypeMem))
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpAtomicOr32Variant(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicOr32Variant ptr val mem)
+ // result: (Select1 (LoweredAtomicOr32Variant ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicOr32Variant, types.NewTuple(typ.UInt32, types.TypeMem))
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpAtomicOr8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicOr8 ptr val mem)
+ // result: (Select1 (LoweredAtomicOr8 ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicOr8, types.NewTuple(typ.UInt8, types.TypeMem))
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpAtomicOr8Variant(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicOr8Variant ptr val mem)
+ // result: (Select1 (LoweredAtomicOr8Variant ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicOr8Variant, types.NewTuple(typ.UInt8, types.TypeMem))
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpAvg64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Avg64u <t> x y)
+ // result: (ADD (SRLconst <t> (SUB <t> x y) [1]) y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64ADD)
+ v0 := b.NewValue0(v.Pos, OpARM64SRLconst, t)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpARM64SUB, t)
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueARM64_OpBitLen32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen32 x)
+ // result: (SUB (MOVDconst [32]) (CLZW <typ.Int> x))
+ for {
+ x := v_0
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(32)
+ v1 := b.NewValue0(v.Pos, OpARM64CLZW, typ.Int)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpBitLen64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen64 x)
+ // result: (SUB (MOVDconst [64]) (CLZ <typ.Int> x))
+ for {
+ x := v_0
+ v.reset(OpARM64SUB)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(64)
+ v1 := b.NewValue0(v.Pos, OpARM64CLZ, typ.Int)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpBitRev16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitRev16 x)
+ // result: (SRLconst [48] (RBIT <typ.UInt64> x))
+ for {
+ x := v_0
+ v.reset(OpARM64SRLconst)
+ v.AuxInt = int64ToAuxInt(48)
+ v0 := b.NewValue0(v.Pos, OpARM64RBIT, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpBitRev8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitRev8 x)
+ // result: (SRLconst [56] (RBIT <typ.UInt64> x))
+ for {
+ x := v_0
+ v.reset(OpARM64SRLconst)
+ v.AuxInt = int64ToAuxInt(56)
+ v0 := b.NewValue0(v.Pos, OpARM64RBIT, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpCondSelect(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CondSelect x y boolval)
+ // cond: flagArg(boolval) != nil
+ // result: (CSEL [boolval.Op] x y flagArg(boolval))
+ for {
+ x := v_0
+ y := v_1
+ boolval := v_2
+ if !(flagArg(boolval) != nil) {
+ break
+ }
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(boolval.Op)
+ v.AddArg3(x, y, flagArg(boolval))
+ return true
+ }
+ // match: (CondSelect x y boolval)
+ // cond: flagArg(boolval) == nil
+ // result: (CSEL [OpARM64NotEqual] x y (CMPWconst [0] boolval))
+ for {
+ x := v_0
+ y := v_1
+ boolval := v_2
+ if !(flagArg(boolval) == nil) {
+ break
+ }
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(boolval)
+ v.AddArg3(x, y, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpConst16(v *Value) bool {
+ // match: (Const16 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt16(v.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueARM64_OpConst32(v *Value) bool {
+ // match: (Const32 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt32(v.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueARM64_OpConst32F(v *Value) bool {
+ // match: (Const32F [val])
+ // result: (FMOVSconst [float64(val)])
+ for {
+ val := auxIntToFloat32(v.AuxInt)
+ v.reset(OpARM64FMOVSconst)
+ v.AuxInt = float64ToAuxInt(float64(val))
+ return true
+ }
+}
+func rewriteValueARM64_OpConst64(v *Value) bool {
+ // match: (Const64 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt64(v.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueARM64_OpConst64F(v *Value) bool {
+ // match: (Const64F [val])
+ // result: (FMOVDconst [float64(val)])
+ for {
+ val := auxIntToFloat64(v.AuxInt)
+ v.reset(OpARM64FMOVDconst)
+ v.AuxInt = float64ToAuxInt(float64(val))
+ return true
+ }
+}
+func rewriteValueARM64_OpConst8(v *Value) bool {
+ // match: (Const8 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt8(v.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueARM64_OpConstBool(v *Value) bool {
+ // match: (ConstBool [b])
+ // result: (MOVDconst [b2i(b)])
+ for {
+ b := auxIntToBool(v.AuxInt)
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(b))
+ return true
+ }
+}
+func rewriteValueARM64_OpConstNil(v *Value) bool {
+ // match: (ConstNil)
+ // result: (MOVDconst [0])
+ for {
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+}
+func rewriteValueARM64_OpCtz16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz16 <t> x)
+ // result: (CLZW <t> (RBITW <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x)))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpARM64CLZW)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpARM64RBITW, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpARM64ORconst, typ.UInt32)
+ v1.AuxInt = int64ToAuxInt(0x10000)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpCtz32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Ctz32 <t> x)
+ // result: (CLZW (RBITW <t> x))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpARM64CLZW)
+ v0 := b.NewValue0(v.Pos, OpARM64RBITW, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpCtz64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Ctz64 <t> x)
+ // result: (CLZ (RBIT <t> x))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpARM64CLZ)
+ v0 := b.NewValue0(v.Pos, OpARM64RBIT, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpCtz8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz8 <t> x)
+ // result: (CLZW <t> (RBITW <typ.UInt32> (ORconst <typ.UInt32> [0x100] x)))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpARM64CLZW)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpARM64RBITW, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpARM64ORconst, typ.UInt32)
+ v1.AuxInt = int64ToAuxInt(0x100)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpDiv16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16 [false] x y)
+ // result: (DIVW (SignExt16to32 x) (SignExt16to32 y))
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpARM64DIVW)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpDiv16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16u x y)
+ // result: (UDIVW (ZeroExt16to32 x) (ZeroExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64UDIVW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpDiv32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Div32 [false] x y)
+ // result: (DIVW x y)
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpARM64DIVW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpDiv64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Div64 [false] x y)
+ // result: (DIV x y)
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpARM64DIV)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 x y)
+ // result: (DIVW (SignExt8to32 x) (SignExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64DIVW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u x y)
+ // result: (UDIVW (ZeroExt8to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64UDIVW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq16 x y)
+ // result: (Equal (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64Equal)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32 x y)
+ // result: (Equal (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64Equal)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpEq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32F x y)
+ // result: (Equal (FCMPS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64Equal)
+ v0 := b.NewValue0(v.Pos, OpARM64FCMPS, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpEq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64 x y)
+ // result: (Equal (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64Equal)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpEq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64F x y)
+ // result: (Equal (FCMPD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64Equal)
+ v0 := b.NewValue0(v.Pos, OpARM64FCMPD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq8 x y)
+ // result: (Equal (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64Equal)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpEqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqB x y)
+ // result: (XOR (MOVDconst [1]) (XOR <typ.Bool> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64XOR)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpARM64XOR, typ.Bool)
+ v1.AddArg2(x, y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpEqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (EqPtr x y)
+ // result: (Equal (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64Equal)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpFMA(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMA x y z)
+ // result: (FMADDD z x y)
+ for {
+ x := v_0
+ y := v_1
+ z := v_2
+ v.reset(OpARM64FMADDD)
+ v.AddArg3(z, x, y)
+ return true
+ }
+}
+func rewriteValueARM64_OpHmul32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul32 x y)
+ // result: (SRAconst (MULL <typ.Int64> x y) [32])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRAconst)
+ v.AuxInt = int64ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpARM64MULL, typ.Int64)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpHmul32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul32u x y)
+ // result: (SRAconst (UMULL <typ.UInt64> x y) [32])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRAconst)
+ v.AuxInt = int64ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpARM64UMULL, typ.UInt64)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpIsInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsInBounds idx len)
+ // result: (LessThanU (CMP idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsNonNil ptr)
+ // result: (NotEqual (CMPconst [0] ptr))
+ for {
+ ptr := v_0
+ v.reset(OpARM64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(0)
+ v0.AddArg(ptr)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpIsSliceInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsSliceInBounds idx len)
+ // result: (LessEqualU (CMP idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpARM64LessEqualU)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16 x y)
+ // result: (LessEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16U x zero:(MOVDconst [0]))
+ // result: (Eq16 x zero)
+ for {
+ x := v_0
+ zero := v_1
+ if zero.Op != OpARM64MOVDconst || auxIntToInt64(zero.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpEq16)
+ v.AddArg2(x, zero)
+ return true
+ }
+ // match: (Leq16U (MOVDconst [1]) x)
+ // result: (Neq16 (MOVDconst [0]) x)
+ for {
+ if v_0.Op != OpARM64MOVDconst || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_1
+ v.reset(OpNeq16)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Leq16U x y)
+ // result: (LessEqualU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessEqualU)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32 x y)
+ // result: (LessEqual (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32F x y)
+ // result: (LessEqualF (FCMPS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessEqualF)
+ v0 := b.NewValue0(v.Pos, OpARM64FCMPS, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32U x zero:(MOVDconst [0]))
+ // result: (Eq32 x zero)
+ for {
+ x := v_0
+ zero := v_1
+ if zero.Op != OpARM64MOVDconst || auxIntToInt64(zero.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpEq32)
+ v.AddArg2(x, zero)
+ return true
+ }
+ // match: (Leq32U (MOVDconst [1]) x)
+ // result: (Neq32 (MOVDconst [0]) x)
+ for {
+ if v_0.Op != OpARM64MOVDconst || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_1
+ v.reset(OpNeq32)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Leq32U x y)
+ // result: (LessEqualU (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessEqualU)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64 x y)
+ // result: (LessEqual (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64F x y)
+ // result: (LessEqualF (FCMPD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessEqualF)
+ v0 := b.NewValue0(v.Pos, OpARM64FCMPD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLeq64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq64U x zero:(MOVDconst [0]))
+ // result: (Eq64 x zero)
+ for {
+ x := v_0
+ zero := v_1
+ if zero.Op != OpARM64MOVDconst || auxIntToInt64(zero.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpEq64)
+ v.AddArg2(x, zero)
+ return true
+ }
+ // match: (Leq64U (MOVDconst [1]) x)
+ // result: (Neq64 (MOVDconst [0]) x)
+ for {
+ if v_0.Op != OpARM64MOVDconst || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_1
+ v.reset(OpNeq64)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Leq64U x y)
+ // result: (LessEqualU (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessEqualU)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8 x y)
+ // result: (LessEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8U x zero:(MOVDconst [0]))
+ // result: (Eq8 x zero)
+ for {
+ x := v_0
+ zero := v_1
+ if zero.Op != OpARM64MOVDconst || auxIntToInt64(zero.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpEq8)
+ v.AddArg2(x, zero)
+ return true
+ }
+ // match: (Leq8U (MOVDconst [1]) x)
+ // result: (Neq8 (MOVDconst [0]) x)
+ for {
+ if v_0.Op != OpARM64MOVDconst || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_1
+ v.reset(OpNeq8)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Leq8U x y)
+ // result: (LessEqualU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessEqualU)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16 x y)
+ // result: (LessThan (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessThan)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16U zero:(MOVDconst [0]) x)
+ // result: (Neq16 zero x)
+ for {
+ zero := v_0
+ if zero.Op != OpARM64MOVDconst || auxIntToInt64(zero.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpNeq16)
+ v.AddArg2(zero, x)
+ return true
+ }
+ // match: (Less16U x (MOVDconst [1]))
+ // result: (Eq16 x (MOVDconst [0]))
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpEq16)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Less16U x y)
+ // result: (LessThanU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32 x y)
+ // result: (LessThan (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessThan)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLess32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32F x y)
+ // result: (LessThanF (FCMPS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessThanF)
+ v0 := b.NewValue0(v.Pos, OpARM64FCMPS, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less32U zero:(MOVDconst [0]) x)
+ // result: (Neq32 zero x)
+ for {
+ zero := v_0
+ if zero.Op != OpARM64MOVDconst || auxIntToInt64(zero.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpNeq32)
+ v.AddArg2(zero, x)
+ return true
+ }
+ // match: (Less32U x (MOVDconst [1]))
+ // result: (Eq32 x (MOVDconst [0]))
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpEq32)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Less32U x y)
+ // result: (LessThanU (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLess64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64 x y)
+ // result: (LessThan (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessThan)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLess64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64F x y)
+ // result: (LessThanF (FCMPD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessThanF)
+ v0 := b.NewValue0(v.Pos, OpARM64FCMPD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLess64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less64U zero:(MOVDconst [0]) x)
+ // result: (Neq64 zero x)
+ for {
+ zero := v_0
+ if zero.Op != OpARM64MOVDconst || auxIntToInt64(zero.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpNeq64)
+ v.AddArg2(zero, x)
+ return true
+ }
+ // match: (Less64U x (MOVDconst [1]))
+ // result: (Eq64 x (MOVDconst [0]))
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpEq64)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Less64U x y)
+ // result: (LessThanU (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8 x y)
+ // result: (LessThan (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessThan)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8U zero:(MOVDconst [0]) x)
+ // result: (Neq8 zero x)
+ for {
+ zero := v_0
+ if zero.Op != OpARM64MOVDconst || auxIntToInt64(zero.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpNeq8)
+ v.AddArg2(zero, x)
+ return true
+ }
+ // match: (Less8U x (MOVDconst [1]))
+ // result: (Eq8 x (MOVDconst [0]))
+ for {
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpEq8)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Less8U x y)
+ // result: (LessThanU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Load <t> ptr mem)
+ // cond: t.IsBoolean()
+ // result: (MOVBUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsBoolean()) {
+ break
+ }
+ v.reset(OpARM64MOVBUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is8BitInt(t) && isSigned(t))
+ // result: (MOVBload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpARM64MOVBload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is8BitInt(t) && !isSigned(t))
+ // result: (MOVBUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpARM64MOVBUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is16BitInt(t) && isSigned(t))
+ // result: (MOVHload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpARM64MOVHload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is16BitInt(t) && !isSigned(t))
+ // result: (MOVHUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpARM64MOVHUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is32BitInt(t) && isSigned(t))
+ // result: (MOVWload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpARM64MOVWload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is32BitInt(t) && !isSigned(t))
+ // result: (MOVWUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpARM64MOVWUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (MOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpARM64MOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitFloat(t)
+ // result: (FMOVSload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(OpARM64FMOVSload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitFloat(t)
+ // result: (FMOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(OpARM64FMOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpLocalAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LocalAddr {sym} base _)
+ // result: (MOVDaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpARM64MOVDaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x16 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x32 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x64 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpConst64, t)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x8 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x16 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x32 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x64 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpConst64, t)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x8 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x16 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x32 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh64x64 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpConst64, t)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x8 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x16 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x32 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x64 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpConst64, t)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueARM64_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x8 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpMod16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16 x y)
+ // result: (MODW (SignExt16to32 x) (SignExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64MODW)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpMod16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16u x y)
+ // result: (UMODW (ZeroExt16to32 x) (ZeroExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64UMODW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpMod32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Mod32 x y)
+ // result: (MODW x y)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64MODW)
+ v.AddArg2(x, y)
+ return true
+ }
+}
+func rewriteValueARM64_OpMod64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Mod64 x y)
+ // result: (MOD x y)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64MOD)
+ v.AddArg2(x, y)
+ return true
+ }
+}
+func rewriteValueARM64_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8 x y)
+ // result: (MODW (SignExt8to32 x) (SignExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64MODW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8u x y)
+ // result: (UMODW (ZeroExt8to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64UMODW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Move [0] _ _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Move [1] dst src mem)
+ // result: (MOVBstore dst (MOVBUload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVBstore)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVBUload, typ.UInt8)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] dst src mem)
+ // result: (MOVHstore dst (MOVHUload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVHstore)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVHUload, typ.UInt16)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [4] dst src mem)
+ // result: (MOVWstore dst (MOVWUload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVWstore)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVWUload, typ.UInt32)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [8] dst src mem)
+ // result: (MOVDstore dst (MOVDload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVDstore)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [3] dst src mem)
+ // result: (MOVBstore [2] dst (MOVBUload [2] src mem) (MOVHstore dst (MOVHUload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVBUload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVHstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVHUload, typ.UInt16)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [5] dst src mem)
+ // result: (MOVBstore [4] dst (MOVBUload [4] src mem) (MOVWstore dst (MOVWUload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVBUload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVWUload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [6] dst src mem)
+ // result: (MOVHstore [4] dst (MOVHUload [4] src mem) (MOVWstore dst (MOVWUload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVHUload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVWUload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [7] dst src mem)
+ // result: (MOVBstore [6] dst (MOVBUload [6] src mem) (MOVHstore [4] dst (MOVHUload [4] src mem) (MOVWstore dst (MOVWUload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVBUload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(6)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVHUload, typ.UInt16)
+ v2.AuxInt = int32ToAuxInt(4)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpARM64MOVWstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpARM64MOVWUload, typ.UInt32)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [12] dst src mem)
+ // result: (MOVWstore [8] dst (MOVWUload [8] src mem) (MOVDstore dst (MOVDload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVWUload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [16] dst src mem)
+ // result: (MOVDstore [8] dst (MOVDload [8] src mem) (MOVDstore dst (MOVDload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [24] dst src mem)
+ // result: (MOVDstore [16] dst (MOVDload [16] src mem) (MOVDstore [8] dst (MOVDload [8] src mem) (MOVDstore dst (MOVDload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(16)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64)
+ v2.AuxInt = int32ToAuxInt(8)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s%8 != 0 && s > 8
+ // result: (Move [s%8] (OffPtr <dst.Type> dst [s-s%8]) (OffPtr <src.Type> src [s-s%8]) (Move [s-s%8] dst src mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s%8 != 0 && s > 8) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(s % 8)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
+ v0.AuxInt = int64ToAuxInt(s - s%8)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
+ v1.AuxInt = int64ToAuxInt(s - s%8)
+ v1.AddArg(src)
+ v2 := b.NewValue0(v.Pos, OpMove, types.TypeMem)
+ v2.AuxInt = int64ToAuxInt(s - s%8)
+ v2.AddArg3(dst, src, mem)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 32 && s <= 16*64 && s%16 == 8 && !config.noDuffDevice && logLargeCopy(v, s)
+ // result: (MOVDstore [int32(s-8)] dst (MOVDload [int32(s-8)] src mem) (DUFFCOPY <types.TypeMem> [8*(64-(s-8)/16)] dst src mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 32 && s <= 16*64 && s%16 == 8 && !config.noDuffDevice && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpARM64MOVDstore)
+ v.AuxInt = int32ToAuxInt(int32(s - 8))
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(int32(s - 8))
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpARM64DUFFCOPY, types.TypeMem)
+ v1.AuxInt = int64ToAuxInt(8 * (64 - (s-8)/16))
+ v1.AddArg3(dst, src, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 32 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
+ // result: (DUFFCOPY [8 * (64 - s/16)] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 32 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpARM64DUFFCOPY)
+ v.AuxInt = int64ToAuxInt(8 * (64 - s/16))
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 24 && s%8 == 0 && logLargeCopy(v, s)
+ // result: (LoweredMove dst src (ADDconst <src.Type> src [s-8]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 24 && s%8 == 0 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpARM64LoweredMove)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDconst, src.Type)
+ v0.AuxInt = int64ToAuxInt(s - 8)
+ v0.AddArg(src)
+ v.AddArg4(dst, src, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq16 x y)
+ // result: (NotEqual (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32 x y)
+ // result: (NotEqual (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpNeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32F x y)
+ // result: (NotEqual (FCMPS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64FCMPS, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpNeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64 x y)
+ // result: (NotEqual (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpNeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64F x y)
+ // result: (NotEqual (FCMPD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64FCMPD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq8 x y)
+ // result: (NotEqual (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpNeqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (NeqPtr x y)
+ // result: (NotEqual (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpNot(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Not x)
+ // result: (XOR (MOVDconst [1]) x)
+ for {
+ x := v_0
+ v.reset(OpARM64XOR)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueARM64_OpOffPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (OffPtr [off] ptr:(SP))
+ // cond: is32Bit(off)
+ // result: (MOVDaddr [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ if ptr.Op != OpSP || !(is32Bit(off)) {
+ break
+ }
+ v.reset(OpARM64MOVDaddr)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (OffPtr [off] ptr)
+ // result: (ADDconst [off] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64ToAuxInt(off)
+ v.AddArg(ptr)
+ return true
+ }
+}
+func rewriteValueARM64_OpPanicBounds(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicBoundsA [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(OpARM64LoweredPanicBoundsA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicBoundsB [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(OpARM64LoweredPanicBoundsB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicBoundsC [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(OpARM64LoweredPanicBoundsC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpPopCount16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount16 <t> x)
+ // result: (FMOVDfpgp <t> (VUADDLV <typ.Float64> (VCNT <typ.Float64> (FMOVDgpfp <typ.Float64> (ZeroExt16to64 x)))))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpARM64FMOVDfpgp)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpARM64VUADDLV, typ.Float64)
+ v1 := b.NewValue0(v.Pos, OpARM64VCNT, typ.Float64)
+ v2 := b.NewValue0(v.Pos, OpARM64FMOVDgpfp, typ.Float64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(x)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpPopCount32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount32 <t> x)
+ // result: (FMOVDfpgp <t> (VUADDLV <typ.Float64> (VCNT <typ.Float64> (FMOVDgpfp <typ.Float64> (ZeroExt32to64 x)))))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpARM64FMOVDfpgp)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpARM64VUADDLV, typ.Float64)
+ v1 := b.NewValue0(v.Pos, OpARM64VCNT, typ.Float64)
+ v2 := b.NewValue0(v.Pos, OpARM64FMOVDgpfp, typ.Float64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(x)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpPopCount64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount64 <t> x)
+ // result: (FMOVDfpgp <t> (VUADDLV <typ.Float64> (VCNT <typ.Float64> (FMOVDgpfp <typ.Float64> x))))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpARM64FMOVDfpgp)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpARM64VUADDLV, typ.Float64)
+ v1 := b.NewValue0(v.Pos, OpARM64VCNT, typ.Float64)
+ v2 := b.NewValue0(v.Pos, OpARM64FMOVDgpfp, typ.Float64)
+ v2.AddArg(x)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpRotateLeft16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft16 <t> x (MOVDconst [c]))
+ // result: (Or16 (Lsh16x64 <t> x (MOVDconst [c&15])) (Rsh16Ux64 <t> x (MOVDconst [-c&15])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpLsh16x64, t)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c & 15)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh16Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(-c & 15)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpRotateLeft32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RotateLeft32 x y)
+ // result: (RORW x (NEG <y.Type> y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64RORW)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, y.Type)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpRotateLeft64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RotateLeft64 x y)
+ // result: (ROR x (NEG <y.Type> y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64ROR)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, y.Type)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpRotateLeft8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft8 <t> x (MOVDconst [c]))
+ // result: (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpLsh8x64, t)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c & 7)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh8Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(-c & 7)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux16 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt16to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst64, t)
+ v3.AuxInt = int64ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux32 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt16to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst64, t)
+ v3.AuxInt = int64ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux64 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt16to64 x) y) (Const64 <t> [0]) (CMPconst [64] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux8 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt16to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst64, t)
+ v3.AuxInt = int64ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x16 x y)
+ // result: (SRA (SignExt16to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v3.AuxInt = int64ToAuxInt(63)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x32 x y)
+ // result: (SRA (SignExt16to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v3.AuxInt = int64ToAuxInt(63)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x64 x y)
+ // result: (SRA (SignExt16to64 x) (CSEL [OpARM64LessThanU] <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x8 x y)
+ // result: (SRA (SignExt16to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v3.AuxInt = int64ToAuxInt(63)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux16 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt32to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst64, t)
+ v3.AuxInt = int64ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux32 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt32to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst64, t)
+ v3.AuxInt = int64ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux64 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt32to64 x) y) (Const64 <t> [0]) (CMPconst [64] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux8 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt32to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst64, t)
+ v3.AuxInt = int64ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x16 x y)
+ // result: (SRA (SignExt32to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v3.AuxInt = int64ToAuxInt(63)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x32 x y)
+ // result: (SRA (SignExt32to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v3.AuxInt = int64ToAuxInt(63)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x64 x y)
+ // result: (SRA (SignExt32to64 x) (CSEL [OpARM64LessThanU] <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x8 x y)
+ // result: (SRA (SignExt32to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v3.AuxInt = int64ToAuxInt(63)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh64Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux16 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh64Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux32 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh64Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64Ux64 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpConst64, t)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh64Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux8 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x16 x y)
+ // result: (SRA x (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v0.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v2 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v0.AddArg3(v1, v2, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x32 x y)
+ // result: (SRA x (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v0.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v2 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v0.AddArg3(v1, v2, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x64 x y)
+ // result: (SRA x (CSEL [OpARM64LessThanU] <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v0.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v1 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v1.AuxInt = int64ToAuxInt(63)
+ v2 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x8 x y)
+ // result: (SRA x (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v0.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v2 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(v1)
+ v0.AddArg3(v1, v2, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux16 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt8to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst64, t)
+ v3.AuxInt = int64ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux32 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt8to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst64, t)
+ v3.AuxInt = int64ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux64 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt8to64 x) y) (Const64 <t> [0]) (CMPconst [64] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux8 <t> x y)
+ // result: (CSEL [OpARM64LessThanU] (SRL <t> (ZeroExt8to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpARM64CSEL)
+ v.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v0 := b.NewValue0(v.Pos, OpARM64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst64, t)
+ v3.AuxInt = int64ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x16 x y)
+ // result: (SRA (SignExt8to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v3.AuxInt = int64ToAuxInt(63)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x32 x y)
+ // result: (SRA (SignExt8to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v3.AuxInt = int64ToAuxInt(63)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x64 x y)
+ // result: (SRA (SignExt8to64 x) (CSEL [OpARM64LessThanU] <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x8 x y)
+ // result: (SRA (SignExt8to64 x) (CSEL [OpARM64LessThanU] <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpARM64SRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpARM64CSEL, y.Type)
+ v1.AuxInt = opToAuxInt(OpARM64LessThanU)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpConst64, y.Type)
+ v3.AuxInt = int64ToAuxInt(63)
+ v4 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags)
+ v4.AuxInt = int64ToAuxInt(64)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueARM64_OpSelect0(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select0 (Add64carry x y c))
+ // result: (Select0 <typ.UInt64> (ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] c))))
+ for {
+ if v_0.Op != OpAdd64carry {
+ break
+ }
+ c := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpSelect0)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpARM64ADCSflags, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v2 := b.NewValue0(v.Pos, OpARM64ADDSconstflags, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v2.AuxInt = int64ToAuxInt(-1)
+ v2.AddArg(c)
+ v1.AddArg(v2)
+ v0.AddArg3(x, y, v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select0 (Sub64borrow x y bo))
+ // result: (Select0 <typ.UInt64> (SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags bo))))
+ for {
+ if v_0.Op != OpSub64borrow {
+ break
+ }
+ bo := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpSelect0)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpARM64SBCSflags, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v2 := b.NewValue0(v.Pos, OpARM64NEGSflags, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v2.AddArg(bo)
+ v1.AddArg(v2)
+ v0.AddArg3(x, y, v1)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpSelect1(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select1 (Add64carry x y c))
+ // result: (ADCzerocarry <typ.UInt64> (Select1 <types.TypeFlags> (ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] c)))))
+ for {
+ if v_0.Op != OpAdd64carry {
+ break
+ }
+ c := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpARM64ADCzerocarry)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpARM64ADCSflags, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v2 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpARM64ADDSconstflags, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v3.AuxInt = int64ToAuxInt(-1)
+ v3.AddArg(c)
+ v2.AddArg(v3)
+ v1.AddArg3(x, y, v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select1 (Sub64borrow x y bo))
+ // result: (NEG <typ.UInt64> (NGCzerocarry <typ.UInt64> (Select1 <types.TypeFlags> (SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags bo))))))
+ for {
+ if v_0.Op != OpSub64borrow {
+ break
+ }
+ bo := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpARM64NEG)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpARM64NGCzerocarry, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v2 := b.NewValue0(v.Pos, OpARM64SBCSflags, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v3 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpARM64NEGSflags, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v4.AddArg(bo)
+ v3.AddArg(v4)
+ v2.AddArg3(x, y, v3)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Slicemask <t> x)
+ // result: (SRAconst (NEG <t> x) [63])
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpARM64SRAconst)
+ v.AuxInt = int64ToAuxInt(63)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 1
+ // result: (MOVBstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 1) {
+ break
+ }
+ v.reset(OpARM64MOVBstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 2
+ // result: (MOVHstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 2) {
+ break
+ }
+ v.reset(OpARM64MOVHstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && !is32BitFloat(val.Type)
+ // result: (MOVWstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && !is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpARM64MOVWstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && !is64BitFloat(val.Type)
+ // result: (MOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && !is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpARM64MOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && is32BitFloat(val.Type)
+ // result: (FMOVSstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpARM64FMOVSstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && is64BitFloat(val.Type)
+ // result: (FMOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpARM64FMOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Zero [0] _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_1
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero [1] ptr mem)
+ // result: (MOVBstore ptr (MOVDconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVBstore)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [2] ptr mem)
+ // result: (MOVHstore ptr (MOVDconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVHstore)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [4] ptr mem)
+ // result: (MOVWstore ptr (MOVDconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVWstore)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [8] ptr mem)
+ // result: (MOVDstore ptr (MOVDconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVDstore)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [3] ptr mem)
+ // result: (MOVBstore [2] ptr (MOVDconst [0]) (MOVHstore ptr (MOVDconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVHstore, types.TypeMem)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [5] ptr mem)
+ // result: (MOVBstore [4] ptr (MOVDconst [0]) (MOVWstore ptr (MOVDconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVWstore, types.TypeMem)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [6] ptr mem)
+ // result: (MOVHstore [4] ptr (MOVDconst [0]) (MOVWstore ptr (MOVDconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVWstore, types.TypeMem)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [7] ptr mem)
+ // result: (MOVBstore [6] ptr (MOVDconst [0]) (MOVHstore [4] ptr (MOVDconst [0]) (MOVWstore ptr (MOVDconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVWstore, types.TypeMem)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [9] ptr mem)
+ // result: (MOVBstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 9 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [10] ptr mem)
+ // result: (MOVHstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 10 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [11] ptr mem)
+ // result: (MOVBstore [10] ptr (MOVDconst [0]) (MOVHstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 11 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(10)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [12] ptr mem)
+ // result: (MOVWstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [13] ptr mem)
+ // result: (MOVBstore [12] ptr (MOVDconst [0]) (MOVWstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 13 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(12)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [14] ptr mem)
+ // result: (MOVHstore [12] ptr (MOVDconst [0]) (MOVWstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 14 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVHstore)
+ v.AuxInt = int32ToAuxInt(12)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [15] ptr mem)
+ // result: (MOVBstore [14] ptr (MOVDconst [0]) (MOVHstore [12] ptr (MOVDconst [0]) (MOVWstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 15 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64MOVBstore)
+ v.AuxInt = int32ToAuxInt(14)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(12)
+ v2 := b.NewValue0(v.Pos, OpARM64MOVWstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(8)
+ v3 := b.NewValue0(v.Pos, OpARM64MOVDstore, types.TypeMem)
+ v3.AddArg3(ptr, v0, mem)
+ v2.AddArg3(ptr, v0, v3)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [16] ptr mem)
+ // result: (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64STP)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg4(ptr, v0, v0, mem)
+ return true
+ }
+ // match: (Zero [32] ptr mem)
+ // result: (STP [16] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 32 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64STP)
+ v.AuxInt = int32ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg4(ptr, v0, v0, mem)
+ v.AddArg4(ptr, v0, v0, v1)
+ return true
+ }
+ // match: (Zero [48] ptr mem)
+ // result: (STP [32] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [16] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 48 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64STP)
+ v.AuxInt = int32ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(16)
+ v2 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg4(ptr, v0, v0, mem)
+ v1.AddArg4(ptr, v0, v0, v2)
+ v.AddArg4(ptr, v0, v0, v1)
+ return true
+ }
+ // match: (Zero [64] ptr mem)
+ // result: (STP [48] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [32] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [16] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 64 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpARM64STP)
+ v.AuxInt = int32ToAuxInt(48)
+ v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(32)
+ v2 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(16)
+ v3 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(0)
+ v3.AddArg4(ptr, v0, v0, mem)
+ v2.AddArg4(ptr, v0, v0, v3)
+ v1.AddArg4(ptr, v0, v0, v2)
+ v.AddArg4(ptr, v0, v0, v1)
+ return true
+ }
+ // match: (Zero [s] ptr mem)
+ // cond: s%16 != 0 && s%16 <= 8 && s > 16
+ // result: (Zero [8] (OffPtr <ptr.Type> ptr [s-8]) (Zero [s-s%16] ptr mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ mem := v_1
+ if !(s%16 != 0 && s%16 <= 8 && s > 16) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, ptr.Type)
+ v0.AuxInt = int64ToAuxInt(s - 8)
+ v0.AddArg(ptr)
+ v1 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
+ v1.AuxInt = int64ToAuxInt(s - s%16)
+ v1.AddArg2(ptr, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Zero [s] ptr mem)
+ // cond: s%16 != 0 && s%16 > 8 && s > 16
+ // result: (Zero [16] (OffPtr <ptr.Type> ptr [s-16]) (Zero [s-s%16] ptr mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ mem := v_1
+ if !(s%16 != 0 && s%16 > 8 && s > 16) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, ptr.Type)
+ v0.AuxInt = int64ToAuxInt(s - 16)
+ v0.AddArg(ptr)
+ v1 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
+ v1.AuxInt = int64ToAuxInt(s - s%16)
+ v1.AddArg2(ptr, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Zero [s] ptr mem)
+ // cond: s%16 == 0 && s > 64 && s <= 16*64 && !config.noDuffDevice
+ // result: (DUFFZERO [4 * (64 - s/16)] ptr mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ mem := v_1
+ if !(s%16 == 0 && s > 64 && s <= 16*64 && !config.noDuffDevice) {
+ break
+ }
+ v.reset(OpARM64DUFFZERO)
+ v.AuxInt = int64ToAuxInt(4 * (64 - s/16))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Zero [s] ptr mem)
+ // cond: s%16 == 0 && (s > 16*64 || config.noDuffDevice)
+ // result: (LoweredZero ptr (ADDconst <ptr.Type> [s-16] ptr) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ mem := v_1
+ if !(s%16 == 0 && (s > 16*64 || config.noDuffDevice)) {
+ break
+ }
+ v.reset(OpARM64LoweredZero)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDconst, ptr.Type)
+ v0.AuxInt = int64ToAuxInt(s - 16)
+ v0.AddArg(ptr)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteBlockARM64(b *Block) bool {
+ switch b.Kind {
+ case BlockARM64EQ:
+ // match: (EQ (CMPWconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (EQ (TSTWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (TST x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (CMPWconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (TSTW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (CMPconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (EQ (TSTconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (EQ (CMNconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (EQ (CMNWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (CMP x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPW {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] x) yes no)
+ // result: (Z x yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockARM64Z, x)
+ return true
+ }
+ // match: (EQ (CMPWconst [0] x) yes no)
+ // result: (ZW x yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockARM64ZW, x)
+ return true
+ }
+ // match: (EQ (CMPconst [0] z:(MADD a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (EQ (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADD {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] z:(MSUB a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (EQ (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUB {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPWconst [0] z:(MADDW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (EQ (CMNW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADDW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPWconst [0] z:(MSUBW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (EQ (CMPW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUBW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (TSTconst [c] x) yes no)
+ // cond: oneBit(c)
+ // result: (TBZ [int64(ntz64(c))] x yes no)
+ for b.Controls[0].Op == OpARM64TSTconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(oneBit(c)) {
+ break
+ }
+ b.resetWithControl(BlockARM64TBZ, x)
+ b.AuxInt = int64ToAuxInt(int64(ntz64(c)))
+ return true
+ }
+ // match: (EQ (TSTWconst [c] x) yes no)
+ // cond: oneBit(int64(uint32(c)))
+ // result: (TBZ [int64(ntz64(int64(uint32(c))))] x yes no)
+ for b.Controls[0].Op == OpARM64TSTWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(oneBit(int64(uint32(c)))) {
+ break
+ }
+ b.resetWithControl(BlockARM64TBZ, x)
+ b.AuxInt = int64ToAuxInt(int64(ntz64(int64(uint32(c)))))
+ return true
+ }
+ // match: (EQ (FlagConstant [fc]) yes no)
+ // cond: fc.eq()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.eq()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (EQ (FlagConstant [fc]) yes no)
+ // cond: !fc.eq()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.eq()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (EQ (InvertFlags cmp) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64EQ, cmp)
+ return true
+ }
+ case BlockARM64FGE:
+ // match: (FGE (InvertFlags cmp) yes no)
+ // result: (FLE cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64FLE, cmp)
+ return true
+ }
+ case BlockARM64FGT:
+ // match: (FGT (InvertFlags cmp) yes no)
+ // result: (FLT cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64FLT, cmp)
+ return true
+ }
+ case BlockARM64FLE:
+ // match: (FLE (InvertFlags cmp) yes no)
+ // result: (FGE cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64FGE, cmp)
+ return true
+ }
+ case BlockARM64FLT:
+ // match: (FLT (InvertFlags cmp) yes no)
+ // result: (FGT cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64FGT, cmp)
+ return true
+ }
+ case BlockARM64GE:
+ // match: (GE (CMPWconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GE (TSTWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64GE, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (TST x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GE, v0)
+ return true
+ }
+ break
+ }
+ // match: (GE (CMPWconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (TSTW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GE, v0)
+ return true
+ }
+ break
+ }
+ // match: (GE (CMPconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GE (TSTconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64GE, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GEnoov (CMNconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64GEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GEnoov (CMNWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64GEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GEnoov (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GEnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (GE (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GEnoov (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GEnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (GE (CMP x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GE, v0)
+ return true
+ }
+ // match: (GE (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPW {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GE, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] z:(MADD a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (GEnoov (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADD {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64GEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] z:(MSUB a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (GEnoov (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUB {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64GEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPWconst [0] z:(MADDW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (GEnoov (CMNW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADDW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64GEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPWconst [0] z:(MSUBW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (GEnoov (CMPW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUBW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64GEnoov, v0)
+ return true
+ }
+ // match: (GE (CMPWconst [0] x) yes no)
+ // result: (TBZ [31] x yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockARM64TBZ, x)
+ b.AuxInt = int64ToAuxInt(31)
+ return true
+ }
+ // match: (GE (CMPconst [0] x) yes no)
+ // result: (TBZ [63] x yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockARM64TBZ, x)
+ b.AuxInt = int64ToAuxInt(63)
+ return true
+ }
+ // match: (GE (FlagConstant [fc]) yes no)
+ // cond: fc.ge()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ge()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GE (FlagConstant [fc]) yes no)
+ // cond: !fc.ge()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ge()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GE (InvertFlags cmp) yes no)
+ // result: (LE cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64LE, cmp)
+ return true
+ }
+ case BlockARM64GEnoov:
+ // match: (GEnoov (FlagConstant [fc]) yes no)
+ // cond: fc.geNoov()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.geNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GEnoov (FlagConstant [fc]) yes no)
+ // cond: !fc.geNoov()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.geNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GEnoov (InvertFlags cmp) yes no)
+ // result: (LEnoov cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64LEnoov, cmp)
+ return true
+ }
+ case BlockARM64GT:
+ // match: (GT (CMPWconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GT (TSTWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64GT, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (TST x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GT, v0)
+ return true
+ }
+ break
+ }
+ // match: (GT (CMPWconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (TSTW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GT, v0)
+ return true
+ }
+ break
+ }
+ // match: (GT (CMPconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GT (TSTconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64GT, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GTnoov (CMNconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64GTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GTnoov (CMNWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64GTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GTnoov (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GTnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (GT (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GTnoov (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GTnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (GT (CMP x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GT, v0)
+ return true
+ }
+ // match: (GT (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPW {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64GT, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] z:(MADD a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (GTnoov (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADD {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64GTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] z:(MSUB a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (GTnoov (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUB {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64GTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPWconst [0] z:(MADDW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (GTnoov (CMNW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADDW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64GTnoov, v0)
+ return true
+ }
+ // match: (GT (CMPWconst [0] z:(MSUBW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (GTnoov (CMPW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUBW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64GTnoov, v0)
+ return true
+ }
+ // match: (GT (FlagConstant [fc]) yes no)
+ // cond: fc.gt()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.gt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GT (FlagConstant [fc]) yes no)
+ // cond: !fc.gt()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.gt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GT (InvertFlags cmp) yes no)
+ // result: (LT cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64LT, cmp)
+ return true
+ }
+ case BlockARM64GTnoov:
+ // match: (GTnoov (FlagConstant [fc]) yes no)
+ // cond: fc.gtNoov()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.gtNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GTnoov (FlagConstant [fc]) yes no)
+ // cond: !fc.gtNoov()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.gtNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GTnoov (InvertFlags cmp) yes no)
+ // result: (LTnoov cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64LTnoov, cmp)
+ return true
+ }
+ case BlockIf:
+ // match: (If (Equal cc) yes no)
+ // result: (EQ cc yes no)
+ for b.Controls[0].Op == OpARM64Equal {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64EQ, cc)
+ return true
+ }
+ // match: (If (NotEqual cc) yes no)
+ // result: (NE cc yes no)
+ for b.Controls[0].Op == OpARM64NotEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64NE, cc)
+ return true
+ }
+ // match: (If (LessThan cc) yes no)
+ // result: (LT cc yes no)
+ for b.Controls[0].Op == OpARM64LessThan {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64LT, cc)
+ return true
+ }
+ // match: (If (LessThanU cc) yes no)
+ // result: (ULT cc yes no)
+ for b.Controls[0].Op == OpARM64LessThanU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64ULT, cc)
+ return true
+ }
+ // match: (If (LessEqual cc) yes no)
+ // result: (LE cc yes no)
+ for b.Controls[0].Op == OpARM64LessEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64LE, cc)
+ return true
+ }
+ // match: (If (LessEqualU cc) yes no)
+ // result: (ULE cc yes no)
+ for b.Controls[0].Op == OpARM64LessEqualU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64ULE, cc)
+ return true
+ }
+ // match: (If (GreaterThan cc) yes no)
+ // result: (GT cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterThan {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64GT, cc)
+ return true
+ }
+ // match: (If (GreaterThanU cc) yes no)
+ // result: (UGT cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterThanU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64UGT, cc)
+ return true
+ }
+ // match: (If (GreaterEqual cc) yes no)
+ // result: (GE cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64GE, cc)
+ return true
+ }
+ // match: (If (GreaterEqualU cc) yes no)
+ // result: (UGE cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterEqualU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64UGE, cc)
+ return true
+ }
+ // match: (If (LessThanF cc) yes no)
+ // result: (FLT cc yes no)
+ for b.Controls[0].Op == OpARM64LessThanF {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64FLT, cc)
+ return true
+ }
+ // match: (If (LessEqualF cc) yes no)
+ // result: (FLE cc yes no)
+ for b.Controls[0].Op == OpARM64LessEqualF {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64FLE, cc)
+ return true
+ }
+ // match: (If (GreaterThanF cc) yes no)
+ // result: (FGT cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterThanF {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64FGT, cc)
+ return true
+ }
+ // match: (If (GreaterEqualF cc) yes no)
+ // result: (FGE cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterEqualF {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64FGE, cc)
+ return true
+ }
+ // match: (If cond yes no)
+ // result: (NZ cond yes no)
+ for {
+ cond := b.Controls[0]
+ b.resetWithControl(BlockARM64NZ, cond)
+ return true
+ }
+ case BlockARM64LE:
+ // match: (LE (CMPWconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LE (TSTWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64LE, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (TST x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LE, v0)
+ return true
+ }
+ break
+ }
+ // match: (LE (CMPWconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (TSTW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LE, v0)
+ return true
+ }
+ break
+ }
+ // match: (LE (CMPconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LE (TSTconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64LE, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LEnoov (CMNconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64LEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LEnoov (CMNWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64LEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LEnoov (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LEnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (LE (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LEnoov (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LEnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (LE (CMP x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LE, v0)
+ return true
+ }
+ // match: (LE (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPW {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LE, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] z:(MADD a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (LEnoov (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADD {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64LEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] z:(MSUB a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (LEnoov (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUB {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64LEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPWconst [0] z:(MADDW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (LEnoov (CMNW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADDW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64LEnoov, v0)
+ return true
+ }
+ // match: (LE (CMPWconst [0] z:(MSUBW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (LEnoov (CMPW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUBW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64LEnoov, v0)
+ return true
+ }
+ // match: (LE (FlagConstant [fc]) yes no)
+ // cond: fc.le()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.le()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LE (FlagConstant [fc]) yes no)
+ // cond: !fc.le()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.le()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LE (InvertFlags cmp) yes no)
+ // result: (GE cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64GE, cmp)
+ return true
+ }
+ case BlockARM64LEnoov:
+ // match: (LEnoov (FlagConstant [fc]) yes no)
+ // cond: fc.leNoov()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.leNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LEnoov (FlagConstant [fc]) yes no)
+ // cond: !fc.leNoov()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.leNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LEnoov (InvertFlags cmp) yes no)
+ // result: (GEnoov cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64GEnoov, cmp)
+ return true
+ }
+ case BlockARM64LT:
+ // match: (LT (CMPWconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LT (TSTWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64LT, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (TST x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LT, v0)
+ return true
+ }
+ break
+ }
+ // match: (LT (CMPWconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (TSTW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LT, v0)
+ return true
+ }
+ break
+ }
+ // match: (LT (CMPconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LT (TSTconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64LT, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LTnoov (CMNconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64LTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LTnoov (CMNWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64LTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LTnoov (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LTnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (LT (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LTnoov (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LTnoov, v0)
+ return true
+ }
+ break
+ }
+ // match: (LT (CMP x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LT, v0)
+ return true
+ }
+ // match: (LT (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPW {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64LT, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] z:(MADD a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (LTnoov (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADD {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64LTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] z:(MSUB a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (LTnoov (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUB {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64LTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPWconst [0] z:(MADDW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (LTnoov (CMNW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADDW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64LTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPWconst [0] z:(MSUBW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (LTnoov (CMPW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUBW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64LTnoov, v0)
+ return true
+ }
+ // match: (LT (CMPWconst [0] x) yes no)
+ // result: (TBNZ [31] x yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockARM64TBNZ, x)
+ b.AuxInt = int64ToAuxInt(31)
+ return true
+ }
+ // match: (LT (CMPconst [0] x) yes no)
+ // result: (TBNZ [63] x yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockARM64TBNZ, x)
+ b.AuxInt = int64ToAuxInt(63)
+ return true
+ }
+ // match: (LT (FlagConstant [fc]) yes no)
+ // cond: fc.lt()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.lt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LT (FlagConstant [fc]) yes no)
+ // cond: !fc.lt()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.lt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LT (InvertFlags cmp) yes no)
+ // result: (GT cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64GT, cmp)
+ return true
+ }
+ case BlockARM64LTnoov:
+ // match: (LTnoov (FlagConstant [fc]) yes no)
+ // cond: fc.ltNoov()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ltNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LTnoov (FlagConstant [fc]) yes no)
+ // cond: !fc.ltNoov()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ltNoov()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LTnoov (InvertFlags cmp) yes no)
+ // result: (GTnoov cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64GTnoov, cmp)
+ return true
+ }
+ case BlockARM64NE:
+ // match: (NE (CMPWconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (NE (TSTWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (TST x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (CMPWconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (TSTW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (CMPconst [0] x:(ANDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (NE (TSTconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ANDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (NE (CMNconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (NE (CMNWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := auxIntToInt64(x.AuxInt)
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (CMP x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (CMN x y) yes no)
+ for b.Controls[0].Op == OpARM64CMP {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (CMNW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPW {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_0.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] x) yes no)
+ // result: (NZ x yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockARM64NZ, x)
+ return true
+ }
+ // match: (NE (CMPWconst [0] x) yes no)
+ // result: (NZW x yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockARM64NZW, x)
+ return true
+ }
+ // match: (NE (CMPconst [0] z:(MADD a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (NE (CMN a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADD {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] z:(MSUB a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (NE (CMP a (MUL <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUB {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMP, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MUL, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPWconst [0] z:(MADDW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (NE (CMNW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MADDW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPWconst [0] z:(MSUBW a x y)) yes no)
+ // cond: z.Uses==1
+ // result: (NE (CMPW a (MULW <x.Type> x y)) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpARM64MSUBW {
+ break
+ }
+ y := z.Args[2]
+ a := z.Args[0]
+ x := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v_0.Pos, OpARM64MULW, x.Type)
+ v1.AddArg2(x, y)
+ v0.AddArg2(a, v1)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (TSTconst [c] x) yes no)
+ // cond: oneBit(c)
+ // result: (TBNZ [int64(ntz64(c))] x yes no)
+ for b.Controls[0].Op == OpARM64TSTconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(oneBit(c)) {
+ break
+ }
+ b.resetWithControl(BlockARM64TBNZ, x)
+ b.AuxInt = int64ToAuxInt(int64(ntz64(c)))
+ return true
+ }
+ // match: (NE (TSTWconst [c] x) yes no)
+ // cond: oneBit(int64(uint32(c)))
+ // result: (TBNZ [int64(ntz64(int64(uint32(c))))] x yes no)
+ for b.Controls[0].Op == OpARM64TSTWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(oneBit(int64(uint32(c)))) {
+ break
+ }
+ b.resetWithControl(BlockARM64TBNZ, x)
+ b.AuxInt = int64ToAuxInt(int64(ntz64(int64(uint32(c)))))
+ return true
+ }
+ // match: (NE (FlagConstant [fc]) yes no)
+ // cond: fc.ne()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ne()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (NE (FlagConstant [fc]) yes no)
+ // cond: !fc.ne()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ne()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (NE (InvertFlags cmp) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64NE, cmp)
+ return true
+ }
+ case BlockARM64NZ:
+ // match: (NZ (Equal cc) yes no)
+ // result: (EQ cc yes no)
+ for b.Controls[0].Op == OpARM64Equal {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64EQ, cc)
+ return true
+ }
+ // match: (NZ (NotEqual cc) yes no)
+ // result: (NE cc yes no)
+ for b.Controls[0].Op == OpARM64NotEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64NE, cc)
+ return true
+ }
+ // match: (NZ (LessThan cc) yes no)
+ // result: (LT cc yes no)
+ for b.Controls[0].Op == OpARM64LessThan {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64LT, cc)
+ return true
+ }
+ // match: (NZ (LessThanU cc) yes no)
+ // result: (ULT cc yes no)
+ for b.Controls[0].Op == OpARM64LessThanU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64ULT, cc)
+ return true
+ }
+ // match: (NZ (LessEqual cc) yes no)
+ // result: (LE cc yes no)
+ for b.Controls[0].Op == OpARM64LessEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64LE, cc)
+ return true
+ }
+ // match: (NZ (LessEqualU cc) yes no)
+ // result: (ULE cc yes no)
+ for b.Controls[0].Op == OpARM64LessEqualU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64ULE, cc)
+ return true
+ }
+ // match: (NZ (GreaterThan cc) yes no)
+ // result: (GT cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterThan {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64GT, cc)
+ return true
+ }
+ // match: (NZ (GreaterThanU cc) yes no)
+ // result: (UGT cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterThanU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64UGT, cc)
+ return true
+ }
+ // match: (NZ (GreaterEqual cc) yes no)
+ // result: (GE cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64GE, cc)
+ return true
+ }
+ // match: (NZ (GreaterEqualU cc) yes no)
+ // result: (UGE cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterEqualU {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64UGE, cc)
+ return true
+ }
+ // match: (NZ (LessThanF cc) yes no)
+ // result: (FLT cc yes no)
+ for b.Controls[0].Op == OpARM64LessThanF {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64FLT, cc)
+ return true
+ }
+ // match: (NZ (LessEqualF cc) yes no)
+ // result: (FLE cc yes no)
+ for b.Controls[0].Op == OpARM64LessEqualF {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64FLE, cc)
+ return true
+ }
+ // match: (NZ (GreaterThanF cc) yes no)
+ // result: (FGT cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterThanF {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64FGT, cc)
+ return true
+ }
+ // match: (NZ (GreaterEqualF cc) yes no)
+ // result: (FGE cc yes no)
+ for b.Controls[0].Op == OpARM64GreaterEqualF {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockARM64FGE, cc)
+ return true
+ }
+ // match: (NZ (ANDconst [c] x) yes no)
+ // cond: oneBit(c)
+ // result: (TBNZ [int64(ntz64(c))] x yes no)
+ for b.Controls[0].Op == OpARM64ANDconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(oneBit(c)) {
+ break
+ }
+ b.resetWithControl(BlockARM64TBNZ, x)
+ b.AuxInt = int64ToAuxInt(int64(ntz64(c)))
+ return true
+ }
+ // match: (NZ (MOVDconst [0]) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64MOVDconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (NZ (MOVDconst [c]) yes no)
+ // cond: c != 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64MOVDconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ case BlockARM64NZW:
+ // match: (NZW (ANDconst [c] x) yes no)
+ // cond: oneBit(int64(uint32(c)))
+ // result: (TBNZ [int64(ntz64(int64(uint32(c))))] x yes no)
+ for b.Controls[0].Op == OpARM64ANDconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(oneBit(int64(uint32(c)))) {
+ break
+ }
+ b.resetWithControl(BlockARM64TBNZ, x)
+ b.AuxInt = int64ToAuxInt(int64(ntz64(int64(uint32(c)))))
+ return true
+ }
+ // match: (NZW (MOVDconst [c]) yes no)
+ // cond: int32(c) == 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64MOVDconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(int32(c) == 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (NZW (MOVDconst [c]) yes no)
+ // cond: int32(c) != 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64MOVDconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(int32(c) != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ case BlockARM64UGE:
+ // match: (UGE (FlagConstant [fc]) yes no)
+ // cond: fc.uge()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.uge()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGE (FlagConstant [fc]) yes no)
+ // cond: !fc.uge()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.uge()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGE (InvertFlags cmp) yes no)
+ // result: (ULE cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64ULE, cmp)
+ return true
+ }
+ case BlockARM64UGT:
+ // match: (UGT (FlagConstant [fc]) yes no)
+ // cond: fc.ugt()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ugt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (UGT (FlagConstant [fc]) yes no)
+ // cond: !fc.ugt()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ugt()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (UGT (InvertFlags cmp) yes no)
+ // result: (ULT cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64ULT, cmp)
+ return true
+ }
+ case BlockARM64ULE:
+ // match: (ULE (FlagConstant [fc]) yes no)
+ // cond: fc.ule()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ule()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULE (FlagConstant [fc]) yes no)
+ // cond: !fc.ule()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ule()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULE (InvertFlags cmp) yes no)
+ // result: (UGE cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64UGE, cmp)
+ return true
+ }
+ case BlockARM64ULT:
+ // match: (ULT (FlagConstant [fc]) yes no)
+ // cond: fc.ult()
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(fc.ult()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ULT (FlagConstant [fc]) yes no)
+ // cond: !fc.ult()
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64FlagConstant {
+ v_0 := b.Controls[0]
+ fc := auxIntToFlagConstant(v_0.AuxInt)
+ if !(!fc.ult()) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (ULT (InvertFlags cmp) yes no)
+ // result: (UGT cmp yes no)
+ for b.Controls[0].Op == OpARM64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockARM64UGT, cmp)
+ return true
+ }
+ case BlockARM64Z:
+ // match: (Z (ANDconst [c] x) yes no)
+ // cond: oneBit(c)
+ // result: (TBZ [int64(ntz64(c))] x yes no)
+ for b.Controls[0].Op == OpARM64ANDconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(oneBit(c)) {
+ break
+ }
+ b.resetWithControl(BlockARM64TBZ, x)
+ b.AuxInt = int64ToAuxInt(int64(ntz64(c)))
+ return true
+ }
+ // match: (Z (MOVDconst [0]) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64MOVDconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (Z (MOVDconst [c]) yes no)
+ // cond: c != 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64MOVDconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockARM64ZW:
+ // match: (ZW (ANDconst [c] x) yes no)
+ // cond: oneBit(int64(uint32(c)))
+ // result: (TBZ [int64(ntz64(int64(uint32(c))))] x yes no)
+ for b.Controls[0].Op == OpARM64ANDconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(oneBit(int64(uint32(c)))) {
+ break
+ }
+ b.resetWithControl(BlockARM64TBZ, x)
+ b.AuxInt = int64ToAuxInt(int64(ntz64(int64(uint32(c)))))
+ return true
+ }
+ // match: (ZW (MOVDconst [c]) yes no)
+ // cond: int32(c) == 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpARM64MOVDconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(int32(c) == 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (ZW (MOVDconst [c]) yes no)
+ // cond: int32(c) != 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpARM64MOVDconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(int32(c) != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteCond_test.go b/src/cmd/compile/internal/ssa/rewriteCond_test.go
new file mode 100644
index 0000000..2c26fdf
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewriteCond_test.go
@@ -0,0 +1,597 @@
+// Copyright 2020 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 (
+ "math"
+ "math/rand"
+ "testing"
+)
+
+var (
+ x64 int64 = math.MaxInt64 - 2
+ x64b int64 = math.MaxInt64 - 2
+ x64c int64 = math.MaxInt64 - 2
+ y64 int64 = math.MinInt64 + 1
+ x32 int32 = math.MaxInt32 - 2
+ x32b int32 = math.MaxInt32 - 2
+ x32c int32 = math.MaxInt32 - 2
+ y32 int32 = math.MinInt32 + 1
+ one64 int64 = 1
+ one32 int32 = 1
+ v64 int64 = 11 // ensure it's not 2**n +/- 1
+ v64_n int64 = -11
+ v32 int32 = 11
+ v32_n int32 = -11
+ uv32 uint32 = 19
+ uz uint8 = 1 // for lowering to SLL/SRL/SRA
+)
+
+var crTests = []struct {
+ name string
+ tf func(t *testing.T)
+}{
+ {"AddConst64", testAddConst64},
+ {"AddConst32", testAddConst32},
+ {"AddVar64", testAddVar64},
+ {"AddVar32", testAddVar32},
+ {"MAddVar64", testMAddVar64},
+ {"MAddVar32", testMAddVar32},
+ {"MSubVar64", testMSubVar64},
+ {"MSubVar32", testMSubVar32},
+ {"AddShift32", testAddShift32},
+ {"SubShift32", testSubShift32},
+}
+
+var crBenches = []struct {
+ name string
+ bf func(b *testing.B)
+}{
+ {"SoloJump", benchSoloJump},
+ {"CombJump", benchCombJump},
+}
+
+// Test int32/int64's add/sub/madd/msub operations with boundary values to
+// ensure the optimization to 'comparing to zero' expressions of if-statements
+// yield expected results.
+// 32 rewriting rules are covered. At least two scenarios for "Canonicalize
+// the order of arguments to comparisons", which helps with CSE, are covered.
+// The tedious if-else structures are necessary to ensure all concerned rules
+// and machine code sequences are covered.
+// It's for arm64 initially, please see https://github.com/golang/go/issues/38740
+func TestCondRewrite(t *testing.T) {
+ for _, test := range crTests {
+ t.Run(test.name, test.tf)
+ }
+}
+
+// Profile the aforementioned optimization from two angles:
+// SoloJump: generated branching code has one 'jump', for '<' and '>='
+// CombJump: generated branching code has two consecutive 'jump', for '<=' and '>'
+// We expect that 'CombJump' is generally on par with the non-optimized code, and
+// 'SoloJump' demonstrates some improvement.
+// It's for arm64 initially, please see https://github.com/golang/go/issues/38740
+func BenchmarkCondRewrite(b *testing.B) {
+ for _, bench := range crBenches {
+ b.Run(bench.name, bench.bf)
+ }
+}
+
+// var +/- const
+func testAddConst64(t *testing.T) {
+ if x64+11 < 0 {
+ } else {
+ t.Errorf("'%#x + 11 < 0' failed", x64)
+ }
+
+ if x64+13 <= 0 {
+ } else {
+ t.Errorf("'%#x + 13 <= 0' failed", x64)
+ }
+
+ if y64-11 > 0 {
+ } else {
+ t.Errorf("'%#x - 11 > 0' failed", y64)
+ }
+
+ if y64-13 >= 0 {
+ } else {
+ t.Errorf("'%#x - 13 >= 0' failed", y64)
+ }
+
+ if x64+19 > 0 {
+ t.Errorf("'%#x + 19 > 0' failed", x64)
+ }
+
+ if x64+23 >= 0 {
+ t.Errorf("'%#x + 23 >= 0' failed", x64)
+ }
+
+ if y64-19 < 0 {
+ t.Errorf("'%#x - 19 < 0' failed", y64)
+ }
+
+ if y64-23 <= 0 {
+ t.Errorf("'%#x - 23 <= 0' failed", y64)
+ }
+}
+
+// 32-bit var +/- const
+func testAddConst32(t *testing.T) {
+ if x32+11 < 0 {
+ } else {
+ t.Errorf("'%#x + 11 < 0' failed", x32)
+ }
+
+ if x32+13 <= 0 {
+ } else {
+ t.Errorf("'%#x + 13 <= 0' failed", x32)
+ }
+
+ if y32-11 > 0 {
+ } else {
+ t.Errorf("'%#x - 11 > 0' failed", y32)
+ }
+
+ if y32-13 >= 0 {
+ } else {
+ t.Errorf("'%#x - 13 >= 0' failed", y32)
+ }
+
+ if x32+19 > 0 {
+ t.Errorf("'%#x + 19 > 0' failed", x32)
+ }
+
+ if x32+23 >= 0 {
+ t.Errorf("'%#x + 23 >= 0' failed", x32)
+ }
+
+ if y32-19 < 0 {
+ t.Errorf("'%#x - 19 < 0' failed", y32)
+ }
+
+ if y32-23 <= 0 {
+ t.Errorf("'%#x - 23 <= 0' failed", y32)
+ }
+}
+
+// var + var
+func testAddVar64(t *testing.T) {
+ if x64+v64 < 0 {
+ } else {
+ t.Errorf("'%#x + %#x < 0' failed", x64, v64)
+ }
+
+ if x64+v64 <= 0 {
+ } else {
+ t.Errorf("'%#x + %#x <= 0' failed", x64, v64)
+ }
+
+ if y64+v64_n > 0 {
+ } else {
+ t.Errorf("'%#x + %#x > 0' failed", y64, v64_n)
+ }
+
+ if y64+v64_n >= 0 {
+ } else {
+ t.Errorf("'%#x + %#x >= 0' failed", y64, v64_n)
+ }
+
+ if x64+v64 > 0 {
+ t.Errorf("'%#x + %#x > 0' failed", x64, v64)
+ }
+
+ if x64+v64 >= 0 {
+ t.Errorf("'%#x + %#x >= 0' failed", x64, v64)
+ }
+
+ if y64+v64_n < 0 {
+ t.Errorf("'%#x + %#x < 0' failed", y64, v64_n)
+ }
+
+ if y64+v64_n <= 0 {
+ t.Errorf("'%#x + %#x <= 0' failed", y64, v64_n)
+ }
+}
+
+// 32-bit var+var
+func testAddVar32(t *testing.T) {
+ if x32+v32 < 0 {
+ } else {
+ t.Errorf("'%#x + %#x < 0' failed", x32, v32)
+ }
+
+ if x32+v32 <= 0 {
+ } else {
+ t.Errorf("'%#x + %#x <= 0' failed", x32, v32)
+ }
+
+ if y32+v32_n > 0 {
+ } else {
+ t.Errorf("'%#x + %#x > 0' failed", y32, v32_n)
+ }
+
+ if y32+v32_n >= 0 {
+ } else {
+ t.Errorf("'%#x + %#x >= 0' failed", y32, v32_n)
+ }
+
+ if x32+v32 > 0 {
+ t.Errorf("'%#x + %#x > 0' failed", x32, v32)
+ }
+
+ if x32+v32 >= 0 {
+ t.Errorf("'%#x + %#x >= 0' failed", x32, v32)
+ }
+
+ if y32+v32_n < 0 {
+ t.Errorf("'%#x + %#x < 0' failed", y32, v32_n)
+ }
+
+ if y32+v32_n <= 0 {
+ t.Errorf("'%#x + %#x <= 0' failed", y32, v32_n)
+ }
+}
+
+// multiply-add
+func testMAddVar64(t *testing.T) {
+ if x64+v64*one64 < 0 {
+ } else {
+ t.Errorf("'%#x + %#x*1 < 0' failed", x64, v64)
+ }
+
+ if x64+v64*one64 <= 0 {
+ } else {
+ t.Errorf("'%#x + %#x*1 <= 0' failed", x64, v64)
+ }
+
+ if y64+v64_n*one64 > 0 {
+ } else {
+ t.Errorf("'%#x + %#x*1 > 0' failed", y64, v64_n)
+ }
+
+ if y64+v64_n*one64 >= 0 {
+ } else {
+ t.Errorf("'%#x + %#x*1 >= 0' failed", y64, v64_n)
+ }
+
+ if x64+v64*one64 > 0 {
+ t.Errorf("'%#x + %#x*1 > 0' failed", x64, v64)
+ }
+
+ if x64+v64*one64 >= 0 {
+ t.Errorf("'%#x + %#x*1 >= 0' failed", x64, v64)
+ }
+
+ if y64+v64_n*one64 < 0 {
+ t.Errorf("'%#x + %#x*1 < 0' failed", y64, v64_n)
+ }
+
+ if y64+v64_n*one64 <= 0 {
+ t.Errorf("'%#x + %#x*1 <= 0' failed", y64, v64_n)
+ }
+}
+
+// 32-bit multiply-add
+func testMAddVar32(t *testing.T) {
+ if x32+v32*one32 < 0 {
+ } else {
+ t.Errorf("'%#x + %#x*1 < 0' failed", x32, v32)
+ }
+
+ if x32+v32*one32 <= 0 {
+ } else {
+ t.Errorf("'%#x + %#x*1 <= 0' failed", x32, v32)
+ }
+
+ if y32+v32_n*one32 > 0 {
+ } else {
+ t.Errorf("'%#x + %#x*1 > 0' failed", y32, v32_n)
+ }
+
+ if y32+v32_n*one32 >= 0 {
+ } else {
+ t.Errorf("'%#x + %#x*1 >= 0' failed", y32, v32_n)
+ }
+
+ if x32+v32*one32 > 0 {
+ t.Errorf("'%#x + %#x*1 > 0' failed", x32, v32)
+ }
+
+ if x32+v32*one32 >= 0 {
+ t.Errorf("'%#x + %#x*1 >= 0' failed", x32, v32)
+ }
+
+ if y32+v32_n*one32 < 0 {
+ t.Errorf("'%#x + %#x*1 < 0' failed", y32, v32_n)
+ }
+
+ if y32+v32_n*one32 <= 0 {
+ t.Errorf("'%#x + %#x*1 <= 0' failed", y32, v32_n)
+ }
+}
+
+// multiply-sub
+func testMSubVar64(t *testing.T) {
+ if x64-v64_n*one64 < 0 {
+ } else {
+ t.Errorf("'%#x - %#x*1 < 0' failed", x64, v64_n)
+ }
+
+ if x64-v64_n*one64 <= 0 {
+ } else {
+ t.Errorf("'%#x - %#x*1 <= 0' failed", x64, v64_n)
+ }
+
+ if y64-v64*one64 > 0 {
+ } else {
+ t.Errorf("'%#x - %#x*1 > 0' failed", y64, v64)
+ }
+
+ if y64-v64*one64 >= 0 {
+ } else {
+ t.Errorf("'%#x - %#x*1 >= 0' failed", y64, v64)
+ }
+
+ if x64-v64_n*one64 > 0 {
+ t.Errorf("'%#x - %#x*1 > 0' failed", x64, v64_n)
+ }
+
+ if x64-v64_n*one64 >= 0 {
+ t.Errorf("'%#x - %#x*1 >= 0' failed", x64, v64_n)
+ }
+
+ if y64-v64*one64 < 0 {
+ t.Errorf("'%#x - %#x*1 < 0' failed", y64, v64)
+ }
+
+ if y64-v64*one64 <= 0 {
+ t.Errorf("'%#x - %#x*1 <= 0' failed", y64, v64)
+ }
+
+ if x64-x64b*one64 < 0 {
+ t.Errorf("'%#x - %#x*1 < 0' failed", x64, x64b)
+ }
+
+ if x64-x64b*one64 >= 0 {
+ } else {
+ t.Errorf("'%#x - %#x*1 >= 0' failed", x64, x64b)
+ }
+}
+
+// 32-bit multiply-sub
+func testMSubVar32(t *testing.T) {
+ if x32-v32_n*one32 < 0 {
+ } else {
+ t.Errorf("'%#x - %#x*1 < 0' failed", x32, v32_n)
+ }
+
+ if x32-v32_n*one32 <= 0 {
+ } else {
+ t.Errorf("'%#x - %#x*1 <= 0' failed", x32, v32_n)
+ }
+
+ if y32-v32*one32 > 0 {
+ } else {
+ t.Errorf("'%#x - %#x*1 > 0' failed", y32, v32)
+ }
+
+ if y32-v32*one32 >= 0 {
+ } else {
+ t.Errorf("'%#x - %#x*1 >= 0' failed", y32, v32)
+ }
+
+ if x32-v32_n*one32 > 0 {
+ t.Errorf("'%#x - %#x*1 > 0' failed", x32, v32_n)
+ }
+
+ if x32-v32_n*one32 >= 0 {
+ t.Errorf("'%#x - %#x*1 >= 0' failed", x32, v32_n)
+ }
+
+ if y32-v32*one32 < 0 {
+ t.Errorf("'%#x - %#x*1 < 0' failed", y32, v32)
+ }
+
+ if y32-v32*one32 <= 0 {
+ t.Errorf("'%#x - %#x*1 <= 0' failed", y32, v32)
+ }
+
+ if x32-x32b*one32 < 0 {
+ t.Errorf("'%#x - %#x*1 < 0' failed", x32, x32b)
+ }
+
+ if x32-x32b*one32 >= 0 {
+ } else {
+ t.Errorf("'%#x - %#x*1 >= 0' failed", x32, x32b)
+ }
+}
+
+// 32-bit ADDshift, pick up 1~2 scenarios randomly for each condition
+func testAddShift32(t *testing.T) {
+ if x32+v32<<1 < 0 {
+ } else {
+ t.Errorf("'%#x + %#x<<%#x < 0' failed", x32, v32, 1)
+ }
+
+ if x32+v32>>1 <= 0 {
+ } else {
+ t.Errorf("'%#x + %#x>>%#x <= 0' failed", x32, v32, 1)
+ }
+
+ if x32+int32(uv32>>1) > 0 {
+ t.Errorf("'%#x + int32(%#x>>%#x) > 0' failed", x32, uv32, 1)
+ }
+
+ if x32+v32<<uz >= 0 {
+ t.Errorf("'%#x + %#x<<%#x >= 0' failed", x32, v32, uz)
+ }
+
+ if x32+v32>>uz > 0 {
+ t.Errorf("'%#x + %#x>>%#x > 0' failed", x32, v32, uz)
+ }
+
+ if x32+int32(uv32>>uz) < 0 {
+ } else {
+ t.Errorf("'%#x + int32(%#x>>%#x) < 0' failed", x32, uv32, uz)
+ }
+}
+
+// 32-bit SUBshift, pick up 1~2 scenarios randomly for each condition
+func testSubShift32(t *testing.T) {
+ if y32-v32<<1 > 0 {
+ } else {
+ t.Errorf("'%#x - %#x<<%#x > 0' failed", y32, v32, 1)
+ }
+
+ if y32-v32>>1 < 0 {
+ t.Errorf("'%#x - %#x>>%#x < 0' failed", y32, v32, 1)
+ }
+
+ if y32-int32(uv32>>1) >= 0 {
+ } else {
+ t.Errorf("'%#x - int32(%#x>>%#x) >= 0' failed", y32, uv32, 1)
+ }
+
+ if y32-v32<<uz < 0 {
+ t.Errorf("'%#x - %#x<<%#x < 0' failed", y32, v32, uz)
+ }
+
+ if y32-v32>>uz >= 0 {
+ } else {
+ t.Errorf("'%#x - %#x>>%#x >= 0' failed", y32, v32, uz)
+ }
+
+ if y32-int32(uv32>>uz) <= 0 {
+ t.Errorf("'%#x - int32(%#x>>%#x) <= 0' failed", y32, uv32, uz)
+ }
+}
+
+var rnd = rand.New(rand.NewSource(0))
+var sink int64
+
+func benchSoloJump(b *testing.B) {
+ r1 := x64
+ r2 := x64b
+ r3 := x64c
+ r4 := y64
+ d := rnd.Int63n(10)
+
+ // 6 out 10 conditions evaluate to true
+ for i := 0; i < b.N; i++ {
+ if r1+r2 < 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r1+r3 >= 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r1+r2*one64 < 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r2+r3*one64 >= 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r1-r2*v64 >= 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r3-r4*v64 < 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r1+11 < 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r1+13 >= 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r4-17 < 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r4-19 >= 0 {
+ d *= 2
+ d /= 2
+ }
+ }
+ sink = d
+}
+
+func benchCombJump(b *testing.B) {
+ r1 := x64
+ r2 := x64b
+ r3 := x64c
+ r4 := y64
+ d := rnd.Int63n(10)
+
+ // 6 out 10 conditions evaluate to true
+ for i := 0; i < b.N; i++ {
+ if r1+r2 <= 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r1+r3 > 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r1+r2*one64 <= 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r2+r3*one64 > 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r1-r2*v64 > 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r3-r4*v64 <= 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r1+11 <= 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r1+13 > 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r4-17 <= 0 {
+ d *= 2
+ d /= 2
+ }
+
+ if r4-19 > 0 {
+ d *= 2
+ d /= 2
+ }
+ }
+ sink = d
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS.go b/src/cmd/compile/internal/ssa/rewriteMIPS.go
new file mode 100644
index 0000000..3fc5527
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewriteMIPS.go
@@ -0,0 +1,7535 @@
+// Code generated from gen/MIPS.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "cmd/compile/internal/types"
+
+func rewriteValueMIPS(v *Value) bool {
+ switch v.Op {
+ case OpAdd16:
+ v.Op = OpMIPSADD
+ return true
+ case OpAdd32:
+ v.Op = OpMIPSADD
+ return true
+ case OpAdd32F:
+ v.Op = OpMIPSADDF
+ return true
+ case OpAdd32withcarry:
+ return rewriteValueMIPS_OpAdd32withcarry(v)
+ case OpAdd64F:
+ v.Op = OpMIPSADDD
+ return true
+ case OpAdd8:
+ v.Op = OpMIPSADD
+ return true
+ case OpAddPtr:
+ v.Op = OpMIPSADD
+ return true
+ case OpAddr:
+ return rewriteValueMIPS_OpAddr(v)
+ case OpAnd16:
+ v.Op = OpMIPSAND
+ return true
+ case OpAnd32:
+ v.Op = OpMIPSAND
+ return true
+ case OpAnd8:
+ v.Op = OpMIPSAND
+ return true
+ case OpAndB:
+ v.Op = OpMIPSAND
+ return true
+ case OpAtomicAdd32:
+ v.Op = OpMIPSLoweredAtomicAdd
+ return true
+ case OpAtomicAnd32:
+ v.Op = OpMIPSLoweredAtomicAnd
+ return true
+ case OpAtomicAnd8:
+ return rewriteValueMIPS_OpAtomicAnd8(v)
+ case OpAtomicCompareAndSwap32:
+ v.Op = OpMIPSLoweredAtomicCas
+ return true
+ case OpAtomicExchange32:
+ v.Op = OpMIPSLoweredAtomicExchange
+ return true
+ case OpAtomicLoad32:
+ v.Op = OpMIPSLoweredAtomicLoad32
+ return true
+ case OpAtomicLoad8:
+ v.Op = OpMIPSLoweredAtomicLoad8
+ return true
+ case OpAtomicLoadPtr:
+ v.Op = OpMIPSLoweredAtomicLoad32
+ return true
+ case OpAtomicOr32:
+ v.Op = OpMIPSLoweredAtomicOr
+ return true
+ case OpAtomicOr8:
+ return rewriteValueMIPS_OpAtomicOr8(v)
+ case OpAtomicStore32:
+ v.Op = OpMIPSLoweredAtomicStore32
+ return true
+ case OpAtomicStore8:
+ v.Op = OpMIPSLoweredAtomicStore8
+ return true
+ case OpAtomicStorePtrNoWB:
+ v.Op = OpMIPSLoweredAtomicStore32
+ return true
+ case OpAvg32u:
+ return rewriteValueMIPS_OpAvg32u(v)
+ case OpBitLen32:
+ return rewriteValueMIPS_OpBitLen32(v)
+ case OpClosureCall:
+ v.Op = OpMIPSCALLclosure
+ return true
+ case OpCom16:
+ return rewriteValueMIPS_OpCom16(v)
+ case OpCom32:
+ return rewriteValueMIPS_OpCom32(v)
+ case OpCom8:
+ return rewriteValueMIPS_OpCom8(v)
+ case OpConst16:
+ return rewriteValueMIPS_OpConst16(v)
+ case OpConst32:
+ return rewriteValueMIPS_OpConst32(v)
+ case OpConst32F:
+ v.Op = OpMIPSMOVFconst
+ return true
+ case OpConst64F:
+ v.Op = OpMIPSMOVDconst
+ return true
+ case OpConst8:
+ return rewriteValueMIPS_OpConst8(v)
+ case OpConstBool:
+ return rewriteValueMIPS_OpConstBool(v)
+ case OpConstNil:
+ return rewriteValueMIPS_OpConstNil(v)
+ case OpCtz32:
+ return rewriteValueMIPS_OpCtz32(v)
+ case OpCtz32NonZero:
+ v.Op = OpCtz32
+ return true
+ case OpCvt32Fto32:
+ v.Op = OpMIPSTRUNCFW
+ return true
+ case OpCvt32Fto64F:
+ v.Op = OpMIPSMOVFD
+ return true
+ case OpCvt32to32F:
+ v.Op = OpMIPSMOVWF
+ return true
+ case OpCvt32to64F:
+ v.Op = OpMIPSMOVWD
+ return true
+ case OpCvt64Fto32:
+ v.Op = OpMIPSTRUNCDW
+ return true
+ case OpCvt64Fto32F:
+ v.Op = OpMIPSMOVDF
+ return true
+ case OpCvtBoolToUint8:
+ v.Op = OpCopy
+ return true
+ case OpDiv16:
+ return rewriteValueMIPS_OpDiv16(v)
+ case OpDiv16u:
+ return rewriteValueMIPS_OpDiv16u(v)
+ case OpDiv32:
+ return rewriteValueMIPS_OpDiv32(v)
+ case OpDiv32F:
+ v.Op = OpMIPSDIVF
+ return true
+ case OpDiv32u:
+ return rewriteValueMIPS_OpDiv32u(v)
+ case OpDiv64F:
+ v.Op = OpMIPSDIVD
+ return true
+ case OpDiv8:
+ return rewriteValueMIPS_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValueMIPS_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValueMIPS_OpEq16(v)
+ case OpEq32:
+ return rewriteValueMIPS_OpEq32(v)
+ case OpEq32F:
+ return rewriteValueMIPS_OpEq32F(v)
+ case OpEq64F:
+ return rewriteValueMIPS_OpEq64F(v)
+ case OpEq8:
+ return rewriteValueMIPS_OpEq8(v)
+ case OpEqB:
+ return rewriteValueMIPS_OpEqB(v)
+ case OpEqPtr:
+ return rewriteValueMIPS_OpEqPtr(v)
+ case OpGetCallerPC:
+ v.Op = OpMIPSLoweredGetCallerPC
+ return true
+ case OpGetCallerSP:
+ v.Op = OpMIPSLoweredGetCallerSP
+ return true
+ case OpGetClosurePtr:
+ v.Op = OpMIPSLoweredGetClosurePtr
+ return true
+ case OpHmul32:
+ return rewriteValueMIPS_OpHmul32(v)
+ case OpHmul32u:
+ return rewriteValueMIPS_OpHmul32u(v)
+ case OpInterCall:
+ v.Op = OpMIPSCALLinter
+ return true
+ case OpIsInBounds:
+ return rewriteValueMIPS_OpIsInBounds(v)
+ case OpIsNonNil:
+ return rewriteValueMIPS_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ return rewriteValueMIPS_OpIsSliceInBounds(v)
+ case OpLeq16:
+ return rewriteValueMIPS_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValueMIPS_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValueMIPS_OpLeq32(v)
+ case OpLeq32F:
+ return rewriteValueMIPS_OpLeq32F(v)
+ case OpLeq32U:
+ return rewriteValueMIPS_OpLeq32U(v)
+ case OpLeq64F:
+ return rewriteValueMIPS_OpLeq64F(v)
+ case OpLeq8:
+ return rewriteValueMIPS_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValueMIPS_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValueMIPS_OpLess16(v)
+ case OpLess16U:
+ return rewriteValueMIPS_OpLess16U(v)
+ case OpLess32:
+ return rewriteValueMIPS_OpLess32(v)
+ case OpLess32F:
+ return rewriteValueMIPS_OpLess32F(v)
+ case OpLess32U:
+ return rewriteValueMIPS_OpLess32U(v)
+ case OpLess64F:
+ return rewriteValueMIPS_OpLess64F(v)
+ case OpLess8:
+ return rewriteValueMIPS_OpLess8(v)
+ case OpLess8U:
+ return rewriteValueMIPS_OpLess8U(v)
+ case OpLoad:
+ return rewriteValueMIPS_OpLoad(v)
+ case OpLocalAddr:
+ return rewriteValueMIPS_OpLocalAddr(v)
+ case OpLsh16x16:
+ return rewriteValueMIPS_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValueMIPS_OpLsh16x32(v)
+ case OpLsh16x64:
+ return rewriteValueMIPS_OpLsh16x64(v)
+ case OpLsh16x8:
+ return rewriteValueMIPS_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValueMIPS_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValueMIPS_OpLsh32x32(v)
+ case OpLsh32x64:
+ return rewriteValueMIPS_OpLsh32x64(v)
+ case OpLsh32x8:
+ return rewriteValueMIPS_OpLsh32x8(v)
+ case OpLsh8x16:
+ return rewriteValueMIPS_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValueMIPS_OpLsh8x32(v)
+ case OpLsh8x64:
+ return rewriteValueMIPS_OpLsh8x64(v)
+ case OpLsh8x8:
+ return rewriteValueMIPS_OpLsh8x8(v)
+ case OpMIPSADD:
+ return rewriteValueMIPS_OpMIPSADD(v)
+ case OpMIPSADDconst:
+ return rewriteValueMIPS_OpMIPSADDconst(v)
+ case OpMIPSAND:
+ return rewriteValueMIPS_OpMIPSAND(v)
+ case OpMIPSANDconst:
+ return rewriteValueMIPS_OpMIPSANDconst(v)
+ case OpMIPSCMOVZ:
+ return rewriteValueMIPS_OpMIPSCMOVZ(v)
+ case OpMIPSCMOVZzero:
+ return rewriteValueMIPS_OpMIPSCMOVZzero(v)
+ case OpMIPSLoweredAtomicAdd:
+ return rewriteValueMIPS_OpMIPSLoweredAtomicAdd(v)
+ case OpMIPSLoweredAtomicStore32:
+ return rewriteValueMIPS_OpMIPSLoweredAtomicStore32(v)
+ case OpMIPSMOVBUload:
+ return rewriteValueMIPS_OpMIPSMOVBUload(v)
+ case OpMIPSMOVBUreg:
+ return rewriteValueMIPS_OpMIPSMOVBUreg(v)
+ case OpMIPSMOVBload:
+ return rewriteValueMIPS_OpMIPSMOVBload(v)
+ case OpMIPSMOVBreg:
+ return rewriteValueMIPS_OpMIPSMOVBreg(v)
+ case OpMIPSMOVBstore:
+ return rewriteValueMIPS_OpMIPSMOVBstore(v)
+ case OpMIPSMOVBstorezero:
+ return rewriteValueMIPS_OpMIPSMOVBstorezero(v)
+ case OpMIPSMOVDload:
+ return rewriteValueMIPS_OpMIPSMOVDload(v)
+ case OpMIPSMOVDstore:
+ return rewriteValueMIPS_OpMIPSMOVDstore(v)
+ case OpMIPSMOVFload:
+ return rewriteValueMIPS_OpMIPSMOVFload(v)
+ case OpMIPSMOVFstore:
+ return rewriteValueMIPS_OpMIPSMOVFstore(v)
+ case OpMIPSMOVHUload:
+ return rewriteValueMIPS_OpMIPSMOVHUload(v)
+ case OpMIPSMOVHUreg:
+ return rewriteValueMIPS_OpMIPSMOVHUreg(v)
+ case OpMIPSMOVHload:
+ return rewriteValueMIPS_OpMIPSMOVHload(v)
+ case OpMIPSMOVHreg:
+ return rewriteValueMIPS_OpMIPSMOVHreg(v)
+ case OpMIPSMOVHstore:
+ return rewriteValueMIPS_OpMIPSMOVHstore(v)
+ case OpMIPSMOVHstorezero:
+ return rewriteValueMIPS_OpMIPSMOVHstorezero(v)
+ case OpMIPSMOVWload:
+ return rewriteValueMIPS_OpMIPSMOVWload(v)
+ case OpMIPSMOVWreg:
+ return rewriteValueMIPS_OpMIPSMOVWreg(v)
+ case OpMIPSMOVWstore:
+ return rewriteValueMIPS_OpMIPSMOVWstore(v)
+ case OpMIPSMOVWstorezero:
+ return rewriteValueMIPS_OpMIPSMOVWstorezero(v)
+ case OpMIPSMUL:
+ return rewriteValueMIPS_OpMIPSMUL(v)
+ case OpMIPSNEG:
+ return rewriteValueMIPS_OpMIPSNEG(v)
+ case OpMIPSNOR:
+ return rewriteValueMIPS_OpMIPSNOR(v)
+ case OpMIPSNORconst:
+ return rewriteValueMIPS_OpMIPSNORconst(v)
+ case OpMIPSOR:
+ return rewriteValueMIPS_OpMIPSOR(v)
+ case OpMIPSORconst:
+ return rewriteValueMIPS_OpMIPSORconst(v)
+ case OpMIPSSGT:
+ return rewriteValueMIPS_OpMIPSSGT(v)
+ case OpMIPSSGTU:
+ return rewriteValueMIPS_OpMIPSSGTU(v)
+ case OpMIPSSGTUconst:
+ return rewriteValueMIPS_OpMIPSSGTUconst(v)
+ case OpMIPSSGTUzero:
+ return rewriteValueMIPS_OpMIPSSGTUzero(v)
+ case OpMIPSSGTconst:
+ return rewriteValueMIPS_OpMIPSSGTconst(v)
+ case OpMIPSSGTzero:
+ return rewriteValueMIPS_OpMIPSSGTzero(v)
+ case OpMIPSSLL:
+ return rewriteValueMIPS_OpMIPSSLL(v)
+ case OpMIPSSLLconst:
+ return rewriteValueMIPS_OpMIPSSLLconst(v)
+ case OpMIPSSRA:
+ return rewriteValueMIPS_OpMIPSSRA(v)
+ case OpMIPSSRAconst:
+ return rewriteValueMIPS_OpMIPSSRAconst(v)
+ case OpMIPSSRL:
+ return rewriteValueMIPS_OpMIPSSRL(v)
+ case OpMIPSSRLconst:
+ return rewriteValueMIPS_OpMIPSSRLconst(v)
+ case OpMIPSSUB:
+ return rewriteValueMIPS_OpMIPSSUB(v)
+ case OpMIPSSUBconst:
+ return rewriteValueMIPS_OpMIPSSUBconst(v)
+ case OpMIPSXOR:
+ return rewriteValueMIPS_OpMIPSXOR(v)
+ case OpMIPSXORconst:
+ return rewriteValueMIPS_OpMIPSXORconst(v)
+ case OpMod16:
+ return rewriteValueMIPS_OpMod16(v)
+ case OpMod16u:
+ return rewriteValueMIPS_OpMod16u(v)
+ case OpMod32:
+ return rewriteValueMIPS_OpMod32(v)
+ case OpMod32u:
+ return rewriteValueMIPS_OpMod32u(v)
+ case OpMod8:
+ return rewriteValueMIPS_OpMod8(v)
+ case OpMod8u:
+ return rewriteValueMIPS_OpMod8u(v)
+ case OpMove:
+ return rewriteValueMIPS_OpMove(v)
+ case OpMul16:
+ v.Op = OpMIPSMUL
+ return true
+ case OpMul32:
+ v.Op = OpMIPSMUL
+ return true
+ case OpMul32F:
+ v.Op = OpMIPSMULF
+ return true
+ case OpMul32uhilo:
+ v.Op = OpMIPSMULTU
+ return true
+ case OpMul64F:
+ v.Op = OpMIPSMULD
+ return true
+ case OpMul8:
+ v.Op = OpMIPSMUL
+ return true
+ case OpNeg16:
+ v.Op = OpMIPSNEG
+ return true
+ case OpNeg32:
+ v.Op = OpMIPSNEG
+ return true
+ case OpNeg32F:
+ v.Op = OpMIPSNEGF
+ return true
+ case OpNeg64F:
+ v.Op = OpMIPSNEGD
+ return true
+ case OpNeg8:
+ v.Op = OpMIPSNEG
+ return true
+ case OpNeq16:
+ return rewriteValueMIPS_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValueMIPS_OpNeq32(v)
+ case OpNeq32F:
+ return rewriteValueMIPS_OpNeq32F(v)
+ case OpNeq64F:
+ return rewriteValueMIPS_OpNeq64F(v)
+ case OpNeq8:
+ return rewriteValueMIPS_OpNeq8(v)
+ case OpNeqB:
+ v.Op = OpMIPSXOR
+ return true
+ case OpNeqPtr:
+ return rewriteValueMIPS_OpNeqPtr(v)
+ case OpNilCheck:
+ v.Op = OpMIPSLoweredNilCheck
+ return true
+ case OpNot:
+ return rewriteValueMIPS_OpNot(v)
+ case OpOffPtr:
+ return rewriteValueMIPS_OpOffPtr(v)
+ case OpOr16:
+ v.Op = OpMIPSOR
+ return true
+ case OpOr32:
+ v.Op = OpMIPSOR
+ return true
+ case OpOr8:
+ v.Op = OpMIPSOR
+ return true
+ case OpOrB:
+ v.Op = OpMIPSOR
+ return true
+ case OpPanicBounds:
+ return rewriteValueMIPS_OpPanicBounds(v)
+ case OpPanicExtend:
+ return rewriteValueMIPS_OpPanicExtend(v)
+ case OpRotateLeft16:
+ return rewriteValueMIPS_OpRotateLeft16(v)
+ case OpRotateLeft32:
+ return rewriteValueMIPS_OpRotateLeft32(v)
+ case OpRotateLeft64:
+ return rewriteValueMIPS_OpRotateLeft64(v)
+ case OpRotateLeft8:
+ return rewriteValueMIPS_OpRotateLeft8(v)
+ case OpRound32F:
+ v.Op = OpCopy
+ return true
+ case OpRound64F:
+ v.Op = OpCopy
+ return true
+ case OpRsh16Ux16:
+ return rewriteValueMIPS_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValueMIPS_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValueMIPS_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValueMIPS_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValueMIPS_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValueMIPS_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValueMIPS_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValueMIPS_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValueMIPS_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValueMIPS_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValueMIPS_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValueMIPS_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValueMIPS_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValueMIPS_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValueMIPS_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValueMIPS_OpRsh32x8(v)
+ case OpRsh8Ux16:
+ return rewriteValueMIPS_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValueMIPS_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValueMIPS_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValueMIPS_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValueMIPS_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValueMIPS_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValueMIPS_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValueMIPS_OpRsh8x8(v)
+ case OpSelect0:
+ return rewriteValueMIPS_OpSelect0(v)
+ case OpSelect1:
+ return rewriteValueMIPS_OpSelect1(v)
+ case OpSignExt16to32:
+ v.Op = OpMIPSMOVHreg
+ return true
+ case OpSignExt8to16:
+ v.Op = OpMIPSMOVBreg
+ return true
+ case OpSignExt8to32:
+ v.Op = OpMIPSMOVBreg
+ return true
+ case OpSignmask:
+ return rewriteValueMIPS_OpSignmask(v)
+ case OpSlicemask:
+ return rewriteValueMIPS_OpSlicemask(v)
+ case OpSqrt:
+ v.Op = OpMIPSSQRTD
+ return true
+ case OpStaticCall:
+ v.Op = OpMIPSCALLstatic
+ return true
+ case OpStore:
+ return rewriteValueMIPS_OpStore(v)
+ case OpSub16:
+ v.Op = OpMIPSSUB
+ return true
+ case OpSub32:
+ v.Op = OpMIPSSUB
+ return true
+ case OpSub32F:
+ v.Op = OpMIPSSUBF
+ return true
+ case OpSub32withcarry:
+ return rewriteValueMIPS_OpSub32withcarry(v)
+ case OpSub64F:
+ v.Op = OpMIPSSUBD
+ return true
+ case OpSub8:
+ v.Op = OpMIPSSUB
+ return true
+ case OpSubPtr:
+ v.Op = OpMIPSSUB
+ return true
+ case OpTrunc16to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to8:
+ v.Op = OpCopy
+ return true
+ case OpWB:
+ v.Op = OpMIPSLoweredWB
+ return true
+ case OpXor16:
+ v.Op = OpMIPSXOR
+ return true
+ case OpXor32:
+ v.Op = OpMIPSXOR
+ return true
+ case OpXor8:
+ v.Op = OpMIPSXOR
+ return true
+ case OpZero:
+ return rewriteValueMIPS_OpZero(v)
+ case OpZeroExt16to32:
+ v.Op = OpMIPSMOVHUreg
+ return true
+ case OpZeroExt8to16:
+ v.Op = OpMIPSMOVBUreg
+ return true
+ case OpZeroExt8to32:
+ v.Op = OpMIPSMOVBUreg
+ return true
+ case OpZeromask:
+ return rewriteValueMIPS_OpZeromask(v)
+ }
+ return false
+}
+func rewriteValueMIPS_OpAdd32withcarry(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Add32withcarry <t> x y c)
+ // result: (ADD c (ADD <t> x y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ c := v_2
+ v.reset(OpMIPSADD)
+ v0 := b.NewValue0(v.Pos, OpMIPSADD, t)
+ v0.AddArg2(x, y)
+ v.AddArg2(c, v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Addr {sym} base)
+ // result: (MOVWaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpMIPSMOVWaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueMIPS_OpAtomicAnd8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (AtomicAnd8 ptr val mem)
+ // cond: !config.BigEndian
+ // result: (LoweredAtomicAnd (AND <typ.UInt32Ptr> (MOVWconst [^3]) ptr) (OR <typ.UInt32> (SLL <typ.UInt32> (ZeroExt8to32 val) (SLLconst <typ.UInt32> [3] (ANDconst <typ.UInt32> [3] ptr))) (NORconst [0] <typ.UInt32> (SLL <typ.UInt32> (MOVWconst [0xff]) (SLLconst <typ.UInt32> [3] (ANDconst <typ.UInt32> [3] ptr))))) mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(!config.BigEndian) {
+ break
+ }
+ v.reset(OpMIPSLoweredAtomicAnd)
+ v0 := b.NewValue0(v.Pos, OpMIPSAND, typ.UInt32Ptr)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(^3)
+ v0.AddArg2(v1, ptr)
+ v2 := b.NewValue0(v.Pos, OpMIPSOR, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpMIPSSLL, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v4.AddArg(val)
+ v5 := b.NewValue0(v.Pos, OpMIPSSLLconst, typ.UInt32)
+ v5.AuxInt = int32ToAuxInt(3)
+ v6 := b.NewValue0(v.Pos, OpMIPSANDconst, typ.UInt32)
+ v6.AuxInt = int32ToAuxInt(3)
+ v6.AddArg(ptr)
+ v5.AddArg(v6)
+ v3.AddArg2(v4, v5)
+ v7 := b.NewValue0(v.Pos, OpMIPSNORconst, typ.UInt32)
+ v7.AuxInt = int32ToAuxInt(0)
+ v8 := b.NewValue0(v.Pos, OpMIPSSLL, typ.UInt32)
+ v9 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v9.AuxInt = int32ToAuxInt(0xff)
+ v8.AddArg2(v9, v5)
+ v7.AddArg(v8)
+ v2.AddArg2(v3, v7)
+ v.AddArg3(v0, v2, mem)
+ return true
+ }
+ // match: (AtomicAnd8 ptr val mem)
+ // cond: config.BigEndian
+ // result: (LoweredAtomicAnd (AND <typ.UInt32Ptr> (MOVWconst [^3]) ptr) (OR <typ.UInt32> (SLL <typ.UInt32> (ZeroExt8to32 val) (SLLconst <typ.UInt32> [3] (ANDconst <typ.UInt32> [3] (XORconst <typ.UInt32> [3] ptr)))) (NORconst [0] <typ.UInt32> (SLL <typ.UInt32> (MOVWconst [0xff]) (SLLconst <typ.UInt32> [3] (ANDconst <typ.UInt32> [3] (XORconst <typ.UInt32> [3] ptr)))))) mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(config.BigEndian) {
+ break
+ }
+ v.reset(OpMIPSLoweredAtomicAnd)
+ v0 := b.NewValue0(v.Pos, OpMIPSAND, typ.UInt32Ptr)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(^3)
+ v0.AddArg2(v1, ptr)
+ v2 := b.NewValue0(v.Pos, OpMIPSOR, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpMIPSSLL, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v4.AddArg(val)
+ v5 := b.NewValue0(v.Pos, OpMIPSSLLconst, typ.UInt32)
+ v5.AuxInt = int32ToAuxInt(3)
+ v6 := b.NewValue0(v.Pos, OpMIPSANDconst, typ.UInt32)
+ v6.AuxInt = int32ToAuxInt(3)
+ v7 := b.NewValue0(v.Pos, OpMIPSXORconst, typ.UInt32)
+ v7.AuxInt = int32ToAuxInt(3)
+ v7.AddArg(ptr)
+ v6.AddArg(v7)
+ v5.AddArg(v6)
+ v3.AddArg2(v4, v5)
+ v8 := b.NewValue0(v.Pos, OpMIPSNORconst, typ.UInt32)
+ v8.AuxInt = int32ToAuxInt(0)
+ v9 := b.NewValue0(v.Pos, OpMIPSSLL, typ.UInt32)
+ v10 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v10.AuxInt = int32ToAuxInt(0xff)
+ v9.AddArg2(v10, v5)
+ v8.AddArg(v9)
+ v2.AddArg2(v3, v8)
+ v.AddArg3(v0, v2, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpAtomicOr8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (AtomicOr8 ptr val mem)
+ // cond: !config.BigEndian
+ // result: (LoweredAtomicOr (AND <typ.UInt32Ptr> (MOVWconst [^3]) ptr) (SLL <typ.UInt32> (ZeroExt8to32 val) (SLLconst <typ.UInt32> [3] (ANDconst <typ.UInt32> [3] ptr))) mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(!config.BigEndian) {
+ break
+ }
+ v.reset(OpMIPSLoweredAtomicOr)
+ v0 := b.NewValue0(v.Pos, OpMIPSAND, typ.UInt32Ptr)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(^3)
+ v0.AddArg2(v1, ptr)
+ v2 := b.NewValue0(v.Pos, OpMIPSSLL, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v3.AddArg(val)
+ v4 := b.NewValue0(v.Pos, OpMIPSSLLconst, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(3)
+ v5 := b.NewValue0(v.Pos, OpMIPSANDconst, typ.UInt32)
+ v5.AuxInt = int32ToAuxInt(3)
+ v5.AddArg(ptr)
+ v4.AddArg(v5)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v2, mem)
+ return true
+ }
+ // match: (AtomicOr8 ptr val mem)
+ // cond: config.BigEndian
+ // result: (LoweredAtomicOr (AND <typ.UInt32Ptr> (MOVWconst [^3]) ptr) (SLL <typ.UInt32> (ZeroExt8to32 val) (SLLconst <typ.UInt32> [3] (ANDconst <typ.UInt32> [3] (XORconst <typ.UInt32> [3] ptr)))) mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(config.BigEndian) {
+ break
+ }
+ v.reset(OpMIPSLoweredAtomicOr)
+ v0 := b.NewValue0(v.Pos, OpMIPSAND, typ.UInt32Ptr)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(^3)
+ v0.AddArg2(v1, ptr)
+ v2 := b.NewValue0(v.Pos, OpMIPSSLL, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v3.AddArg(val)
+ v4 := b.NewValue0(v.Pos, OpMIPSSLLconst, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(3)
+ v5 := b.NewValue0(v.Pos, OpMIPSANDconst, typ.UInt32)
+ v5.AuxInt = int32ToAuxInt(3)
+ v6 := b.NewValue0(v.Pos, OpMIPSXORconst, typ.UInt32)
+ v6.AuxInt = int32ToAuxInt(3)
+ v6.AddArg(ptr)
+ v5.AddArg(v6)
+ v4.AddArg(v5)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v2, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpAvg32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Avg32u <t> x y)
+ // result: (ADD (SRLconst <t> (SUB <t> x y) [1]) y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSADD)
+ v0 := b.NewValue0(v.Pos, OpMIPSSRLconst, t)
+ v0.AuxInt = int32ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPSSUB, t)
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueMIPS_OpBitLen32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen32 <t> x)
+ // result: (SUB (MOVWconst [32]) (CLZ <t> x))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpMIPSSUB)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(32)
+ v1 := b.NewValue0(v.Pos, OpMIPSCLZ, t)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpCom16(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com16 x)
+ // result: (NORconst [0] x)
+ for {
+ x := v_0
+ v.reset(OpMIPSNORconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueMIPS_OpCom32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com32 x)
+ // result: (NORconst [0] x)
+ for {
+ x := v_0
+ v.reset(OpMIPSNORconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueMIPS_OpCom8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com8 x)
+ // result: (NORconst [0] x)
+ for {
+ x := v_0
+ v.reset(OpMIPSNORconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueMIPS_OpConst16(v *Value) bool {
+ // match: (Const16 [val])
+ // result: (MOVWconst [int32(val)])
+ for {
+ val := auxIntToInt16(v.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(val))
+ return true
+ }
+}
+func rewriteValueMIPS_OpConst32(v *Value) bool {
+ // match: (Const32 [val])
+ // result: (MOVWconst [int32(val)])
+ for {
+ val := auxIntToInt32(v.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(val))
+ return true
+ }
+}
+func rewriteValueMIPS_OpConst8(v *Value) bool {
+ // match: (Const8 [val])
+ // result: (MOVWconst [int32(val)])
+ for {
+ val := auxIntToInt8(v.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(val))
+ return true
+ }
+}
+func rewriteValueMIPS_OpConstBool(v *Value) bool {
+ // match: (ConstBool [b])
+ // result: (MOVWconst [b2i32(b)])
+ for {
+ b := auxIntToBool(v.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(b2i32(b))
+ return true
+ }
+}
+func rewriteValueMIPS_OpConstNil(v *Value) bool {
+ // match: (ConstNil)
+ // result: (MOVWconst [0])
+ for {
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpCtz32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz32 <t> x)
+ // result: (SUB (MOVWconst [32]) (CLZ <t> (SUBconst <t> [1] (AND <t> x (NEG <t> x)))))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpMIPSSUB)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(32)
+ v1 := b.NewValue0(v.Pos, OpMIPSCLZ, t)
+ v2 := b.NewValue0(v.Pos, OpMIPSSUBconst, t)
+ v2.AuxInt = int32ToAuxInt(1)
+ v3 := b.NewValue0(v.Pos, OpMIPSAND, t)
+ v4 := b.NewValue0(v.Pos, OpMIPSNEG, t)
+ v4.AddArg(x)
+ v3.AddArg2(x, v4)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpDiv16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16 x y)
+ // result: (Select1 (DIV (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIV, types.NewTuple(typ.Int32, typ.Int32))
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpDiv16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16u x y)
+ // result: (Select1 (DIVU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIVU, types.NewTuple(typ.UInt32, typ.UInt32))
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpDiv32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32 x y)
+ // result: (Select1 (DIV x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIV, types.NewTuple(typ.Int32, typ.Int32))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpDiv32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32u x y)
+ // result: (Select1 (DIVU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIVU, types.NewTuple(typ.UInt32, typ.UInt32))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 x y)
+ // result: (Select1 (DIV (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIV, types.NewTuple(typ.Int32, typ.Int32))
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u x y)
+ // result: (Select1 (DIVU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIVU, types.NewTuple(typ.UInt32, typ.UInt32))
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq16 x y)
+ // result: (SGTUconst [1] (XOR (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTUconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSXOR, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq32 x y)
+ // result: (SGTUconst [1] (XOR x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTUconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSXOR, typ.UInt32)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpEq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32F x y)
+ // result: (FPFlagTrue (CMPEQF x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSFPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMPEQF, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpEq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64F x y)
+ // result: (FPFlagTrue (CMPEQD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSFPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMPEQD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq8 x y)
+ // result: (SGTUconst [1] (XOR (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTUconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSXOR, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpEqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqB x y)
+ // result: (XORconst [1] (XOR <typ.Bool> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSXOR, typ.Bool)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpEqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqPtr x y)
+ // result: (SGTUconst [1] (XOR x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTUconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSXOR, typ.UInt32)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpHmul32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul32 x y)
+ // result: (Select0 (MULT x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPSMULT, types.NewTuple(typ.Int32, typ.Int32))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpHmul32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul32u x y)
+ // result: (Select0 (MULTU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPSMULTU, types.NewTuple(typ.UInt32, typ.UInt32))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpIsInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (IsInBounds idx len)
+ // result: (SGTU len idx)
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpMIPSSGTU)
+ v.AddArg2(len, idx)
+ return true
+ }
+}
+func rewriteValueMIPS_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (IsNonNil ptr)
+ // result: (SGTU ptr (MOVWconst [0]))
+ for {
+ ptr := v_0
+ v.reset(OpMIPSSGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(ptr, v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpIsSliceInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (IsSliceInBounds idx len)
+ // result: (XORconst [1] (SGTU idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSSGTU, typ.Bool)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16 x y)
+ // result: (XORconst [1] (SGT (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSSGT, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16U x y)
+ // result: (XORconst [1] (SGTU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSSGTU, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32 x y)
+ // result: (XORconst [1] (SGT x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSSGT, typ.Bool)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32F x y)
+ // result: (FPFlagTrue (CMPGEF y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSFPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMPGEF, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32U x y)
+ // result: (XORconst [1] (SGTU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSSGTU, typ.Bool)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64F x y)
+ // result: (FPFlagTrue (CMPGED y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSFPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMPGED, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8 x y)
+ // result: (XORconst [1] (SGT (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSSGT, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8U x y)
+ // result: (XORconst [1] (SGTU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSSGTU, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16 x y)
+ // result: (SGT (SignExt16to32 y) (SignExt16to32 x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGT)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16U x y)
+ // result: (SGTU (ZeroExt16to32 y) (ZeroExt16to32 x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less32 x y)
+ // result: (SGT y x)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGT)
+ v.AddArg2(y, x)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLess32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32F x y)
+ // result: (FPFlagTrue (CMPGTF y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSFPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMPGTF, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less32U x y)
+ // result: (SGTU y x)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTU)
+ v.AddArg2(y, x)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLess64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64F x y)
+ // result: (FPFlagTrue (CMPGTD y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSFPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMPGTD, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8 x y)
+ // result: (SGT (SignExt8to32 y) (SignExt8to32 x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGT)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8U x y)
+ // result: (SGTU (ZeroExt8to32 y) (ZeroExt8to32 x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Load <t> ptr mem)
+ // cond: t.IsBoolean()
+ // result: (MOVBUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsBoolean()) {
+ break
+ }
+ v.reset(OpMIPSMOVBUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is8BitInt(t) && isSigned(t))
+ // result: (MOVBload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpMIPSMOVBload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is8BitInt(t) && !isSigned(t))
+ // result: (MOVBUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpMIPSMOVBUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is16BitInt(t) && isSigned(t))
+ // result: (MOVHload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpMIPSMOVHload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is16BitInt(t) && !isSigned(t))
+ // result: (MOVHUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpMIPSMOVHUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is32BitInt(t) || isPtr(t))
+ // result: (MOVWload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpMIPSMOVWload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitFloat(t)
+ // result: (MOVFload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(OpMIPSMOVFload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitFloat(t)
+ // result: (MOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(OpMIPSMOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpLocalAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LocalAddr {sym} base _)
+ // result: (MOVWaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpMIPSMOVWaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x16 <t> x y)
+ // result: (CMOVZ (SLL <t> x (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x32 <t> x y)
+ // result: (CMOVZ (SLL <t> x y) (MOVWconst [0]) (SGTUconst [32] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Lsh16x64 x (Const64 [c]))
+ // cond: uint32(c) < 16
+ // result: (SLLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 16) {
+ break
+ }
+ v.reset(OpMIPSSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh16x64 _ (Const64 [c]))
+ // cond: uint32(c) >= 16
+ // result: (MOVWconst [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) >= 16) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x8 <t> x y)
+ // result: (CMOVZ (SLL <t> x (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x16 <t> x y)
+ // result: (CMOVZ (SLL <t> x (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x32 <t> x y)
+ // result: (CMOVZ (SLL <t> x y) (MOVWconst [0]) (SGTUconst [32] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Lsh32x64 x (Const64 [c]))
+ // cond: uint32(c) < 32
+ // result: (SLLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 32) {
+ break
+ }
+ v.reset(OpMIPSSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh32x64 _ (Const64 [c]))
+ // cond: uint32(c) >= 32
+ // result: (MOVWconst [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) >= 32) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x8 <t> x y)
+ // result: (CMOVZ (SLL <t> x (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x16 <t> x y)
+ // result: (CMOVZ (SLL <t> x (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x32 <t> x y)
+ // result: (CMOVZ (SLL <t> x y) (MOVWconst [0]) (SGTUconst [32] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueMIPS_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Lsh8x64 x (Const64 [c]))
+ // cond: uint32(c) < 8
+ // result: (SLLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 8) {
+ break
+ }
+ v.reset(OpMIPSSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh8x64 _ (Const64 [c]))
+ // cond: uint32(c) >= 8
+ // result: (MOVWconst [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) >= 8) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x8 <t> x y)
+ // result: (CMOVZ (SLL <t> x (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpMIPSADD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADD x (MOVWconst [c]))
+ // result: (ADDconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpMIPSADDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (NEG y))
+ // result: (SUB x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPSNEG {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpMIPSSUB)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSADDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDconst [off1] (MOVWaddr [off2] {sym} ptr))
+ // result: (MOVWaddr [off1+off2] {sym} ptr)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ v.reset(OpMIPSMOVWaddr)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (ADDconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ADDconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [int32(c+d)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(c + d))
+ return true
+ }
+ // match: (ADDconst [c] (ADDconst [d] x))
+ // result: (ADDconst [c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSADDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpMIPSADDconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [c] (SUBconst [d] x))
+ // result: (ADDconst [c-d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSSUBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpMIPSADDconst)
+ v.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSAND(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (AND x (MOVWconst [c]))
+ // result: (ANDconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpMIPSANDconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (AND (SGTUconst [1] x) (SGTUconst [1] y))
+ // result: (SGTUconst [1] (OR <x.Type> x y))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMIPSSGTUconst || auxIntToInt32(v_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpMIPSSGTUconst || auxIntToInt32(v_1.AuxInt) != 1 {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpMIPSSGTUconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSOR, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSANDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ANDconst [0] _)
+ // result: (MOVWconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (ANDconst [-1] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [c&d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(c & d)
+ return true
+ }
+ // match: (ANDconst [c] (ANDconst [d] x))
+ // result: (ANDconst [c&d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSANDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpMIPSANDconst)
+ v.AuxInt = int32ToAuxInt(c & d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSCMOVZ(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVZ _ f (MOVWconst [0]))
+ // result: f
+ for {
+ f := v_1
+ if v_2.Op != OpMIPSMOVWconst || auxIntToInt32(v_2.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(f)
+ return true
+ }
+ // match: (CMOVZ a _ (MOVWconst [c]))
+ // cond: c!=0
+ // result: a
+ for {
+ a := v_0
+ if v_2.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_2.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.copyOf(a)
+ return true
+ }
+ // match: (CMOVZ a (MOVWconst [0]) c)
+ // result: (CMOVZzero a c)
+ for {
+ a := v_0
+ if v_1.Op != OpMIPSMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ c := v_2
+ v.reset(OpMIPSCMOVZzero)
+ v.AddArg2(a, c)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSCMOVZzero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CMOVZzero _ (MOVWconst [0]))
+ // result: (MOVWconst [0])
+ for {
+ if v_1.Op != OpMIPSMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (CMOVZzero a (MOVWconst [c]))
+ // cond: c!=0
+ // result: a
+ for {
+ a := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.copyOf(a)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSLoweredAtomicAdd(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LoweredAtomicAdd ptr (MOVWconst [c]) mem)
+ // cond: is16Bit(int64(c))
+ // result: (LoweredAtomicAddconst [c] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ mem := v_2
+ if !(is16Bit(int64(c))) {
+ break
+ }
+ v.reset(OpMIPSLoweredAtomicAddconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSLoweredAtomicStore32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LoweredAtomicStore32 ptr (MOVWconst [0]) mem)
+ // result: (LoweredAtomicStorezero ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpMIPSLoweredAtomicStorezero)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVBUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBUload [off1] {sym} x:(ADDconst [off2] ptr) mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVBUload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVBUreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVBstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpMIPSMOVBUreg)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVBUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVBUreg x:(MOVBUload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVBUload {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg x:(MOVBUreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVBUreg {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg <t> x:(MOVBload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBUload <t> [off] {sym} ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpMIPSMOVBload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpMIPSMOVBUload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUreg (ANDconst [c] x))
+ // result: (ANDconst [c&0xff] x)
+ for {
+ if v_0.Op != OpMIPSANDconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpMIPSANDconst)
+ v.AuxInt = int32ToAuxInt(c & 0xff)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg (MOVWconst [c]))
+ // result: (MOVWconst [int32(uint8(c))])
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint8(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVBload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBload [off1] {sym} x:(ADDconst [off2] ptr) mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVBload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVBreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVBstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpMIPSMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVBreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVBreg x:(MOVBload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVBload {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg x:(MOVBreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVBreg {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg <t> x:(MOVBUload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBload <t> [off] {sym} ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpMIPSMOVBUload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpMIPSMOVBload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBreg (ANDconst [c] x))
+ // cond: c & 0x80 == 0
+ // result: (ANDconst [c&0x7f] x)
+ for {
+ if v_0.Op != OpMIPSANDconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c&0x80 == 0) {
+ break
+ }
+ v.reset(OpMIPSANDconst)
+ v.AuxInt = int32ToAuxInt(c & 0x7f)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (MOVWconst [c]))
+ // result: (MOVWconst [int32(int8(c))])
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(int8(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVBstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstore [off1] {sym} x:(ADDconst [off2] ptr) val mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVBstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVWconst [0]) mem)
+ // result: (MOVBstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpMIPSMOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVBreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVBUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVHUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVBstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstorezero [off1] {sym} x:(ADDconst [off2] ptr) mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVBstorezero [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstorezero [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDload [off1] {sym} x:(ADDconst [off2] ptr) mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVDload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVDstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstore [off1] {sym} x:(ADDconst [off2] ptr) val mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVDstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVFload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVFload [off1] {sym} x:(ADDconst [off2] ptr) mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVFload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVFload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVFload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVFload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVFload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVFload [off] {sym} ptr (MOVFstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVFstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVFstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVFstore [off1] {sym} x:(ADDconst [off2] ptr) val mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVFstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVFstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVFstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVFstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVFstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVHUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHUload [off1] {sym} x:(ADDconst [off2] ptr) mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVHUload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVHUreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVHstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpMIPSMOVHUreg)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVHUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVHUreg x:(MOVBUload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVBUload {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVHUload {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVBUreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVBUreg {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVHUreg {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg <t> x:(MOVHload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVHUload <t> [off] {sym} ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpMIPSMOVHload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpMIPSMOVHUload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUreg (ANDconst [c] x))
+ // result: (ANDconst [c&0xffff] x)
+ for {
+ if v_0.Op != OpMIPSANDconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpMIPSANDconst)
+ v.AuxInt = int32ToAuxInt(c & 0xffff)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg (MOVWconst [c]))
+ // result: (MOVWconst [int32(uint16(c))])
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint16(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVHload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHload [off1] {sym} x:(ADDconst [off2] ptr) mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVHload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: (MOVHreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVHstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.reset(OpMIPSMOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVHreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVHreg x:(MOVBload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVBload {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVBUload {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHload _ _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVHload {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVBreg {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVBUreg {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHreg _))
+ // result: (MOVWreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPSMOVHreg {
+ break
+ }
+ v.reset(OpMIPSMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg <t> x:(MOVHUload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVHload <t> [off] {sym} ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpMIPSMOVHUload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpMIPSMOVHload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHreg (ANDconst [c] x))
+ // cond: c & 0x8000 == 0
+ // result: (ANDconst [c&0x7fff] x)
+ for {
+ if v_0.Op != OpMIPSANDconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c&0x8000 == 0) {
+ break
+ }
+ v.reset(OpMIPSANDconst)
+ v.AuxInt = int32ToAuxInt(c & 0x7fff)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (MOVWconst [c]))
+ // result: (MOVWconst [int32(int16(c))])
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(int16(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVHstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstore [off1] {sym} x:(ADDconst [off2] ptr) val mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVHstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVWconst [0]) mem)
+ // result: (MOVHstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpMIPSMOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPSMOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHUreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVHUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPSMOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPSMOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVHstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstorezero [off1] {sym} x:(ADDconst [off2] ptr) mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVHstorezero [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstorezero [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVWload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWload [off1] {sym} x:(ADDconst [off2] ptr) mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVWload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
+ // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVWstore {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVWreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVWreg x)
+ // cond: x.Uses == 1
+ // result: (MOVWnop x)
+ for {
+ x := v_0
+ if !(x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVWnop)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg (MOVWconst [c]))
+ // result: (MOVWconst [c])
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVWstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstore [off1] {sym} x:(ADDconst [off2] ptr) val mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVWstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWconst [0]) mem)
+ // result: (MOVWstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpMIPSMOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPSMOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPSMOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMOVWstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstorezero [off1] {sym} x:(ADDconst [off2] ptr) mem)
+ // cond: (is16Bit(int64(off1+off2)) || x.Uses == 1)
+ // result: (MOVWstorezero [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if x.Op != OpMIPSADDconst {
+ break
+ }
+ off2 := auxIntToInt32(x.AuxInt)
+ ptr := x.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1+off2)) || x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstorezero [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2)
+ // result: (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPSMOVWaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpMIPSMOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSMUL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MUL (MOVWconst [0]) _ )
+ // result: (MOVWconst [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMIPSMOVWconst || auxIntToInt32(v_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (MUL (MOVWconst [1]) x )
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMIPSMOVWconst || auxIntToInt32(v_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (MUL (MOVWconst [-1]) x )
+ // result: (NEG x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMIPSMOVWconst || auxIntToInt32(v_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpMIPSNEG)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MUL (MOVWconst [c]) x )
+ // cond: isPowerOfTwo64(int64(uint32(c)))
+ // result: (SLLconst [int32(log2uint32(int64(c)))] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ if !(isPowerOfTwo64(int64(uint32(c)))) {
+ continue
+ }
+ v.reset(OpMIPSSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(log2uint32(int64(c))))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MUL (MOVWconst [c]) (MOVWconst [d]))
+ // result: (MOVWconst [c*d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpMIPSMOVWconst {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(c * d)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSNEG(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEG (MOVWconst [c]))
+ // result: (MOVWconst [-c])
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSNOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (NOR x (MOVWconst [c]))
+ // result: (NORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpMIPSNORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSNORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NORconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [^(c|d)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(^(c | d))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (OR x (MOVWconst [c]))
+ // result: (ORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpMIPSORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (OR x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (OR (SGTUzero x) (SGTUzero y))
+ // result: (SGTUzero (OR <x.Type> x y))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMIPSSGTUzero {
+ continue
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpMIPSSGTUzero {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpMIPSSGTUzero)
+ v0 := b.NewValue0(v.Pos, OpMIPSOR, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORconst [-1] _)
+ // result: (MOVWconst [-1])
+ for {
+ if auxIntToInt32(v.AuxInt) != -1 {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ // match: (ORconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [c|d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(c | d)
+ return true
+ }
+ // match: (ORconst [c] (ORconst [d] x))
+ // result: (ORconst [c|d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSORconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpMIPSORconst)
+ v.AuxInt = int32ToAuxInt(c | d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSGT(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SGT (MOVWconst [c]) x)
+ // result: (SGTconst [c] x)
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpMIPSSGTconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SGT x (MOVWconst [0]))
+ // result: (SGTzero x)
+ for {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpMIPSSGTzero)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSGTU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SGTU (MOVWconst [c]) x)
+ // result: (SGTUconst [c] x)
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpMIPSSGTUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SGTU x (MOVWconst [0]))
+ // result: (SGTUzero x)
+ for {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpMIPSSGTUzero)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSGTUconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SGTUconst [c] (MOVWconst [d]))
+ // cond: uint32(c) > uint32(d)
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ if !(uint32(c) > uint32(d)) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTUconst [c] (MOVWconst [d]))
+ // cond: uint32(c) <= uint32(d)
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ if !(uint32(c) <= uint32(d)) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SGTUconst [c] (MOVBUreg _))
+ // cond: 0xff < uint32(c)
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVBUreg || !(0xff < uint32(c)) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTUconst [c] (MOVHUreg _))
+ // cond: 0xffff < uint32(c)
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVHUreg || !(0xffff < uint32(c)) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTUconst [c] (ANDconst [m] _))
+ // cond: uint32(m) < uint32(c)
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSANDconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(uint32(m) < uint32(c)) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTUconst [c] (SRLconst _ [d]))
+ // cond: uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c)
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSSRLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ if !(uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c)) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSGTUzero(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SGTUzero (MOVWconst [d]))
+ // cond: d != 0
+ // result: (MOVWconst [1])
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTUzero (MOVWconst [d]))
+ // cond: d == 0
+ // result: (MOVWconst [0])
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ if !(d == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSGTconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SGTconst [c] (MOVWconst [d]))
+ // cond: c > d
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ if !(c > d) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (MOVWconst [d]))
+ // cond: c <= d
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ if !(c <= d) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (MOVBreg _))
+ // cond: 0x7f < c
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVBreg || !(0x7f < c) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (MOVBreg _))
+ // cond: c <= -0x80
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVBreg || !(c <= -0x80) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (MOVBUreg _))
+ // cond: 0xff < c
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVBUreg || !(0xff < c) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (MOVBUreg _))
+ // cond: c < 0
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVBUreg || !(c < 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (MOVHreg _))
+ // cond: 0x7fff < c
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVHreg || !(0x7fff < c) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (MOVHreg _))
+ // cond: c <= -0x8000
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVHreg || !(c <= -0x8000) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (MOVHUreg _))
+ // cond: 0xffff < c
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVHUreg || !(0xffff < c) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (MOVHUreg _))
+ // cond: c < 0
+ // result: (MOVWconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVHUreg || !(c < 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (ANDconst [m] _))
+ // cond: 0 <= m && m < c
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSANDconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= m && m < c) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (SRLconst _ [d]))
+ // cond: 0 <= c && uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c)
+ // result: (MOVWconst [1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSSRLconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ if !(0 <= c && uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c)) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSGTzero(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SGTzero (MOVWconst [d]))
+ // cond: d > 0
+ // result: (MOVWconst [1])
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ if !(d > 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ return true
+ }
+ // match: (SGTzero (MOVWconst [d]))
+ // cond: d <= 0
+ // result: (MOVWconst [0])
+ for {
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ if !(d <= 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SLL x (MOVWconst [c]))
+ // result: (SLLconst x [c&31])
+ for {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpMIPSSLLconst)
+ v.AuxInt = int32ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSLLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SLLconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [d<<uint32(c)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(d << uint32(c))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRA x (MOVWconst [c]))
+ // result: (SRAconst x [c&31])
+ for {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpMIPSSRAconst)
+ v.AuxInt = int32ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSRAconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRAconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [d>>uint32(c)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(d >> uint32(c))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRL x (MOVWconst [c]))
+ // result: (SRLconst x [c&31])
+ for {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpMIPSSRLconst)
+ v.AuxInt = int32ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSRLconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRLconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [int32(uint32(d)>>uint32(c))])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(d) >> uint32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSUB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUB x (MOVWconst [c]))
+ // result: (SUBconst [c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpMIPSSUBconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB x x)
+ // result: (MOVWconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (SUB (MOVWconst [0]) x)
+ // result: (NEG x)
+ for {
+ if v_0.Op != OpMIPSMOVWconst || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpMIPSNEG)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSSUBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SUBconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUBconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [d-c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(d - c)
+ return true
+ }
+ // match: (SUBconst [c] (SUBconst [d] x))
+ // result: (ADDconst [-c-d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSSUBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpMIPSADDconst)
+ v.AuxInt = int32ToAuxInt(-c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBconst [c] (ADDconst [d] x))
+ // result: (ADDconst [-c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSADDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpMIPSADDconst)
+ v.AuxInt = int32ToAuxInt(-c + d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSXOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XOR x (MOVWconst [c]))
+ // result: (XORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR x x)
+ // result: (MOVWconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMIPSXORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (XORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (XORconst [-1] x)
+ // result: (NORconst [0] x)
+ for {
+ if auxIntToInt32(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.reset(OpMIPSNORconst)
+ v.AuxInt = int32ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORconst [c] (MOVWconst [d]))
+ // result: (MOVWconst [c^d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(c ^ d)
+ return true
+ }
+ // match: (XORconst [c] (XORconst [d] x))
+ // result: (XORconst [c^d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpMIPSXORconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(c ^ d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpMod16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16 x y)
+ // result: (Select0 (DIV (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIV, types.NewTuple(typ.Int32, typ.Int32))
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpMod16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16u x y)
+ // result: (Select0 (DIVU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIVU, types.NewTuple(typ.UInt32, typ.UInt32))
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpMod32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32 x y)
+ // result: (Select0 (DIV x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIV, types.NewTuple(typ.Int32, typ.Int32))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpMod32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32u x y)
+ // result: (Select0 (DIVU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIVU, types.NewTuple(typ.UInt32, typ.UInt32))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8 x y)
+ // result: (Select0 (DIV (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIV, types.NewTuple(typ.Int32, typ.Int32))
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8u x y)
+ // result: (Select0 (DIVU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPSDIVU, types.NewTuple(typ.UInt32, typ.UInt32))
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Move [0] _ _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Move [1] dst src mem)
+ // result: (MOVBstore dst (MOVBUload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpMIPSMOVBstore)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVBUload, typ.UInt8)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore dst (MOVHUload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVHstore)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVHUload, typ.UInt16)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] dst src mem)
+ // result: (MOVBstore [1] dst (MOVBUload [1] src mem) (MOVBstore dst (MOVBUload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVBUload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVBUload, typ.UInt8)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [4] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore dst (MOVWload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWload, typ.UInt32)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [4] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [2] dst (MOVHUload [2] src mem) (MOVHstore dst (MOVHUload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVHstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVHUload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVHstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVHUload, typ.UInt16)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [4] dst src mem)
+ // result: (MOVBstore [3] dst (MOVBUload [3] src mem) (MOVBstore [2] dst (MOVBUload [2] src mem) (MOVBstore [1] dst (MOVBUload [1] src mem) (MOVBstore dst (MOVBUload src mem) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVBUload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(3)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVBUload, typ.UInt8)
+ v2.AuxInt = int32ToAuxInt(2)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(1)
+ v4 := b.NewValue0(v.Pos, OpMIPSMOVBUload, typ.UInt8)
+ v4.AuxInt = int32ToAuxInt(1)
+ v4.AddArg2(src, mem)
+ v5 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v6 := b.NewValue0(v.Pos, OpMIPSMOVBUload, typ.UInt8)
+ v6.AddArg2(src, mem)
+ v5.AddArg3(dst, v6, mem)
+ v3.AddArg3(dst, v4, v5)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [3] dst src mem)
+ // result: (MOVBstore [2] dst (MOVBUload [2] src mem) (MOVBstore [1] dst (MOVBUload [1] src mem) (MOVBstore dst (MOVBUload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVBUload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVBUload, typ.UInt8)
+ v2.AuxInt = int32ToAuxInt(1)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpMIPSMOVBUload, typ.UInt8)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [8] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [4] dst (MOVWload [4] src mem) (MOVWstore dst (MOVWload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [8] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [6] dst (MOVHload [6] src mem) (MOVHstore [4] dst (MOVHload [4] src mem) (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVHstore)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVHload, typ.Int16)
+ v0.AuxInt = int32ToAuxInt(6)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVHload, typ.Int16)
+ v2.AuxInt = int32ToAuxInt(4)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVHstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(2)
+ v4 := b.NewValue0(v.Pos, OpMIPSMOVHload, typ.Int16)
+ v4.AuxInt = int32ToAuxInt(2)
+ v4.AddArg2(src, mem)
+ v5 := b.NewValue0(v.Pos, OpMIPSMOVHstore, types.TypeMem)
+ v6 := b.NewValue0(v.Pos, OpMIPSMOVHload, typ.Int16)
+ v6.AddArg2(src, mem)
+ v5.AddArg3(dst, v6, mem)
+ v3.AddArg3(dst, v4, v5)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [6] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [4] dst (MOVHload [4] src mem) (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVHstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVHload, typ.Int16)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVHload, typ.Int16)
+ v2.AuxInt = int32ToAuxInt(2)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVHstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpMIPSMOVHload, typ.Int16)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [12] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [8] dst (MOVWload [8] src mem) (MOVWstore [4] dst (MOVWload [4] src mem) (MOVWstore dst (MOVWload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWload, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(4)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpMIPSMOVWload, typ.UInt32)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [16] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [12] dst (MOVWload [12] src mem) (MOVWstore [8] dst (MOVWload [8] src mem) (MOVWstore [4] dst (MOVWload [4] src mem) (MOVWstore dst (MOVWload src mem) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v.AuxInt = int32ToAuxInt(12)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(12)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWload, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(8)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(4)
+ v4 := b.NewValue0(v.Pos, OpMIPSMOVWload, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(4)
+ v4.AddArg2(src, mem)
+ v5 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v6 := b.NewValue0(v.Pos, OpMIPSMOVWload, typ.UInt32)
+ v6.AddArg2(src, mem)
+ v5.AddArg3(dst, v6, mem)
+ v3.AddArg3(dst, v4, v5)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] {t} dst src mem)
+ // cond: (s > 16 && logLargeCopy(v, s) || t.Alignment()%4 != 0)
+ // result: (LoweredMove [int32(t.Alignment())] dst src (ADDconst <src.Type> src [int32(s-moveSize(t.Alignment(), config))]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 16 && logLargeCopy(v, s) || t.Alignment()%4 != 0) {
+ break
+ }
+ v.reset(OpMIPSLoweredMove)
+ v.AuxInt = int32ToAuxInt(int32(t.Alignment()))
+ v0 := b.NewValue0(v.Pos, OpMIPSADDconst, src.Type)
+ v0.AuxInt = int32ToAuxInt(int32(s - moveSize(t.Alignment(), config)))
+ v0.AddArg(src)
+ v.AddArg4(dst, src, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq16 x y)
+ // result: (SGTU (XOR (ZeroExt16to32 x) (ZeroExt16to32 y)) (MOVWconst [0]))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPSXOR, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq32 x y)
+ // result: (SGTU (XOR x y) (MOVWconst [0]))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPSXOR, typ.UInt32)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpNeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32F x y)
+ // result: (FPFlagFalse (CMPEQF x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSFPFlagFalse)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMPEQF, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpNeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64F x y)
+ // result: (FPFlagFalse (CMPEQD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSFPFlagFalse)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMPEQD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq8 x y)
+ // result: (SGTU (XOR (ZeroExt8to32 x) (ZeroExt8to32 y)) (MOVWconst [0]))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPSXOR, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpNeqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (NeqPtr x y)
+ // result: (SGTU (XOR x y) (MOVWconst [0]))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPSXOR, typ.UInt32)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpNot(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Not x)
+ // result: (XORconst [1] x)
+ for {
+ x := v_0
+ v.reset(OpMIPSXORconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueMIPS_OpOffPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (OffPtr [off] ptr:(SP))
+ // result: (MOVWaddr [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ if ptr.Op != OpSP {
+ break
+ }
+ v.reset(OpMIPSMOVWaddr)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (OffPtr [off] ptr)
+ // result: (ADDconst [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ v.reset(OpMIPSADDconst)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+}
+func rewriteValueMIPS_OpPanicBounds(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicBoundsA [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(OpMIPSLoweredPanicBoundsA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicBoundsB [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(OpMIPSLoweredPanicBoundsB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicBoundsC [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(OpMIPSLoweredPanicBoundsC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpPanicExtend(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicExtend [kind] hi lo y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicExtendA [kind] hi lo y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ hi := v_0
+ lo := v_1
+ y := v_2
+ mem := v_3
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(OpMIPSLoweredPanicExtendA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg4(hi, lo, y, mem)
+ return true
+ }
+ // match: (PanicExtend [kind] hi lo y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicExtendB [kind] hi lo y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ hi := v_0
+ lo := v_1
+ y := v_2
+ mem := v_3
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(OpMIPSLoweredPanicExtendB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg4(hi, lo, y, mem)
+ return true
+ }
+ // match: (PanicExtend [kind] hi lo y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicExtendC [kind] hi lo y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ hi := v_0
+ lo := v_1
+ y := v_2
+ mem := v_3
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(OpMIPSLoweredPanicExtendC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg4(hi, lo, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRotateLeft16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft16 <t> x (MOVWconst [c]))
+ // result: (Or16 (Lsh16x32 <t> x (MOVWconst [c&15])) (Rsh16Ux32 <t> x (MOVWconst [-c&15])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpLsh16x32, t)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(c & 15)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh16Ux32, t)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(-c & 15)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRotateLeft32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft32 <t> x (MOVWconst [c]))
+ // result: (Or32 (Lsh32x32 <t> x (MOVWconst [c&31])) (Rsh32Ux32 <t> x (MOVWconst [-c&31])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpOr32)
+ v0 := b.NewValue0(v.Pos, OpLsh32x32, t)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(c & 31)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh32Ux32, t)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(-c & 31)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRotateLeft64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft64 <t> x (MOVWconst [c]))
+ // result: (Or64 (Lsh64x32 <t> x (MOVWconst [c&63])) (Rsh64Ux32 <t> x (MOVWconst [-c&63])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpOr64)
+ v0 := b.NewValue0(v.Pos, OpLsh64x32, t)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(c & 63)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh64Ux32, t)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(-c & 63)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRotateLeft8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft8 <t> x (MOVWconst [c]))
+ // result: (Or8 (Lsh8x32 <t> x (MOVWconst [c&7])) (Rsh8Ux32 <t> x (MOVWconst [-c&7])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpLsh8x32, t)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(c & 7)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh8Ux32, t)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(-c & 7)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux16 <t> x y)
+ // result: (CMOVZ (SRL <t> (ZeroExt16to32 x) (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v4.AuxInt = int32ToAuxInt(32)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux32 <t> x y)
+ // result: (CMOVZ (SRL <t> (ZeroExt16to32 x) y) (MOVWconst [0]) (SGTUconst [32] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(y)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux64 x (Const64 [c]))
+ // cond: uint32(c) < 16
+ // result: (SRLconst (SLLconst <typ.UInt32> x [16]) [int32(c+16)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 16) {
+ break
+ }
+ v.reset(OpMIPSSRLconst)
+ v.AuxInt = int32ToAuxInt(int32(c + 16))
+ v0 := b.NewValue0(v.Pos, OpMIPSSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh16Ux64 _ (Const64 [c]))
+ // cond: uint32(c) >= 16
+ // result: (MOVWconst [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) >= 16) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux8 <t> x y)
+ // result: (CMOVZ (SRL <t> (ZeroExt16to32 x) (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v4.AuxInt = int32ToAuxInt(32)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x16 x y)
+ // result: (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> (ZeroExt16to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt16to32 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPSCMOVZ, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(31)
+ v4 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v4.AuxInt = int32ToAuxInt(32)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x32 x y)
+ // result: (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> y (MOVWconst [31]) (SGTUconst [32] y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPSCMOVZ, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(31)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(y)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x64 x (Const64 [c]))
+ // cond: uint32(c) < 16
+ // result: (SRAconst (SLLconst <typ.UInt32> x [16]) [int32(c+16)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 16) {
+ break
+ }
+ v.reset(OpMIPSSRAconst)
+ v.AuxInt = int32ToAuxInt(int32(c + 16))
+ v0 := b.NewValue0(v.Pos, OpMIPSSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh16x64 x (Const64 [c]))
+ // cond: uint32(c) >= 16
+ // result: (SRAconst (SLLconst <typ.UInt32> x [16]) [31])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) >= 16) {
+ break
+ }
+ v.reset(OpMIPSSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x8 x y)
+ // result: (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> (ZeroExt8to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt8to32 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPSCMOVZ, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(31)
+ v4 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v4.AuxInt = int32ToAuxInt(32)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux16 <t> x y)
+ // result: (CMOVZ (SRL <t> x (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux32 <t> x y)
+ // result: (CMOVZ (SRL <t> x y) (MOVWconst [0]) (SGTUconst [32] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Rsh32Ux64 x (Const64 [c]))
+ // cond: uint32(c) < 32
+ // result: (SRLconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 32) {
+ break
+ }
+ v.reset(OpMIPSSRLconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32Ux64 _ (Const64 [c]))
+ // cond: uint32(c) >= 32
+ // result: (MOVWconst [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) >= 32) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux8 <t> x y)
+ // result: (CMOVZ (SRL <t> x (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(v1)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x16 x y)
+ // result: (SRA x ( CMOVZ <typ.UInt32> (ZeroExt16to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt16to32 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSRA)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMOVZ, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(31)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(v1)
+ v0.AddArg3(v1, v2, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x32 x y)
+ // result: (SRA x ( CMOVZ <typ.UInt32> y (MOVWconst [31]) (SGTUconst [32] y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSRA)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMOVZ, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(31)
+ v2 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v2.AuxInt = int32ToAuxInt(32)
+ v2.AddArg(y)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Rsh32x64 x (Const64 [c]))
+ // cond: uint32(c) < 32
+ // result: (SRAconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 32) {
+ break
+ }
+ v.reset(OpMIPSSRAconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32x64 x (Const64 [c]))
+ // cond: uint32(c) >= 32
+ // result: (SRAconst x [31])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) >= 32) {
+ break
+ }
+ v.reset(OpMIPSSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x8 x y)
+ // result: (SRA x ( CMOVZ <typ.UInt32> (ZeroExt8to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt8to32 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSRA)
+ v0 := b.NewValue0(v.Pos, OpMIPSCMOVZ, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(31)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(v1)
+ v0.AddArg3(v1, v2, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux16 <t> x y)
+ // result: (CMOVZ (SRL <t> (ZeroExt8to32 x) (ZeroExt16to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt16to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v4.AuxInt = int32ToAuxInt(32)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux32 <t> x y)
+ // result: (CMOVZ (SRL <t> (ZeroExt8to32 x) y) (MOVWconst [0]) (SGTUconst [32] y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(y)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux64 x (Const64 [c]))
+ // cond: uint32(c) < 8
+ // result: (SRLconst (SLLconst <typ.UInt32> x [24]) [int32(c+24)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 8) {
+ break
+ }
+ v.reset(OpMIPSSRLconst)
+ v.AuxInt = int32ToAuxInt(int32(c + 24))
+ v0 := b.NewValue0(v.Pos, OpMIPSSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(24)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh8Ux64 _ (Const64 [c]))
+ // cond: uint32(c) >= 8
+ // result: (MOVWconst [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) >= 8) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux8 <t> x y)
+ // result: (CMOVZ (SRL <t> (ZeroExt8to32 x) (ZeroExt8to32 y) ) (MOVWconst [0]) (SGTUconst [32] (ZeroExt8to32 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSSRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(0)
+ v4 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v4.AuxInt = int32ToAuxInt(32)
+ v4.AddArg(v2)
+ v.AddArg3(v0, v3, v4)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x16 x y)
+ // result: (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> (ZeroExt16to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt16to32 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPSCMOVZ, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(31)
+ v4 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v4.AuxInt = int32ToAuxInt(32)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x32 x y)
+ // result: (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> y (MOVWconst [31]) (SGTUconst [32] y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPSCMOVZ, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(31)
+ v3 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v3.AuxInt = int32ToAuxInt(32)
+ v3.AddArg(y)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x64 x (Const64 [c]))
+ // cond: uint32(c) < 8
+ // result: (SRAconst (SLLconst <typ.UInt32> x [24]) [int32(c+24)])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 8) {
+ break
+ }
+ v.reset(OpMIPSSRAconst)
+ v.AuxInt = int32ToAuxInt(int32(c + 24))
+ v0 := b.NewValue0(v.Pos, OpMIPSSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(24)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh8x64 x (Const64 [c]))
+ // cond: uint32(c) >= 8
+ // result: (SRAconst (SLLconst <typ.UInt32> x [24]) [31])
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) >= 8) {
+ break
+ }
+ v.reset(OpMIPSSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v0 := b.NewValue0(v.Pos, OpMIPSSLLconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(24)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x8 x y)
+ // result: (SRA (SignExt16to32 x) ( CMOVZ <typ.UInt32> (ZeroExt8to32 y) (MOVWconst [31]) (SGTUconst [32] (ZeroExt8to32 y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPSSRA)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPSCMOVZ, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(31)
+ v4 := b.NewValue0(v.Pos, OpMIPSSGTUconst, typ.Bool)
+ v4.AuxInt = int32ToAuxInt(32)
+ v4.AddArg(v2)
+ v1.AddArg3(v2, v3, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS_OpSelect0(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select0 (Add32carry <t> x y))
+ // result: (ADD <t.FieldType(0)> x y)
+ for {
+ if v_0.Op != OpAdd32carry {
+ break
+ }
+ t := v_0.Type
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpMIPSADD)
+ v.Type = t.FieldType(0)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Select0 (Sub32carry <t> x y))
+ // result: (SUB <t.FieldType(0)> x y)
+ for {
+ if v_0.Op != OpSub32carry {
+ break
+ }
+ t := v_0.Type
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpMIPSSUB)
+ v.Type = t.FieldType(0)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Select0 (MULTU (MOVWconst [0]) _ ))
+ // result: (MOVWconst [0])
+ for {
+ if v_0.Op != OpMIPSMULTU {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPSMOVWconst || auxIntToInt32(v_0_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (Select0 (MULTU (MOVWconst [1]) _ ))
+ // result: (MOVWconst [0])
+ for {
+ if v_0.Op != OpMIPSMULTU {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPSMOVWconst || auxIntToInt32(v_0_0.AuxInt) != 1 {
+ continue
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (Select0 (MULTU (MOVWconst [-1]) x ))
+ // result: (CMOVZ (ADDconst <x.Type> [-1] x) (MOVWconst [0]) x)
+ for {
+ if v_0.Op != OpMIPSMULTU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPSMOVWconst || auxIntToInt32(v_0_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_0_1
+ v.reset(OpMIPSCMOVZ)
+ v0 := b.NewValue0(v.Pos, OpMIPSADDconst, x.Type)
+ v0.AuxInt = int32ToAuxInt(-1)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(v0, v1, x)
+ return true
+ }
+ break
+ }
+ // match: (Select0 (MULTU (MOVWconst [c]) x ))
+ // cond: isPowerOfTwo64(int64(uint32(c)))
+ // result: (SRLconst [int32(32-log2uint32(int64(c)))] x)
+ for {
+ if v_0.Op != OpMIPSMULTU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ x := v_0_1
+ if !(isPowerOfTwo64(int64(uint32(c)))) {
+ continue
+ }
+ v.reset(OpMIPSSRLconst)
+ v.AuxInt = int32ToAuxInt(int32(32 - log2uint32(int64(c))))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Select0 (MULTU (MOVWconst [c]) (MOVWconst [d])))
+ // result: (MOVWconst [int32((int64(uint32(c))*int64(uint32(d)))>>32)])
+ for {
+ if v_0.Op != OpMIPSMULTU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_0_1.Op != OpMIPSMOVWconst {
+ continue
+ }
+ d := auxIntToInt32(v_0_1.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32((int64(uint32(c)) * int64(uint32(d))) >> 32))
+ return true
+ }
+ break
+ }
+ // match: (Select0 (DIV (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
+ // result: (MOVWconst [c%d])
+ for {
+ if v_0.Op != OpMIPSDIV {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(c % d)
+ return true
+ }
+ // match: (Select0 (DIVU (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
+ // result: (MOVWconst [int32(uint32(c)%uint32(d))])
+ for {
+ if v_0.Op != OpMIPSDIVU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) % uint32(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpSelect1(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select1 (Add32carry <t> x y))
+ // result: (SGTU <typ.Bool> x (ADD <t.FieldType(0)> x y))
+ for {
+ if v_0.Op != OpAdd32carry {
+ break
+ }
+ t := v_0.Type
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpMIPSSGTU)
+ v.Type = typ.Bool
+ v0 := b.NewValue0(v.Pos, OpMIPSADD, t.FieldType(0))
+ v0.AddArg2(x, y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Select1 (Sub32carry <t> x y))
+ // result: (SGTU <typ.Bool> (SUB <t.FieldType(0)> x y) x)
+ for {
+ if v_0.Op != OpSub32carry {
+ break
+ }
+ t := v_0.Type
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpMIPSSGTU)
+ v.Type = typ.Bool
+ v0 := b.NewValue0(v.Pos, OpMIPSSUB, t.FieldType(0))
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Select1 (MULTU (MOVWconst [0]) _ ))
+ // result: (MOVWconst [0])
+ for {
+ if v_0.Op != OpMIPSMULTU {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPSMOVWconst || auxIntToInt32(v_0_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (Select1 (MULTU (MOVWconst [1]) x ))
+ // result: x
+ for {
+ if v_0.Op != OpMIPSMULTU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPSMOVWconst || auxIntToInt32(v_0_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_0_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Select1 (MULTU (MOVWconst [-1]) x ))
+ // result: (NEG <x.Type> x)
+ for {
+ if v_0.Op != OpMIPSMULTU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPSMOVWconst || auxIntToInt32(v_0_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_0_1
+ v.reset(OpMIPSNEG)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Select1 (MULTU (MOVWconst [c]) x ))
+ // cond: isPowerOfTwo64(int64(uint32(c)))
+ // result: (SLLconst [int32(log2uint32(int64(c)))] x)
+ for {
+ if v_0.Op != OpMIPSMULTU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ x := v_0_1
+ if !(isPowerOfTwo64(int64(uint32(c)))) {
+ continue
+ }
+ v.reset(OpMIPSSLLconst)
+ v.AuxInt = int32ToAuxInt(int32(log2uint32(int64(c))))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Select1 (MULTU (MOVWconst [c]) (MOVWconst [d])))
+ // result: (MOVWconst [int32(uint32(c)*uint32(d))])
+ for {
+ if v_0.Op != OpMIPSMULTU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPSMOVWconst {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_0_1.Op != OpMIPSMOVWconst {
+ continue
+ }
+ d := auxIntToInt32(v_0_1.AuxInt)
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) * uint32(d)))
+ return true
+ }
+ break
+ }
+ // match: (Select1 (DIV (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
+ // result: (MOVWconst [c/d])
+ for {
+ if v_0.Op != OpMIPSDIV {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(c / d)
+ return true
+ }
+ // match: (Select1 (DIVU (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
+ // result: (MOVWconst [int32(uint32(c)/uint32(d))])
+ for {
+ if v_0.Op != OpMIPSDIVU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpMIPSMOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPSMOVWconst {
+ break
+ }
+ d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWconst)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) / uint32(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpSignmask(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Signmask x)
+ // result: (SRAconst x [31])
+ for {
+ x := v_0
+ v.reset(OpMIPSSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueMIPS_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Slicemask <t> x)
+ // result: (SRAconst (NEG <t> x) [31])
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpMIPSSRAconst)
+ v.AuxInt = int32ToAuxInt(31)
+ v0 := b.NewValue0(v.Pos, OpMIPSNEG, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 1
+ // result: (MOVBstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 1) {
+ break
+ }
+ v.reset(OpMIPSMOVBstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 2
+ // result: (MOVHstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 2) {
+ break
+ }
+ v.reset(OpMIPSMOVHstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && !is32BitFloat(val.Type)
+ // result: (MOVWstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && !is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && is32BitFloat(val.Type)
+ // result: (MOVFstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpMIPSMOVFstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && is64BitFloat(val.Type)
+ // result: (MOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpMIPSMOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpSub32withcarry(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Sub32withcarry <t> x y c)
+ // result: (SUB (SUB <t> x y) c)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ c := v_2
+ v.reset(OpMIPSSUB)
+ v0 := b.NewValue0(v.Pos, OpMIPSSUB, t)
+ v0.AddArg2(x, y)
+ v.AddArg2(v0, c)
+ return true
+ }
+}
+func rewriteValueMIPS_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Zero [0] _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_1
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero [1] ptr mem)
+ // result: (MOVBstore ptr (MOVWconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpMIPSMOVBstore)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [2] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore ptr (MOVWconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVHstore)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [2] ptr mem)
+ // result: (MOVBstore [1] ptr (MOVWconst [0]) (MOVBstore [0] ptr (MOVWconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [4] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore ptr (MOVWconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [4] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [2] ptr (MOVWconst [0]) (MOVHstore [0] ptr (MOVWconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVHstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [4] ptr mem)
+ // result: (MOVBstore [3] ptr (MOVWconst [0]) (MOVBstore [2] ptr (MOVWconst [0]) (MOVBstore [1] ptr (MOVWconst [0]) (MOVBstore [0] ptr (MOVWconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(1)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(0)
+ v3.AddArg3(ptr, v0, mem)
+ v2.AddArg3(ptr, v0, v3)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [3] ptr mem)
+ // result: (MOVBstore [2] ptr (MOVWconst [0]) (MOVBstore [1] ptr (MOVWconst [0]) (MOVBstore [0] ptr (MOVWconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpMIPSMOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVBstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [6] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [4] ptr (MOVWconst [0]) (MOVHstore [2] ptr (MOVWconst [0]) (MOVHstore [0] ptr (MOVWconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVHstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVHstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [8] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [4] ptr (MOVWconst [0]) (MOVWstore [0] ptr (MOVWconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [12] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [8] ptr (MOVWconst [0]) (MOVWstore [4] ptr (MOVWconst [0]) (MOVWstore [0] ptr (MOVWconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [16] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [12] ptr (MOVWconst [0]) (MOVWstore [8] ptr (MOVWconst [0]) (MOVWstore [4] ptr (MOVWconst [0]) (MOVWstore [0] ptr (MOVWconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPSMOVWstore)
+ v.AuxInt = int32ToAuxInt(12)
+ v0 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(4)
+ v3 := b.NewValue0(v.Pos, OpMIPSMOVWstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(0)
+ v3.AddArg3(ptr, v0, mem)
+ v2.AddArg3(ptr, v0, v3)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [s] {t} ptr mem)
+ // cond: (s > 16 || t.Alignment()%4 != 0)
+ // result: (LoweredZero [int32(t.Alignment())] ptr (ADDconst <ptr.Type> ptr [int32(s-moveSize(t.Alignment(), config))]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(s > 16 || t.Alignment()%4 != 0) {
+ break
+ }
+ v.reset(OpMIPSLoweredZero)
+ v.AuxInt = int32ToAuxInt(int32(t.Alignment()))
+ v0 := b.NewValue0(v.Pos, OpMIPSADDconst, ptr.Type)
+ v0.AuxInt = int32ToAuxInt(int32(s - moveSize(t.Alignment(), config)))
+ v0.AddArg(ptr)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS_OpZeromask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Zeromask x)
+ // result: (NEG (SGTU x (MOVWconst [0])))
+ for {
+ x := v_0
+ v.reset(OpMIPSNEG)
+ v0 := b.NewValue0(v.Pos, OpMIPSSGTU, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpMIPSMOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v0.AddArg2(x, v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteBlockMIPS(b *Block) bool {
+ switch b.Kind {
+ case BlockMIPSEQ:
+ // match: (EQ (FPFlagTrue cmp) yes no)
+ // result: (FPF cmp yes no)
+ for b.Controls[0].Op == OpMIPSFPFlagTrue {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockMIPSFPF, cmp)
+ return true
+ }
+ // match: (EQ (FPFlagFalse cmp) yes no)
+ // result: (FPT cmp yes no)
+ for b.Controls[0].Op == OpMIPSFPFlagFalse {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockMIPSFPT, cmp)
+ return true
+ }
+ // match: (EQ (XORconst [1] cmp:(SGT _ _)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGT {
+ break
+ }
+ b.resetWithControl(BlockMIPSNE, cmp)
+ return true
+ }
+ // match: (EQ (XORconst [1] cmp:(SGTU _ _)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGTU {
+ break
+ }
+ b.resetWithControl(BlockMIPSNE, cmp)
+ return true
+ }
+ // match: (EQ (XORconst [1] cmp:(SGTconst _)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGTconst {
+ break
+ }
+ b.resetWithControl(BlockMIPSNE, cmp)
+ return true
+ }
+ // match: (EQ (XORconst [1] cmp:(SGTUconst _)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGTUconst {
+ break
+ }
+ b.resetWithControl(BlockMIPSNE, cmp)
+ return true
+ }
+ // match: (EQ (XORconst [1] cmp:(SGTzero _)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGTzero {
+ break
+ }
+ b.resetWithControl(BlockMIPSNE, cmp)
+ return true
+ }
+ // match: (EQ (XORconst [1] cmp:(SGTUzero _)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGTUzero {
+ break
+ }
+ b.resetWithControl(BlockMIPSNE, cmp)
+ return true
+ }
+ // match: (EQ (SGTUconst [1] x) yes no)
+ // result: (NE x yes no)
+ for b.Controls[0].Op == OpMIPSSGTUconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPSNE, x)
+ return true
+ }
+ // match: (EQ (SGTUzero x) yes no)
+ // result: (EQ x yes no)
+ for b.Controls[0].Op == OpMIPSSGTUzero {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPSEQ, x)
+ return true
+ }
+ // match: (EQ (SGTconst [0] x) yes no)
+ // result: (GEZ x yes no)
+ for b.Controls[0].Op == OpMIPSSGTconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPSGEZ, x)
+ return true
+ }
+ // match: (EQ (SGTzero x) yes no)
+ // result: (LEZ x yes no)
+ for b.Controls[0].Op == OpMIPSSGTzero {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPSLEZ, x)
+ return true
+ }
+ // match: (EQ (MOVWconst [0]) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (EQ (MOVWconst [c]) yes no)
+ // cond: c != 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockMIPSGEZ:
+ // match: (GEZ (MOVWconst [c]) yes no)
+ // cond: c >= 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(c >= 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GEZ (MOVWconst [c]) yes no)
+ // cond: c < 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(c < 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockMIPSGTZ:
+ // match: (GTZ (MOVWconst [c]) yes no)
+ // cond: c > 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(c > 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GTZ (MOVWconst [c]) yes no)
+ // cond: c <= 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(c <= 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockIf:
+ // match: (If cond yes no)
+ // result: (NE cond yes no)
+ for {
+ cond := b.Controls[0]
+ b.resetWithControl(BlockMIPSNE, cond)
+ return true
+ }
+ case BlockMIPSLEZ:
+ // match: (LEZ (MOVWconst [c]) yes no)
+ // cond: c <= 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(c <= 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LEZ (MOVWconst [c]) yes no)
+ // cond: c > 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(c > 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockMIPSLTZ:
+ // match: (LTZ (MOVWconst [c]) yes no)
+ // cond: c < 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(c < 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LTZ (MOVWconst [c]) yes no)
+ // cond: c >= 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(c >= 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockMIPSNE:
+ // match: (NE (FPFlagTrue cmp) yes no)
+ // result: (FPT cmp yes no)
+ for b.Controls[0].Op == OpMIPSFPFlagTrue {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockMIPSFPT, cmp)
+ return true
+ }
+ // match: (NE (FPFlagFalse cmp) yes no)
+ // result: (FPF cmp yes no)
+ for b.Controls[0].Op == OpMIPSFPFlagFalse {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockMIPSFPF, cmp)
+ return true
+ }
+ // match: (NE (XORconst [1] cmp:(SGT _ _)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGT {
+ break
+ }
+ b.resetWithControl(BlockMIPSEQ, cmp)
+ return true
+ }
+ // match: (NE (XORconst [1] cmp:(SGTU _ _)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGTU {
+ break
+ }
+ b.resetWithControl(BlockMIPSEQ, cmp)
+ return true
+ }
+ // match: (NE (XORconst [1] cmp:(SGTconst _)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGTconst {
+ break
+ }
+ b.resetWithControl(BlockMIPSEQ, cmp)
+ return true
+ }
+ // match: (NE (XORconst [1] cmp:(SGTUconst _)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGTUconst {
+ break
+ }
+ b.resetWithControl(BlockMIPSEQ, cmp)
+ return true
+ }
+ // match: (NE (XORconst [1] cmp:(SGTzero _)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGTzero {
+ break
+ }
+ b.resetWithControl(BlockMIPSEQ, cmp)
+ return true
+ }
+ // match: (NE (XORconst [1] cmp:(SGTUzero _)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpMIPSXORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPSSGTUzero {
+ break
+ }
+ b.resetWithControl(BlockMIPSEQ, cmp)
+ return true
+ }
+ // match: (NE (SGTUconst [1] x) yes no)
+ // result: (EQ x yes no)
+ for b.Controls[0].Op == OpMIPSSGTUconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPSEQ, x)
+ return true
+ }
+ // match: (NE (SGTUzero x) yes no)
+ // result: (NE x yes no)
+ for b.Controls[0].Op == OpMIPSSGTUzero {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPSNE, x)
+ return true
+ }
+ // match: (NE (SGTconst [0] x) yes no)
+ // result: (LTZ x yes no)
+ for b.Controls[0].Op == OpMIPSSGTconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPSLTZ, x)
+ return true
+ }
+ // match: (NE (SGTzero x) yes no)
+ // result: (GTZ x yes no)
+ for b.Controls[0].Op == OpMIPSSGTzero {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPSGTZ, x)
+ return true
+ }
+ // match: (NE (MOVWconst [0]) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (NE (MOVWconst [c]) yes no)
+ // cond: c != 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPSMOVWconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS64.go b/src/cmd/compile/internal/ssa/rewriteMIPS64.go
new file mode 100644
index 0000000..d78f608
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewriteMIPS64.go
@@ -0,0 +1,8040 @@
+// Code generated from gen/MIPS64.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "cmd/compile/internal/types"
+
+func rewriteValueMIPS64(v *Value) bool {
+ switch v.Op {
+ case OpAdd16:
+ v.Op = OpMIPS64ADDV
+ return true
+ case OpAdd32:
+ v.Op = OpMIPS64ADDV
+ return true
+ case OpAdd32F:
+ v.Op = OpMIPS64ADDF
+ return true
+ case OpAdd64:
+ v.Op = OpMIPS64ADDV
+ return true
+ case OpAdd64F:
+ v.Op = OpMIPS64ADDD
+ return true
+ case OpAdd8:
+ v.Op = OpMIPS64ADDV
+ return true
+ case OpAddPtr:
+ v.Op = OpMIPS64ADDV
+ return true
+ case OpAddr:
+ return rewriteValueMIPS64_OpAddr(v)
+ case OpAnd16:
+ v.Op = OpMIPS64AND
+ return true
+ case OpAnd32:
+ v.Op = OpMIPS64AND
+ return true
+ case OpAnd64:
+ v.Op = OpMIPS64AND
+ return true
+ case OpAnd8:
+ v.Op = OpMIPS64AND
+ return true
+ case OpAndB:
+ v.Op = OpMIPS64AND
+ return true
+ case OpAtomicAdd32:
+ v.Op = OpMIPS64LoweredAtomicAdd32
+ return true
+ case OpAtomicAdd64:
+ v.Op = OpMIPS64LoweredAtomicAdd64
+ return true
+ case OpAtomicCompareAndSwap32:
+ v.Op = OpMIPS64LoweredAtomicCas32
+ return true
+ case OpAtomicCompareAndSwap64:
+ v.Op = OpMIPS64LoweredAtomicCas64
+ return true
+ case OpAtomicExchange32:
+ v.Op = OpMIPS64LoweredAtomicExchange32
+ return true
+ case OpAtomicExchange64:
+ v.Op = OpMIPS64LoweredAtomicExchange64
+ return true
+ case OpAtomicLoad32:
+ v.Op = OpMIPS64LoweredAtomicLoad32
+ return true
+ case OpAtomicLoad64:
+ v.Op = OpMIPS64LoweredAtomicLoad64
+ return true
+ case OpAtomicLoad8:
+ v.Op = OpMIPS64LoweredAtomicLoad8
+ return true
+ case OpAtomicLoadPtr:
+ v.Op = OpMIPS64LoweredAtomicLoad64
+ return true
+ case OpAtomicStore32:
+ v.Op = OpMIPS64LoweredAtomicStore32
+ return true
+ case OpAtomicStore64:
+ v.Op = OpMIPS64LoweredAtomicStore64
+ return true
+ case OpAtomicStore8:
+ v.Op = OpMIPS64LoweredAtomicStore8
+ return true
+ case OpAtomicStorePtrNoWB:
+ v.Op = OpMIPS64LoweredAtomicStore64
+ return true
+ case OpAvg64u:
+ return rewriteValueMIPS64_OpAvg64u(v)
+ case OpClosureCall:
+ v.Op = OpMIPS64CALLclosure
+ return true
+ case OpCom16:
+ return rewriteValueMIPS64_OpCom16(v)
+ case OpCom32:
+ return rewriteValueMIPS64_OpCom32(v)
+ case OpCom64:
+ return rewriteValueMIPS64_OpCom64(v)
+ case OpCom8:
+ return rewriteValueMIPS64_OpCom8(v)
+ case OpConst16:
+ return rewriteValueMIPS64_OpConst16(v)
+ case OpConst32:
+ return rewriteValueMIPS64_OpConst32(v)
+ case OpConst32F:
+ return rewriteValueMIPS64_OpConst32F(v)
+ case OpConst64:
+ return rewriteValueMIPS64_OpConst64(v)
+ case OpConst64F:
+ return rewriteValueMIPS64_OpConst64F(v)
+ case OpConst8:
+ return rewriteValueMIPS64_OpConst8(v)
+ case OpConstBool:
+ return rewriteValueMIPS64_OpConstBool(v)
+ case OpConstNil:
+ return rewriteValueMIPS64_OpConstNil(v)
+ case OpCvt32Fto32:
+ v.Op = OpMIPS64TRUNCFW
+ return true
+ case OpCvt32Fto64:
+ v.Op = OpMIPS64TRUNCFV
+ return true
+ case OpCvt32Fto64F:
+ v.Op = OpMIPS64MOVFD
+ return true
+ case OpCvt32to32F:
+ v.Op = OpMIPS64MOVWF
+ return true
+ case OpCvt32to64F:
+ v.Op = OpMIPS64MOVWD
+ return true
+ case OpCvt64Fto32:
+ v.Op = OpMIPS64TRUNCDW
+ return true
+ case OpCvt64Fto32F:
+ v.Op = OpMIPS64MOVDF
+ return true
+ case OpCvt64Fto64:
+ v.Op = OpMIPS64TRUNCDV
+ return true
+ case OpCvt64to32F:
+ v.Op = OpMIPS64MOVVF
+ return true
+ case OpCvt64to64F:
+ v.Op = OpMIPS64MOVVD
+ return true
+ case OpCvtBoolToUint8:
+ v.Op = OpCopy
+ return true
+ case OpDiv16:
+ return rewriteValueMIPS64_OpDiv16(v)
+ case OpDiv16u:
+ return rewriteValueMIPS64_OpDiv16u(v)
+ case OpDiv32:
+ return rewriteValueMIPS64_OpDiv32(v)
+ case OpDiv32F:
+ v.Op = OpMIPS64DIVF
+ return true
+ case OpDiv32u:
+ return rewriteValueMIPS64_OpDiv32u(v)
+ case OpDiv64:
+ return rewriteValueMIPS64_OpDiv64(v)
+ case OpDiv64F:
+ v.Op = OpMIPS64DIVD
+ return true
+ case OpDiv64u:
+ return rewriteValueMIPS64_OpDiv64u(v)
+ case OpDiv8:
+ return rewriteValueMIPS64_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValueMIPS64_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValueMIPS64_OpEq16(v)
+ case OpEq32:
+ return rewriteValueMIPS64_OpEq32(v)
+ case OpEq32F:
+ return rewriteValueMIPS64_OpEq32F(v)
+ case OpEq64:
+ return rewriteValueMIPS64_OpEq64(v)
+ case OpEq64F:
+ return rewriteValueMIPS64_OpEq64F(v)
+ case OpEq8:
+ return rewriteValueMIPS64_OpEq8(v)
+ case OpEqB:
+ return rewriteValueMIPS64_OpEqB(v)
+ case OpEqPtr:
+ return rewriteValueMIPS64_OpEqPtr(v)
+ case OpGetCallerPC:
+ v.Op = OpMIPS64LoweredGetCallerPC
+ return true
+ case OpGetCallerSP:
+ v.Op = OpMIPS64LoweredGetCallerSP
+ return true
+ case OpGetClosurePtr:
+ v.Op = OpMIPS64LoweredGetClosurePtr
+ return true
+ case OpHmul32:
+ return rewriteValueMIPS64_OpHmul32(v)
+ case OpHmul32u:
+ return rewriteValueMIPS64_OpHmul32u(v)
+ case OpHmul64:
+ return rewriteValueMIPS64_OpHmul64(v)
+ case OpHmul64u:
+ return rewriteValueMIPS64_OpHmul64u(v)
+ case OpInterCall:
+ v.Op = OpMIPS64CALLinter
+ return true
+ case OpIsInBounds:
+ return rewriteValueMIPS64_OpIsInBounds(v)
+ case OpIsNonNil:
+ return rewriteValueMIPS64_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ return rewriteValueMIPS64_OpIsSliceInBounds(v)
+ case OpLeq16:
+ return rewriteValueMIPS64_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValueMIPS64_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValueMIPS64_OpLeq32(v)
+ case OpLeq32F:
+ return rewriteValueMIPS64_OpLeq32F(v)
+ case OpLeq32U:
+ return rewriteValueMIPS64_OpLeq32U(v)
+ case OpLeq64:
+ return rewriteValueMIPS64_OpLeq64(v)
+ case OpLeq64F:
+ return rewriteValueMIPS64_OpLeq64F(v)
+ case OpLeq64U:
+ return rewriteValueMIPS64_OpLeq64U(v)
+ case OpLeq8:
+ return rewriteValueMIPS64_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValueMIPS64_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValueMIPS64_OpLess16(v)
+ case OpLess16U:
+ return rewriteValueMIPS64_OpLess16U(v)
+ case OpLess32:
+ return rewriteValueMIPS64_OpLess32(v)
+ case OpLess32F:
+ return rewriteValueMIPS64_OpLess32F(v)
+ case OpLess32U:
+ return rewriteValueMIPS64_OpLess32U(v)
+ case OpLess64:
+ return rewriteValueMIPS64_OpLess64(v)
+ case OpLess64F:
+ return rewriteValueMIPS64_OpLess64F(v)
+ case OpLess64U:
+ return rewriteValueMIPS64_OpLess64U(v)
+ case OpLess8:
+ return rewriteValueMIPS64_OpLess8(v)
+ case OpLess8U:
+ return rewriteValueMIPS64_OpLess8U(v)
+ case OpLoad:
+ return rewriteValueMIPS64_OpLoad(v)
+ case OpLocalAddr:
+ return rewriteValueMIPS64_OpLocalAddr(v)
+ case OpLsh16x16:
+ return rewriteValueMIPS64_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValueMIPS64_OpLsh16x32(v)
+ case OpLsh16x64:
+ return rewriteValueMIPS64_OpLsh16x64(v)
+ case OpLsh16x8:
+ return rewriteValueMIPS64_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValueMIPS64_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValueMIPS64_OpLsh32x32(v)
+ case OpLsh32x64:
+ return rewriteValueMIPS64_OpLsh32x64(v)
+ case OpLsh32x8:
+ return rewriteValueMIPS64_OpLsh32x8(v)
+ case OpLsh64x16:
+ return rewriteValueMIPS64_OpLsh64x16(v)
+ case OpLsh64x32:
+ return rewriteValueMIPS64_OpLsh64x32(v)
+ case OpLsh64x64:
+ return rewriteValueMIPS64_OpLsh64x64(v)
+ case OpLsh64x8:
+ return rewriteValueMIPS64_OpLsh64x8(v)
+ case OpLsh8x16:
+ return rewriteValueMIPS64_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValueMIPS64_OpLsh8x32(v)
+ case OpLsh8x64:
+ return rewriteValueMIPS64_OpLsh8x64(v)
+ case OpLsh8x8:
+ return rewriteValueMIPS64_OpLsh8x8(v)
+ case OpMIPS64ADDV:
+ return rewriteValueMIPS64_OpMIPS64ADDV(v)
+ case OpMIPS64ADDVconst:
+ return rewriteValueMIPS64_OpMIPS64ADDVconst(v)
+ case OpMIPS64AND:
+ return rewriteValueMIPS64_OpMIPS64AND(v)
+ case OpMIPS64ANDconst:
+ return rewriteValueMIPS64_OpMIPS64ANDconst(v)
+ case OpMIPS64LoweredAtomicAdd32:
+ return rewriteValueMIPS64_OpMIPS64LoweredAtomicAdd32(v)
+ case OpMIPS64LoweredAtomicAdd64:
+ return rewriteValueMIPS64_OpMIPS64LoweredAtomicAdd64(v)
+ case OpMIPS64LoweredAtomicStore32:
+ return rewriteValueMIPS64_OpMIPS64LoweredAtomicStore32(v)
+ case OpMIPS64LoweredAtomicStore64:
+ return rewriteValueMIPS64_OpMIPS64LoweredAtomicStore64(v)
+ case OpMIPS64MOVBUload:
+ return rewriteValueMIPS64_OpMIPS64MOVBUload(v)
+ case OpMIPS64MOVBUreg:
+ return rewriteValueMIPS64_OpMIPS64MOVBUreg(v)
+ case OpMIPS64MOVBload:
+ return rewriteValueMIPS64_OpMIPS64MOVBload(v)
+ case OpMIPS64MOVBreg:
+ return rewriteValueMIPS64_OpMIPS64MOVBreg(v)
+ case OpMIPS64MOVBstore:
+ return rewriteValueMIPS64_OpMIPS64MOVBstore(v)
+ case OpMIPS64MOVBstorezero:
+ return rewriteValueMIPS64_OpMIPS64MOVBstorezero(v)
+ case OpMIPS64MOVDload:
+ return rewriteValueMIPS64_OpMIPS64MOVDload(v)
+ case OpMIPS64MOVDstore:
+ return rewriteValueMIPS64_OpMIPS64MOVDstore(v)
+ case OpMIPS64MOVFload:
+ return rewriteValueMIPS64_OpMIPS64MOVFload(v)
+ case OpMIPS64MOVFstore:
+ return rewriteValueMIPS64_OpMIPS64MOVFstore(v)
+ case OpMIPS64MOVHUload:
+ return rewriteValueMIPS64_OpMIPS64MOVHUload(v)
+ case OpMIPS64MOVHUreg:
+ return rewriteValueMIPS64_OpMIPS64MOVHUreg(v)
+ case OpMIPS64MOVHload:
+ return rewriteValueMIPS64_OpMIPS64MOVHload(v)
+ case OpMIPS64MOVHreg:
+ return rewriteValueMIPS64_OpMIPS64MOVHreg(v)
+ case OpMIPS64MOVHstore:
+ return rewriteValueMIPS64_OpMIPS64MOVHstore(v)
+ case OpMIPS64MOVHstorezero:
+ return rewriteValueMIPS64_OpMIPS64MOVHstorezero(v)
+ case OpMIPS64MOVVload:
+ return rewriteValueMIPS64_OpMIPS64MOVVload(v)
+ case OpMIPS64MOVVreg:
+ return rewriteValueMIPS64_OpMIPS64MOVVreg(v)
+ case OpMIPS64MOVVstore:
+ return rewriteValueMIPS64_OpMIPS64MOVVstore(v)
+ case OpMIPS64MOVVstorezero:
+ return rewriteValueMIPS64_OpMIPS64MOVVstorezero(v)
+ case OpMIPS64MOVWUload:
+ return rewriteValueMIPS64_OpMIPS64MOVWUload(v)
+ case OpMIPS64MOVWUreg:
+ return rewriteValueMIPS64_OpMIPS64MOVWUreg(v)
+ case OpMIPS64MOVWload:
+ return rewriteValueMIPS64_OpMIPS64MOVWload(v)
+ case OpMIPS64MOVWreg:
+ return rewriteValueMIPS64_OpMIPS64MOVWreg(v)
+ case OpMIPS64MOVWstore:
+ return rewriteValueMIPS64_OpMIPS64MOVWstore(v)
+ case OpMIPS64MOVWstorezero:
+ return rewriteValueMIPS64_OpMIPS64MOVWstorezero(v)
+ case OpMIPS64NEGV:
+ return rewriteValueMIPS64_OpMIPS64NEGV(v)
+ case OpMIPS64NOR:
+ return rewriteValueMIPS64_OpMIPS64NOR(v)
+ case OpMIPS64NORconst:
+ return rewriteValueMIPS64_OpMIPS64NORconst(v)
+ case OpMIPS64OR:
+ return rewriteValueMIPS64_OpMIPS64OR(v)
+ case OpMIPS64ORconst:
+ return rewriteValueMIPS64_OpMIPS64ORconst(v)
+ case OpMIPS64SGT:
+ return rewriteValueMIPS64_OpMIPS64SGT(v)
+ case OpMIPS64SGTU:
+ return rewriteValueMIPS64_OpMIPS64SGTU(v)
+ case OpMIPS64SGTUconst:
+ return rewriteValueMIPS64_OpMIPS64SGTUconst(v)
+ case OpMIPS64SGTconst:
+ return rewriteValueMIPS64_OpMIPS64SGTconst(v)
+ case OpMIPS64SLLV:
+ return rewriteValueMIPS64_OpMIPS64SLLV(v)
+ case OpMIPS64SLLVconst:
+ return rewriteValueMIPS64_OpMIPS64SLLVconst(v)
+ case OpMIPS64SRAV:
+ return rewriteValueMIPS64_OpMIPS64SRAV(v)
+ case OpMIPS64SRAVconst:
+ return rewriteValueMIPS64_OpMIPS64SRAVconst(v)
+ case OpMIPS64SRLV:
+ return rewriteValueMIPS64_OpMIPS64SRLV(v)
+ case OpMIPS64SRLVconst:
+ return rewriteValueMIPS64_OpMIPS64SRLVconst(v)
+ case OpMIPS64SUBV:
+ return rewriteValueMIPS64_OpMIPS64SUBV(v)
+ case OpMIPS64SUBVconst:
+ return rewriteValueMIPS64_OpMIPS64SUBVconst(v)
+ case OpMIPS64XOR:
+ return rewriteValueMIPS64_OpMIPS64XOR(v)
+ case OpMIPS64XORconst:
+ return rewriteValueMIPS64_OpMIPS64XORconst(v)
+ case OpMod16:
+ return rewriteValueMIPS64_OpMod16(v)
+ case OpMod16u:
+ return rewriteValueMIPS64_OpMod16u(v)
+ case OpMod32:
+ return rewriteValueMIPS64_OpMod32(v)
+ case OpMod32u:
+ return rewriteValueMIPS64_OpMod32u(v)
+ case OpMod64:
+ return rewriteValueMIPS64_OpMod64(v)
+ case OpMod64u:
+ return rewriteValueMIPS64_OpMod64u(v)
+ case OpMod8:
+ return rewriteValueMIPS64_OpMod8(v)
+ case OpMod8u:
+ return rewriteValueMIPS64_OpMod8u(v)
+ case OpMove:
+ return rewriteValueMIPS64_OpMove(v)
+ case OpMul16:
+ return rewriteValueMIPS64_OpMul16(v)
+ case OpMul32:
+ return rewriteValueMIPS64_OpMul32(v)
+ case OpMul32F:
+ v.Op = OpMIPS64MULF
+ return true
+ case OpMul64:
+ return rewriteValueMIPS64_OpMul64(v)
+ case OpMul64F:
+ v.Op = OpMIPS64MULD
+ return true
+ case OpMul64uhilo:
+ v.Op = OpMIPS64MULVU
+ return true
+ case OpMul8:
+ return rewriteValueMIPS64_OpMul8(v)
+ case OpNeg16:
+ v.Op = OpMIPS64NEGV
+ return true
+ case OpNeg32:
+ v.Op = OpMIPS64NEGV
+ return true
+ case OpNeg32F:
+ v.Op = OpMIPS64NEGF
+ return true
+ case OpNeg64:
+ v.Op = OpMIPS64NEGV
+ return true
+ case OpNeg64F:
+ v.Op = OpMIPS64NEGD
+ return true
+ case OpNeg8:
+ v.Op = OpMIPS64NEGV
+ return true
+ case OpNeq16:
+ return rewriteValueMIPS64_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValueMIPS64_OpNeq32(v)
+ case OpNeq32F:
+ return rewriteValueMIPS64_OpNeq32F(v)
+ case OpNeq64:
+ return rewriteValueMIPS64_OpNeq64(v)
+ case OpNeq64F:
+ return rewriteValueMIPS64_OpNeq64F(v)
+ case OpNeq8:
+ return rewriteValueMIPS64_OpNeq8(v)
+ case OpNeqB:
+ v.Op = OpMIPS64XOR
+ return true
+ case OpNeqPtr:
+ return rewriteValueMIPS64_OpNeqPtr(v)
+ case OpNilCheck:
+ v.Op = OpMIPS64LoweredNilCheck
+ return true
+ case OpNot:
+ return rewriteValueMIPS64_OpNot(v)
+ case OpOffPtr:
+ return rewriteValueMIPS64_OpOffPtr(v)
+ case OpOr16:
+ v.Op = OpMIPS64OR
+ return true
+ case OpOr32:
+ v.Op = OpMIPS64OR
+ return true
+ case OpOr64:
+ v.Op = OpMIPS64OR
+ return true
+ case OpOr8:
+ v.Op = OpMIPS64OR
+ return true
+ case OpOrB:
+ v.Op = OpMIPS64OR
+ return true
+ case OpPanicBounds:
+ return rewriteValueMIPS64_OpPanicBounds(v)
+ case OpRotateLeft16:
+ return rewriteValueMIPS64_OpRotateLeft16(v)
+ case OpRotateLeft32:
+ return rewriteValueMIPS64_OpRotateLeft32(v)
+ case OpRotateLeft64:
+ return rewriteValueMIPS64_OpRotateLeft64(v)
+ case OpRotateLeft8:
+ return rewriteValueMIPS64_OpRotateLeft8(v)
+ case OpRound32F:
+ v.Op = OpCopy
+ return true
+ case OpRound64F:
+ v.Op = OpCopy
+ return true
+ case OpRsh16Ux16:
+ return rewriteValueMIPS64_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValueMIPS64_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValueMIPS64_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValueMIPS64_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValueMIPS64_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValueMIPS64_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValueMIPS64_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValueMIPS64_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValueMIPS64_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValueMIPS64_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValueMIPS64_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValueMIPS64_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValueMIPS64_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValueMIPS64_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValueMIPS64_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValueMIPS64_OpRsh32x8(v)
+ case OpRsh64Ux16:
+ return rewriteValueMIPS64_OpRsh64Ux16(v)
+ case OpRsh64Ux32:
+ return rewriteValueMIPS64_OpRsh64Ux32(v)
+ case OpRsh64Ux64:
+ return rewriteValueMIPS64_OpRsh64Ux64(v)
+ case OpRsh64Ux8:
+ return rewriteValueMIPS64_OpRsh64Ux8(v)
+ case OpRsh64x16:
+ return rewriteValueMIPS64_OpRsh64x16(v)
+ case OpRsh64x32:
+ return rewriteValueMIPS64_OpRsh64x32(v)
+ case OpRsh64x64:
+ return rewriteValueMIPS64_OpRsh64x64(v)
+ case OpRsh64x8:
+ return rewriteValueMIPS64_OpRsh64x8(v)
+ case OpRsh8Ux16:
+ return rewriteValueMIPS64_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValueMIPS64_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValueMIPS64_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValueMIPS64_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValueMIPS64_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValueMIPS64_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValueMIPS64_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValueMIPS64_OpRsh8x8(v)
+ case OpSelect0:
+ return rewriteValueMIPS64_OpSelect0(v)
+ case OpSelect1:
+ return rewriteValueMIPS64_OpSelect1(v)
+ case OpSignExt16to32:
+ v.Op = OpMIPS64MOVHreg
+ return true
+ case OpSignExt16to64:
+ v.Op = OpMIPS64MOVHreg
+ return true
+ case OpSignExt32to64:
+ v.Op = OpMIPS64MOVWreg
+ return true
+ case OpSignExt8to16:
+ v.Op = OpMIPS64MOVBreg
+ return true
+ case OpSignExt8to32:
+ v.Op = OpMIPS64MOVBreg
+ return true
+ case OpSignExt8to64:
+ v.Op = OpMIPS64MOVBreg
+ return true
+ case OpSlicemask:
+ return rewriteValueMIPS64_OpSlicemask(v)
+ case OpSqrt:
+ v.Op = OpMIPS64SQRTD
+ return true
+ case OpStaticCall:
+ v.Op = OpMIPS64CALLstatic
+ return true
+ case OpStore:
+ return rewriteValueMIPS64_OpStore(v)
+ case OpSub16:
+ v.Op = OpMIPS64SUBV
+ return true
+ case OpSub32:
+ v.Op = OpMIPS64SUBV
+ return true
+ case OpSub32F:
+ v.Op = OpMIPS64SUBF
+ return true
+ case OpSub64:
+ v.Op = OpMIPS64SUBV
+ return true
+ case OpSub64F:
+ v.Op = OpMIPS64SUBD
+ return true
+ case OpSub8:
+ v.Op = OpMIPS64SUBV
+ return true
+ case OpSubPtr:
+ v.Op = OpMIPS64SUBV
+ return true
+ case OpTrunc16to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to32:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to8:
+ v.Op = OpCopy
+ return true
+ case OpWB:
+ v.Op = OpMIPS64LoweredWB
+ return true
+ case OpXor16:
+ v.Op = OpMIPS64XOR
+ return true
+ case OpXor32:
+ v.Op = OpMIPS64XOR
+ return true
+ case OpXor64:
+ v.Op = OpMIPS64XOR
+ return true
+ case OpXor8:
+ v.Op = OpMIPS64XOR
+ return true
+ case OpZero:
+ return rewriteValueMIPS64_OpZero(v)
+ case OpZeroExt16to32:
+ v.Op = OpMIPS64MOVHUreg
+ return true
+ case OpZeroExt16to64:
+ v.Op = OpMIPS64MOVHUreg
+ return true
+ case OpZeroExt32to64:
+ v.Op = OpMIPS64MOVWUreg
+ return true
+ case OpZeroExt8to16:
+ v.Op = OpMIPS64MOVBUreg
+ return true
+ case OpZeroExt8to32:
+ v.Op = OpMIPS64MOVBUreg
+ return true
+ case OpZeroExt8to64:
+ v.Op = OpMIPS64MOVBUreg
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Addr {sym} base)
+ // result: (MOVVaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpMIPS64MOVVaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpAvg64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Avg64u <t> x y)
+ // result: (ADDV (SRLVconst <t> (SUBV <t> x y) [1]) y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64ADDV)
+ v0 := b.NewValue0(v.Pos, OpMIPS64SRLVconst, t)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SUBV, t)
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpCom16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Com16 x)
+ // result: (NOR (MOVVconst [0]) x)
+ for {
+ x := v_0
+ v.reset(OpMIPS64NOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpCom32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Com32 x)
+ // result: (NOR (MOVVconst [0]) x)
+ for {
+ x := v_0
+ v.reset(OpMIPS64NOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpCom64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Com64 x)
+ // result: (NOR (MOVVconst [0]) x)
+ for {
+ x := v_0
+ v.reset(OpMIPS64NOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpCom8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Com8 x)
+ // result: (NOR (MOVVconst [0]) x)
+ for {
+ x := v_0
+ v.reset(OpMIPS64NOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpConst16(v *Value) bool {
+ // match: (Const16 [val])
+ // result: (MOVVconst [int64(val)])
+ for {
+ val := auxIntToInt16(v.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueMIPS64_OpConst32(v *Value) bool {
+ // match: (Const32 [val])
+ // result: (MOVVconst [int64(val)])
+ for {
+ val := auxIntToInt32(v.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueMIPS64_OpConst32F(v *Value) bool {
+ // match: (Const32F [val])
+ // result: (MOVFconst [float64(val)])
+ for {
+ val := auxIntToFloat32(v.AuxInt)
+ v.reset(OpMIPS64MOVFconst)
+ v.AuxInt = float64ToAuxInt(float64(val))
+ return true
+ }
+}
+func rewriteValueMIPS64_OpConst64(v *Value) bool {
+ // match: (Const64 [val])
+ // result: (MOVVconst [int64(val)])
+ for {
+ val := auxIntToInt64(v.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueMIPS64_OpConst64F(v *Value) bool {
+ // match: (Const64F [val])
+ // result: (MOVDconst [float64(val)])
+ for {
+ val := auxIntToFloat64(v.AuxInt)
+ v.reset(OpMIPS64MOVDconst)
+ v.AuxInt = float64ToAuxInt(float64(val))
+ return true
+ }
+}
+func rewriteValueMIPS64_OpConst8(v *Value) bool {
+ // match: (Const8 [val])
+ // result: (MOVVconst [int64(val)])
+ for {
+ val := auxIntToInt8(v.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueMIPS64_OpConstBool(v *Value) bool {
+ // match: (ConstBool [b])
+ // result: (MOVVconst [int64(b2i(b))])
+ for {
+ b := auxIntToBool(v.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(b2i(b)))
+ return true
+ }
+}
+func rewriteValueMIPS64_OpConstNil(v *Value) bool {
+ // match: (ConstNil)
+ // result: (MOVVconst [0])
+ for {
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpDiv16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16 x y)
+ // result: (Select1 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVV, types.NewTuple(typ.Int64, typ.Int64))
+ v1 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpDiv16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16u x y)
+ // result: (Select1 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpDiv32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32 x y)
+ // result: (Select1 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVV, types.NewTuple(typ.Int64, typ.Int64))
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpDiv32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32u x y)
+ // result: (Select1 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpDiv64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div64 x y)
+ // result: (Select1 (DIVV x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVV, types.NewTuple(typ.Int64, typ.Int64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpDiv64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div64u x y)
+ // result: (Select1 (DIVVU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 x y)
+ // result: (Select1 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVV, types.NewTuple(typ.Int64, typ.Int64))
+ v1 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u x y)
+ // result: (Select1 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq16 x y)
+ // result: (SGTU (MOVVconst [1]) (XOR (ZeroExt16to64 x) (ZeroExt16to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq32 x y)
+ // result: (SGTU (MOVVconst [1]) (XOR (ZeroExt32to64 x) (ZeroExt32to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpEq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32F x y)
+ // result: (FPFlagTrue (CMPEQF x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64FPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPS64CMPEQF, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpEq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq64 x y)
+ // result: (SGTU (MOVVconst [1]) (XOR x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.UInt64)
+ v1.AddArg2(x, y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpEq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64F x y)
+ // result: (FPFlagTrue (CMPEQD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64FPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPS64CMPEQD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq8 x y)
+ // result: (SGTU (MOVVconst [1]) (XOR (ZeroExt8to64 x) (ZeroExt8to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpEqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqB x y)
+ // result: (XOR (MOVVconst [1]) (XOR <typ.Bool> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64XOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.Bool)
+ v1.AddArg2(x, y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpEqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqPtr x y)
+ // result: (SGTU (MOVVconst [1]) (XOR x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.UInt64)
+ v1.AddArg2(x, y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpHmul32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul32 x y)
+ // result: (SRAVconst (Select1 <typ.Int64> (MULV (SignExt32to64 x) (SignExt32to64 y))) [32])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAVconst)
+ v.AuxInt = int64ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpSelect1, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MULV, types.NewTuple(typ.Int64, typ.Int64))
+ v2 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpHmul32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul32u x y)
+ // result: (SRLVconst (Select1 <typ.UInt64> (MULVU (ZeroExt32to64 x) (ZeroExt32to64 y))) [32])
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRLVconst)
+ v.AuxInt = int64ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpHmul64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul64 x y)
+ // result: (Select0 (MULV x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MULV, types.NewTuple(typ.Int64, typ.Int64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpHmul64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul64u x y)
+ // result: (Select0 (MULVU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpIsInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (IsInBounds idx len)
+ // result: (SGTU len idx)
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpMIPS64SGTU)
+ v.AddArg2(len, idx)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (IsNonNil ptr)
+ // result: (SGTU ptr (MOVVconst [0]))
+ for {
+ ptr := v_0
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(ptr, v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpIsSliceInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (IsSliceInBounds idx len)
+ // result: (XOR (MOVVconst [1]) (SGTU idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpMIPS64XOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v1.AddArg2(idx, len)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16 x y)
+ // result: (XOR (MOVVconst [1]) (SGT (SignExt16to64 x) (SignExt16to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64XOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGT, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16U x y)
+ // result: (XOR (MOVVconst [1]) (SGTU (ZeroExt16to64 x) (ZeroExt16to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64XOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32 x y)
+ // result: (XOR (MOVVconst [1]) (SGT (SignExt32to64 x) (SignExt32to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64XOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGT, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32F x y)
+ // result: (FPFlagTrue (CMPGEF y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64FPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPS64CMPGEF, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32U x y)
+ // result: (XOR (MOVVconst [1]) (SGTU (ZeroExt32to64 x) (ZeroExt32to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64XOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq64 x y)
+ // result: (XOR (MOVVconst [1]) (SGT x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64XOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGT, typ.Bool)
+ v1.AddArg2(x, y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64F x y)
+ // result: (FPFlagTrue (CMPGED y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64FPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPS64CMPGED, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLeq64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq64U x y)
+ // result: (XOR (MOVVconst [1]) (SGTU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64XOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v1.AddArg2(x, y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8 x y)
+ // result: (XOR (MOVVconst [1]) (SGT (SignExt8to64 x) (SignExt8to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64XOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGT, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8U x y)
+ // result: (XOR (MOVVconst [1]) (SGTU (ZeroExt8to64 x) (ZeroExt8to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64XOR)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16 x y)
+ // result: (SGT (SignExt16to64 y) (SignExt16to64 x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGT)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16U x y)
+ // result: (SGTU (ZeroExt16to64 y) (ZeroExt16to64 x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less32 x y)
+ // result: (SGT (SignExt32to64 y) (SignExt32to64 x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGT)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLess32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32F x y)
+ // result: (FPFlagTrue (CMPGTF y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64FPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPS64CMPGTF, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less32U x y)
+ // result: (SGTU (ZeroExt32to64 y) (ZeroExt32to64 x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLess64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less64 x y)
+ // result: (SGT y x)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGT)
+ v.AddArg2(y, x)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLess64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64F x y)
+ // result: (FPFlagTrue (CMPGTD y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64FPFlagTrue)
+ v0 := b.NewValue0(v.Pos, OpMIPS64CMPGTD, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLess64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less64U x y)
+ // result: (SGTU y x)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v.AddArg2(y, x)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8 x y)
+ // result: (SGT (SignExt8to64 y) (SignExt8to64 x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGT)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8U x y)
+ // result: (SGTU (ZeroExt8to64 y) (ZeroExt8to64 x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(y)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Load <t> ptr mem)
+ // cond: t.IsBoolean()
+ // result: (MOVBUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsBoolean()) {
+ break
+ }
+ v.reset(OpMIPS64MOVBUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is8BitInt(t) && isSigned(t))
+ // result: (MOVBload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpMIPS64MOVBload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is8BitInt(t) && !isSigned(t))
+ // result: (MOVBUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpMIPS64MOVBUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is16BitInt(t) && isSigned(t))
+ // result: (MOVHload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpMIPS64MOVHload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is16BitInt(t) && !isSigned(t))
+ // result: (MOVHUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpMIPS64MOVHUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is32BitInt(t) && isSigned(t))
+ // result: (MOVWload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpMIPS64MOVWload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is32BitInt(t) && !isSigned(t))
+ // result: (MOVWUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpMIPS64MOVWUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (MOVVload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitFloat(t)
+ // result: (MOVFload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(OpMIPS64MOVFload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitFloat(t)
+ // result: (MOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(OpMIPS64MOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpLocalAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LocalAddr {sym} base _)
+ // result: (MOVVaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpMIPS64MOVVaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x16 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x32 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x64 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v1.AddArg2(v2, y)
+ v0.AddArg(v1)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v3.AddArg2(x, y)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x8 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x16 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x32 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x64 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v1.AddArg2(v2, y)
+ v0.AddArg(v1)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v3.AddArg2(x, y)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x8 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x16 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x32 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x64 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v1.AddArg2(v2, y)
+ v0.AddArg(v1)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v3.AddArg2(x, y)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x8 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x16 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x32 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x64 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v1.AddArg2(v2, y)
+ v0.AddArg(v1)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v3.AddArg2(x, y)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x8 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SLLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMIPS64ADDV(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDV x (MOVVconst [c]))
+ // cond: is32Bit(c)
+ // result: (ADDVconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpMIPS64ADDVconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDV x (NEGV y))
+ // result: (SUBV x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPS64NEGV {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpMIPS64SUBV)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64ADDVconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDVconst [off1] (MOVVaddr [off2] {sym} ptr))
+ // cond: is32Bit(off1+int64(off2))
+ // result: (MOVVaddr [int32(off1)+int32(off2)] {sym} ptr)
+ for {
+ off1 := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ if !(is32Bit(off1 + int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVVaddr)
+ v.AuxInt = int32ToAuxInt(int32(off1) + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (ADDVconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ADDVconst [c] (MOVVconst [d]))
+ // result: (MOVVconst [c+d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(c + d)
+ return true
+ }
+ // match: (ADDVconst [c] (ADDVconst [d] x))
+ // cond: is32Bit(c+d)
+ // result: (ADDVconst [c+d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(c + d)) {
+ break
+ }
+ v.reset(OpMIPS64ADDVconst)
+ v.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDVconst [c] (SUBVconst [d] x))
+ // cond: is32Bit(c-d)
+ // result: (ADDVconst [c-d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64SUBVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(c - d)) {
+ break
+ }
+ v.reset(OpMIPS64ADDVconst)
+ v.AuxInt = int64ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64AND(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AND x (MOVVconst [c]))
+ // cond: is32Bit(c)
+ // result: (ANDconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpMIPS64ANDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64ANDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ANDconst [0] _)
+ // result: (MOVVconst [0])
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ANDconst [-1] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVVconst [d]))
+ // result: (MOVVconst [c&d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(c & d)
+ return true
+ }
+ // match: (ANDconst [c] (ANDconst [d] x))
+ // result: (ANDconst [c&d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64ANDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpMIPS64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64LoweredAtomicAdd32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LoweredAtomicAdd32 ptr (MOVVconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (LoweredAtomicAddconst32 [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpMIPS64LoweredAtomicAddconst32)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64LoweredAtomicAdd64(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LoweredAtomicAdd64 ptr (MOVVconst [c]) mem)
+ // cond: is32Bit(c)
+ // result: (LoweredAtomicAddconst64 [c] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpMIPS64LoweredAtomicAddconst64)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64LoweredAtomicStore32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LoweredAtomicStore32 ptr (MOVVconst [0]) mem)
+ // result: (LoweredAtomicStorezero32 ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpMIPS64LoweredAtomicStorezero32)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64LoweredAtomicStore64(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LoweredAtomicStore64 ptr (MOVVconst [0]) mem)
+ // result: (LoweredAtomicStorezero64 ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpMIPS64LoweredAtomicStorezero64)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVBUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBUload [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVBUload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBUload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVBUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVBUreg x:(MOVBUload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBUload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg x:(MOVBUreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBUreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg (MOVVconst [c]))
+ // result: (MOVVconst [int64(uint8(c))])
+ for {
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVBload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBload [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVBload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVBreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVBreg x:(MOVBload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg x:(MOVBreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (MOVVconst [c]))
+ // result: (MOVVconst [int64(int8(c))])
+ for {
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(int8(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVBstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstore [off1] {sym} (ADDVconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVBstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVVconst [0]) mem)
+ // result: (MOVBstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpMIPS64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVBreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVBUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVHUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVWUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVWUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVBstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstorezero [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVBstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBstorezero [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDload [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVDload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVDload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstore [off1] {sym} (ADDVconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVDstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVDstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVFload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVFload [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVFload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVFload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVFload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVFload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVFload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVFstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVFstore [off1] {sym} (ADDVconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVFstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVFstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVFstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVFstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVFstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVHUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHUload [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVHUload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVHUload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVHUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVHUreg x:(MOVBUload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBUload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVHUload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVBUreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBUreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVHUreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg (MOVVconst [c]))
+ // result: (MOVVconst [int64(uint16(c))])
+ for {
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVHload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHload [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVHload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVHload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVHreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVHreg x:(MOVBload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBUload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVHload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBUreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVHreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (MOVVconst [c]))
+ // result: (MOVVconst [int64(int16(c))])
+ for {
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(int16(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVHstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstore [off1] {sym} (ADDVconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVHstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVHstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVVconst [0]) mem)
+ // result: (MOVHstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpMIPS64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHUreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVHUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVWUreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVWUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVHstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstorezero [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVHstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVHstorezero [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVVload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVVload [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVVload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVVload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVVload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVVload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVVreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVVreg x)
+ // cond: x.Uses == 1
+ // result: (MOVVnop x)
+ for {
+ x := v_0
+ if !(x.Uses == 1) {
+ break
+ }
+ v.reset(OpMIPS64MOVVnop)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVVreg (MOVVconst [c]))
+ // result: (MOVVconst [c])
+ for {
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(c)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVVstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVVstore [off1] {sym} (ADDVconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVVstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVVstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVVstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVVstore [off] {sym} ptr (MOVVconst [0]) mem)
+ // result: (MOVVstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpMIPS64MOVVstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVVstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVVstorezero [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVVstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVVstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVVstorezero [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVWUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWUload [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVWUload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVWUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWUload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVWUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVWUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVWUreg x:(MOVBUload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBUload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVHUload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVHUload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVWUload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVWUload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVBUreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBUreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVHUreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVHUreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVWUreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVWUreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg (MOVVconst [c]))
+ // result: (MOVVconst [int64(uint32(c))])
+ for {
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVWload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWload [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVWload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWload [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVWreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVWreg x:(MOVBload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBUload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBUload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVHload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHUload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVHUload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWload _ _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVWload {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBUreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVBUreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVHreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWreg _))
+ // result: (MOVVreg x)
+ for {
+ x := v_0
+ if x.Op != OpMIPS64MOVWreg {
+ break
+ }
+ v.reset(OpMIPS64MOVVreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg (MOVVconst [c]))
+ // result: (MOVVconst [int64(int32(c))])
+ for {
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVWstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstore [off1] {sym} (ADDVconst [off2] ptr) val mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVWstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWstore [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVVconst [0]) mem)
+ // result: (MOVWstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpMIPS64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWUreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpMIPS64MOVWUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpMIPS64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64MOVWstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstorezero [off1] {sym} (ADDVconst [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVWstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWstorezero [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpMIPS64MOVVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64NEGV(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEGV (MOVVconst [c]))
+ // result: (MOVVconst [-c])
+ for {
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(-c)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64NOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (NOR x (MOVVconst [c]))
+ // cond: is32Bit(c)
+ // result: (NORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpMIPS64NORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64NORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NORconst [c] (MOVVconst [d]))
+ // result: (MOVVconst [^(c|d)])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(^(c | d))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64OR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (OR x (MOVVconst [c]))
+ // cond: is32Bit(c)
+ // result: (ORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpMIPS64ORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (OR x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64ORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORconst [-1] _)
+ // result: (MOVVconst [-1])
+ for {
+ if auxIntToInt64(v.AuxInt) != -1 {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (ORconst [c] (MOVVconst [d]))
+ // result: (MOVVconst [c|d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(c | d)
+ return true
+ }
+ // match: (ORconst [c] (ORconst [d] x))
+ // cond: is32Bit(c|d)
+ // result: (ORconst [c|d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64ORconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(c | d)) {
+ break
+ }
+ v.reset(OpMIPS64ORconst)
+ v.AuxInt = int64ToAuxInt(c | d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SGT(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SGT (MOVVconst [c]) x)
+ // cond: is32Bit(c)
+ // result: (SGTconst [c] x)
+ for {
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpMIPS64SGTconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SGTU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SGTU (MOVVconst [c]) x)
+ // cond: is32Bit(c)
+ // result: (SGTUconst [c] x)
+ for {
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpMIPS64SGTUconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SGTUconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SGTUconst [c] (MOVVconst [d]))
+ // cond: uint64(c)>uint64(d)
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ if !(uint64(c) > uint64(d)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (SGTUconst [c] (MOVVconst [d]))
+ // cond: uint64(c)<=uint64(d)
+ // result: (MOVVconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ if !(uint64(c) <= uint64(d)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SGTUconst [c] (MOVBUreg _))
+ // cond: 0xff < uint64(c)
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVBUreg || !(0xff < uint64(c)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (SGTUconst [c] (MOVHUreg _))
+ // cond: 0xffff < uint64(c)
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVHUreg || !(0xffff < uint64(c)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (SGTUconst [c] (ANDconst [m] _))
+ // cond: uint64(m) < uint64(c)
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64ANDconst {
+ break
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ if !(uint64(m) < uint64(c)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (SGTUconst [c] (SRLVconst _ [d]))
+ // cond: 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c)
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64SRLVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ if !(0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SGTconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SGTconst [c] (MOVVconst [d]))
+ // cond: c>d
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ if !(c > d) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (MOVVconst [d]))
+ // cond: c<=d
+ // result: (MOVVconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ if !(c <= d) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (MOVBreg _))
+ // cond: 0x7f < c
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVBreg || !(0x7f < c) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (MOVBreg _))
+ // cond: c <= -0x80
+ // result: (MOVVconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVBreg || !(c <= -0x80) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (MOVBUreg _))
+ // cond: 0xff < c
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVBUreg || !(0xff < c) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (MOVBUreg _))
+ // cond: c < 0
+ // result: (MOVVconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVBUreg || !(c < 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (MOVHreg _))
+ // cond: 0x7fff < c
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVHreg || !(0x7fff < c) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (MOVHreg _))
+ // cond: c <= -0x8000
+ // result: (MOVVconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVHreg || !(c <= -0x8000) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (MOVHUreg _))
+ // cond: 0xffff < c
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVHUreg || !(0xffff < c) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (MOVHUreg _))
+ // cond: c < 0
+ // result: (MOVVconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVHUreg || !(c < 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (MOVWUreg _))
+ // cond: c < 0
+ // result: (MOVVconst [0])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVWUreg || !(c < 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SGTconst [c] (ANDconst [m] _))
+ // cond: 0 <= m && m < c
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64ANDconst {
+ break
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ if !(0 <= m && m < c) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (SGTconst [c] (SRLVconst _ [d]))
+ // cond: 0 <= c && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c)
+ // result: (MOVVconst [1])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64SRLVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ if !(0 <= c && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SLLV(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SLLV _ (MOVVconst [c]))
+ // cond: uint64(c)>=64
+ // result: (MOVVconst [0])
+ for {
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SLLV x (MOVVconst [c]))
+ // result: (SLLVconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpMIPS64SLLVconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SLLVconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SLLVconst [c] (MOVVconst [d]))
+ // result: (MOVVconst [d<<uint64(c)])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(d << uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SRAV(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRAV x (MOVVconst [c]))
+ // cond: uint64(c)>=64
+ // result: (SRAVconst x [63])
+ for {
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpMIPS64SRAVconst)
+ v.AuxInt = int64ToAuxInt(63)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAV x (MOVVconst [c]))
+ // result: (SRAVconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpMIPS64SRAVconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SRAVconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRAVconst [c] (MOVVconst [d]))
+ // result: (MOVVconst [d>>uint64(c)])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(d >> uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SRLV(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRLV _ (MOVVconst [c]))
+ // cond: uint64(c)>=64
+ // result: (MOVVconst [0])
+ for {
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SRLV x (MOVVconst [c]))
+ // result: (SRLVconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpMIPS64SRLVconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SRLVconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRLVconst [c] (MOVVconst [d]))
+ // result: (MOVVconst [int64(uint64(d)>>uint64(c))])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(d) >> uint64(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SUBV(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBV x (MOVVconst [c]))
+ // cond: is32Bit(c)
+ // result: (SUBVconst [c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpMIPS64SUBVconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBV x x)
+ // result: (MOVVconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SUBV (MOVVconst [0]) x)
+ // result: (NEGV x)
+ for {
+ if v_0.Op != OpMIPS64MOVVconst || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpMIPS64NEGV)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64SUBVconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SUBVconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUBVconst [c] (MOVVconst [d]))
+ // result: (MOVVconst [d-c])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(d - c)
+ return true
+ }
+ // match: (SUBVconst [c] (SUBVconst [d] x))
+ // cond: is32Bit(-c-d)
+ // result: (ADDVconst [-c-d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64SUBVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(-c - d)) {
+ break
+ }
+ v.reset(OpMIPS64ADDVconst)
+ v.AuxInt = int64ToAuxInt(-c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBVconst [c] (ADDVconst [d] x))
+ // cond: is32Bit(-c+d)
+ // result: (ADDVconst [-c+d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64ADDVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(-c + d)) {
+ break
+ }
+ v.reset(OpMIPS64ADDVconst)
+ v.AuxInt = int64ToAuxInt(-c + d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64XOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XOR x (MOVVconst [c]))
+ // cond: is32Bit(c)
+ // result: (XORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpMIPS64XORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR x x)
+ // result: (MOVVconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMIPS64XORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (XORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (XORconst [-1] x)
+ // result: (NORconst [0] x)
+ for {
+ if auxIntToInt64(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.reset(OpMIPS64NORconst)
+ v.AuxInt = int64ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORconst [c] (MOVVconst [d]))
+ // result: (MOVVconst [c^d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(c ^ d)
+ return true
+ }
+ // match: (XORconst [c] (XORconst [d] x))
+ // cond: is32Bit(c^d)
+ // result: (XORconst [c^d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpMIPS64XORconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(c ^ d)) {
+ break
+ }
+ v.reset(OpMIPS64XORconst)
+ v.AuxInt = int64ToAuxInt(c ^ d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMod16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16 x y)
+ // result: (Select0 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVV, types.NewTuple(typ.Int64, typ.Int64))
+ v1 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMod16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16u x y)
+ // result: (Select0 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMod32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32 x y)
+ // result: (Select0 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVV, types.NewTuple(typ.Int64, typ.Int64))
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMod32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32u x y)
+ // result: (Select0 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMod64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod64 x y)
+ // result: (Select0 (DIVV x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVV, types.NewTuple(typ.Int64, typ.Int64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMod64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod64u x y)
+ // result: (Select0 (DIVVU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8 x y)
+ // result: (Select0 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVV, types.NewTuple(typ.Int64, typ.Int64))
+ v1 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8u x y)
+ // result: (Select0 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpMIPS64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Move [0] _ _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Move [1] dst src mem)
+ // result: (MOVBstore dst (MOVBload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpMIPS64MOVBstore)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVBload, typ.Int8)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore dst (MOVHload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVHload, typ.Int16)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] dst src mem)
+ // result: (MOVBstore [1] dst (MOVBload [1] src mem) (MOVBstore dst (MOVBload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVBload, typ.Int8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVBload, typ.Int8)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [4] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore dst (MOVWload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstore)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVWload, typ.Int32)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [4] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVHload, typ.Int16)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVHload, typ.Int16)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [4] dst src mem)
+ // result: (MOVBstore [3] dst (MOVBload [3] src mem) (MOVBstore [2] dst (MOVBload [2] src mem) (MOVBstore [1] dst (MOVBload [1] src mem) (MOVBstore dst (MOVBload src mem) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVBload, typ.Int8)
+ v0.AuxInt = int32ToAuxInt(3)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVBload, typ.Int8)
+ v2.AuxInt = int32ToAuxInt(2)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVBload, typ.Int8)
+ v4.AuxInt = int32ToAuxInt(1)
+ v4.AddArg2(src, mem)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v6 := b.NewValue0(v.Pos, OpMIPS64MOVBload, typ.Int8)
+ v6.AddArg2(src, mem)
+ v5.AddArg3(dst, v6, mem)
+ v3.AddArg3(dst, v4, v5)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [8] {t} dst src mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVVstore dst (MOVVload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstore)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVload, typ.UInt64)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [8] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [4] dst (MOVWload [4] src mem) (MOVWstore dst (MOVWload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVWload, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVWload, typ.Int32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [8] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [6] dst (MOVHload [6] src mem) (MOVHstore [4] dst (MOVHload [4] src mem) (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVHload, typ.Int16)
+ v0.AuxInt = int32ToAuxInt(6)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVHload, typ.Int16)
+ v2.AuxInt = int32ToAuxInt(4)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(2)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVHload, typ.Int16)
+ v4.AuxInt = int32ToAuxInt(2)
+ v4.AddArg2(src, mem)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v6 := b.NewValue0(v.Pos, OpMIPS64MOVHload, typ.Int16)
+ v6.AddArg2(src, mem)
+ v5.AddArg3(dst, v6, mem)
+ v3.AddArg3(dst, v4, v5)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [3] dst src mem)
+ // result: (MOVBstore [2] dst (MOVBload [2] src mem) (MOVBstore [1] dst (MOVBload [1] src mem) (MOVBstore dst (MOVBload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVBload, typ.Int8)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVBload, typ.Int8)
+ v2.AuxInt = int32ToAuxInt(1)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVBload, typ.Int8)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [6] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [4] dst (MOVHload [4] src mem) (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVHload, typ.Int16)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVHload, typ.Int16)
+ v2.AuxInt = int32ToAuxInt(2)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVHload, typ.Int16)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [12] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [8] dst (MOVWload [8] src mem) (MOVWstore [4] dst (MOVWload [4] src mem) (MOVWstore dst (MOVWload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVWload, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVWload, typ.Int32)
+ v2.AuxInt = int32ToAuxInt(4)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVWstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVWload, typ.Int32)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [16] {t} dst src mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVVstore [8] dst (MOVVload [8] src mem) (MOVVstore dst (MOVVload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVVstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVload, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [24] {t} dst src mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVVstore [16] dst (MOVVload [16] src mem) (MOVVstore [8] dst (MOVVload [8] src mem) (MOVVstore dst (MOVVload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstore)
+ v.AuxInt = int32ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(16)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVVstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVload, typ.UInt64)
+ v2.AuxInt = int32ToAuxInt(8)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVVstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVVload, typ.UInt64)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] {t} dst src mem)
+ // cond: s%8 == 0 && s >= 24 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
+ // result: (DUFFCOPY [16 * (128 - s/8)] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s%8 == 0 && s >= 24 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpMIPS64DUFFCOPY)
+ v.AuxInt = int64ToAuxInt(16 * (128 - s/8))
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (Move [s] {t} dst src mem)
+ // cond: s > 24 && logLargeCopy(v, s) || t.Alignment()%8 != 0
+ // result: (LoweredMove [t.Alignment()] dst src (ADDVconst <src.Type> src [s-moveSize(t.Alignment(), config)]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 24 && logLargeCopy(v, s) || t.Alignment()%8 != 0) {
+ break
+ }
+ v.reset(OpMIPS64LoweredMove)
+ v.AuxInt = int64ToAuxInt(t.Alignment())
+ v0 := b.NewValue0(v.Pos, OpMIPS64ADDVconst, src.Type)
+ v0.AuxInt = int64ToAuxInt(s - moveSize(t.Alignment(), config))
+ v0.AddArg(src)
+ v.AddArg4(dst, src, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpMul16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul16 x y)
+ // result: (Select1 (MULVU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMul32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul32 x y)
+ // result: (Select1 (MULVU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMul64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul64 x y)
+ // result: (Select1 (MULVU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpMul8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul8 x y)
+ // result: (Select1 (MULVU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq16 x y)
+ // result: (SGTU (XOR (ZeroExt16to32 x) (ZeroExt16to64 y)) (MOVVconst [0]))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq32 x y)
+ // result: (SGTU (XOR (ZeroExt32to64 x) (ZeroExt32to64 y)) (MOVVconst [0]))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpNeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32F x y)
+ // result: (FPFlagFalse (CMPEQF x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64FPFlagFalse)
+ v0 := b.NewValue0(v.Pos, OpMIPS64CMPEQF, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpNeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq64 x y)
+ // result: (SGTU (XOR x y) (MOVVconst [0]))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.UInt64)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpNeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64F x y)
+ // result: (FPFlagFalse (CMPEQD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64FPFlagFalse)
+ v0 := b.NewValue0(v.Pos, OpMIPS64CMPEQD, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq8 x y)
+ // result: (SGTU (XOR (ZeroExt8to64 x) (ZeroExt8to64 y)) (MOVVconst [0]))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpNeqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (NeqPtr x y)
+ // result: (SGTU (XOR x y) (MOVVconst [0]))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SGTU)
+ v0 := b.NewValue0(v.Pos, OpMIPS64XOR, typ.UInt64)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpNot(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Not x)
+ // result: (XORconst [1] x)
+ for {
+ x := v_0
+ v.reset(OpMIPS64XORconst)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpOffPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (OffPtr [off] ptr:(SP))
+ // cond: is32Bit(off)
+ // result: (MOVVaddr [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ if ptr.Op != OpSP || !(is32Bit(off)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVaddr)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (OffPtr [off] ptr)
+ // result: (ADDVconst [off] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ v.reset(OpMIPS64ADDVconst)
+ v.AuxInt = int64ToAuxInt(off)
+ v.AddArg(ptr)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpPanicBounds(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicBoundsA [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(OpMIPS64LoweredPanicBoundsA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicBoundsB [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(OpMIPS64LoweredPanicBoundsB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicBoundsC [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(OpMIPS64LoweredPanicBoundsC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpRotateLeft16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft16 <t> x (MOVVconst [c]))
+ // result: (Or16 (Lsh16x64 <t> x (MOVVconst [c&15])) (Rsh16Ux64 <t> x (MOVVconst [-c&15])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpLsh16x64, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c & 15)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh16Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(-c & 15)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpRotateLeft32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft32 <t> x (MOVVconst [c]))
+ // result: (Or32 (Lsh32x64 <t> x (MOVVconst [c&31])) (Rsh32Ux64 <t> x (MOVVconst [-c&31])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr32)
+ v0 := b.NewValue0(v.Pos, OpLsh32x64, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c & 31)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh32Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(-c & 31)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpRotateLeft64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft64 <t> x (MOVVconst [c]))
+ // result: (Or64 (Lsh64x64 <t> x (MOVVconst [c&63])) (Rsh64Ux64 <t> x (MOVVconst [-c&63])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr64)
+ v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c & 63)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh64Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(-c & 63)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpRotateLeft8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft8 <t> x (MOVVconst [c]))
+ // result: (Or8 (Lsh8x64 <t> x (MOVVconst [c&7])) (Rsh8Ux64 <t> x (MOVVconst [-c&7])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpLsh8x64, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c & 7)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh8Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(-c & 7)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux16 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v5 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v5.AddArg(x)
+ v4.AddArg2(v5, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux32 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v5 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v5.AddArg(x)
+ v4.AddArg2(v5, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux64 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt16to64 x) y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v1.AddArg2(v2, y)
+ v0.AddArg(v1)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(x)
+ v3.AddArg2(v4, y)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux8 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v5 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v5.AddArg(x)
+ v4.AddArg2(v5, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x16 <t> x y)
+ // result: (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x32 <t> x y)
+ // result: (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x64 <t> x y)
+ // result: (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(y, v4)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x8 <t> x y)
+ // result: (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux16 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v5 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v5.AddArg(x)
+ v4.AddArg2(v5, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux32 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v5 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v5.AddArg(x)
+ v4.AddArg2(v5, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux64 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt32to64 x) y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v1.AddArg2(v2, y)
+ v0.AddArg(v1)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(x)
+ v3.AddArg2(v4, y)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux8 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v5 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v5.AddArg(x)
+ v4.AddArg2(v5, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x16 <t> x y)
+ // result: (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x32 <t> x y)
+ // result: (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x64 <t> x y)
+ // result: (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(y, v4)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x8 <t> x y)
+ // result: (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh64Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux16 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> x (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh64Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux32 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> x (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh64Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux64 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> x y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v1.AddArg2(v2, y)
+ v0.AddArg(v1)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v3.AddArg2(x, y)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh64Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux8 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> x (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v4.AddArg2(x, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x16 <t> x y)
+ // result: (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(63)
+ v2.AddArg2(v3, v4)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x32 <t> x y)
+ // result: (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(63)
+ v2.AddArg2(v3, v4)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x64 <t> x y)
+ // result: (SRAV x (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(63)
+ v2.AddArg2(y, v3)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x8 <t> x y)
+ // result: (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(63)
+ v2.AddArg2(v3, v4)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux16 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v5 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v5.AddArg(x)
+ v4.AddArg2(v5, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux32 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v5 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v5.AddArg(x)
+ v4.AddArg2(v5, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux64 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt8to64 x) y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v1.AddArg2(v2, y)
+ v0.AddArg(v1)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(x)
+ v3.AddArg2(v4, y)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux8 <t> x y)
+ // result: (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64AND)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v1 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v0.AddArg(v1)
+ v4 := b.NewValue0(v.Pos, OpMIPS64SRLV, t)
+ v5 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v5.AddArg(x)
+ v4.AddArg2(v5, v3)
+ v.AddArg2(v0, v4)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x16 <t> x y)
+ // result: (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x32 <t> x y)
+ // result: (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x64 <t> x y)
+ // result: (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(y, v4)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x8 <t> x y)
+ // result: (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpMIPS64SRAV)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpMIPS64OR, t)
+ v2 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v3 := b.NewValue0(v.Pos, OpMIPS64SGTU, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(63)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v1.AddArg2(v2, v4)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpSelect0(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select0 (Mul64uover x y))
+ // result: (Select1 <typ.UInt64> (MULVU x y))
+ for {
+ if v_0.Op != OpMul64uover {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpSelect1)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpMIPS64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select0 (DIVVU _ (MOVVconst [1])))
+ // result: (MOVVconst [0])
+ for {
+ if v_0.Op != OpMIPS64DIVVU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Select0 (DIVVU x (MOVVconst [c])))
+ // cond: isPowerOfTwo64(c)
+ // result: (ANDconst [c-1] x)
+ for {
+ if v_0.Op != OpMIPS64DIVVU {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpMIPS64ANDconst)
+ v.AuxInt = int64ToAuxInt(c - 1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Select0 (DIVV (MOVVconst [c]) (MOVVconst [d])))
+ // cond: d != 0
+ // result: (MOVVconst [c%d])
+ for {
+ if v_0.Op != OpMIPS64DIVV {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(c % d)
+ return true
+ }
+ // match: (Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d])))
+ // cond: d != 0
+ // result: (MOVVconst [int64(uint64(c)%uint64(d))])
+ for {
+ if v_0.Op != OpMIPS64DIVVU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpSelect1(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select1 (Mul64uover x y))
+ // result: (SGTU <typ.Bool> (Select0 <typ.UInt64> (MULVU x y)) (MOVVconst <typ.UInt64> [0]))
+ for {
+ if v_0.Op != OpMul64uover {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpMIPS64SGTU)
+ v.Type = typ.Bool
+ v0 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (Select1 (MULVU x (MOVVconst [-1])))
+ // result: (NEGV x)
+ for {
+ if v_0.Op != OpMIPS64MULVU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != -1 {
+ continue
+ }
+ v.reset(OpMIPS64NEGV)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Select1 (MULVU _ (MOVVconst [0])))
+ // result: (MOVVconst [0])
+ for {
+ if v_0.Op != OpMIPS64MULVU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (Select1 (MULVU x (MOVVconst [1])))
+ // result: x
+ for {
+ if v_0.Op != OpMIPS64MULVU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 1 {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Select1 (MULVU x (MOVVconst [c])))
+ // cond: isPowerOfTwo64(c)
+ // result: (SLLVconst [log64(c)] x)
+ for {
+ if v_0.Op != OpMIPS64MULVU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpMIPS64MOVVconst {
+ continue
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ continue
+ }
+ v.reset(OpMIPS64SLLVconst)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Select1 (DIVVU x (MOVVconst [1])))
+ // result: x
+ for {
+ if v_0.Op != OpMIPS64DIVVU {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Select1 (DIVVU x (MOVVconst [c])))
+ // cond: isPowerOfTwo64(c)
+ // result: (SRLVconst [log64(c)] x)
+ for {
+ if v_0.Op != OpMIPS64DIVVU {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpMIPS64SRLVconst)
+ v.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (Select1 (MULVU (MOVVconst [c]) (MOVVconst [d])))
+ // result: (MOVVconst [c*d])
+ for {
+ if v_0.Op != OpMIPS64MULVU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpMIPS64MOVVconst {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_0_1.Op != OpMIPS64MOVVconst {
+ continue
+ }
+ d := auxIntToInt64(v_0_1.AuxInt)
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(c * d)
+ return true
+ }
+ break
+ }
+ // match: (Select1 (DIVV (MOVVconst [c]) (MOVVconst [d])))
+ // cond: d != 0
+ // result: (MOVVconst [c/d])
+ for {
+ if v_0.Op != OpMIPS64DIVV {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(c / d)
+ return true
+ }
+ // match: (Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d])))
+ // cond: d != 0
+ // result: (MOVVconst [int64(uint64(c)/uint64(d))])
+ for {
+ if v_0.Op != OpMIPS64DIVVU {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpMIPS64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst {
+ break
+ }
+ d := auxIntToInt64(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVconst)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Slicemask <t> x)
+ // result: (SRAVconst (NEGV <t> x) [63])
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpMIPS64SRAVconst)
+ v.AuxInt = int64ToAuxInt(63)
+ v0 := b.NewValue0(v.Pos, OpMIPS64NEGV, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueMIPS64_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 1
+ // result: (MOVBstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 1) {
+ break
+ }
+ v.reset(OpMIPS64MOVBstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 2
+ // result: (MOVHstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 2) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && !is32BitFloat(val.Type)
+ // result: (MOVWstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && !is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && !is64BitFloat(val.Type)
+ // result: (MOVVstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && !is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && is32BitFloat(val.Type)
+ // result: (MOVFstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpMIPS64MOVFstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && is64BitFloat(val.Type)
+ // result: (MOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpMIPS64MOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueMIPS64_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Zero [0] _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_1
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero [1] ptr mem)
+ // result: (MOVBstore ptr (MOVVconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpMIPS64MOVBstore)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [2] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore ptr (MOVVconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [2] ptr mem)
+ // result: (MOVBstore [1] ptr (MOVVconst [0]) (MOVBstore [0] ptr (MOVVconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [4] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore ptr (MOVVconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstore)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [4] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [2] ptr (MOVVconst [0]) (MOVHstore [0] ptr (MOVVconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [4] ptr mem)
+ // result: (MOVBstore [3] ptr (MOVVconst [0]) (MOVBstore [2] ptr (MOVVconst [0]) (MOVBstore [1] ptr (MOVVconst [0]) (MOVBstore [0] ptr (MOVVconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(1)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(0)
+ v3.AddArg3(ptr, v0, mem)
+ v2.AddArg3(ptr, v0, v3)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [8] {t} ptr mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVVstore ptr (MOVVconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstore)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [8] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [4] ptr (MOVVconst [0]) (MOVWstore [0] ptr (MOVVconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [8] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [6] ptr (MOVVconst [0]) (MOVHstore [4] ptr (MOVVconst [0]) (MOVHstore [2] ptr (MOVVconst [0]) (MOVHstore [0] ptr (MOVVconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(2)
+ v3 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(0)
+ v3.AddArg3(ptr, v0, mem)
+ v2.AddArg3(ptr, v0, v3)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [3] ptr mem)
+ // result: (MOVBstore [2] ptr (MOVVconst [0]) (MOVBstore [1] ptr (MOVVconst [0]) (MOVBstore [0] ptr (MOVVconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpMIPS64MOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVBstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [6] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [4] ptr (MOVVconst [0]) (MOVHstore [2] ptr (MOVVconst [0]) (MOVHstore [0] ptr (MOVVconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVHstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVHstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [12] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [8] ptr (MOVVconst [0]) (MOVWstore [4] ptr (MOVVconst [0]) (MOVWstore [0] ptr (MOVVconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVWstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVWstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [16] {t} ptr mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVVstore [8] ptr (MOVVconst [0]) (MOVVstore [0] ptr (MOVVconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVVstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [24] {t} ptr mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVVstore [16] ptr (MOVVconst [0]) (MOVVstore [8] ptr (MOVVconst [0]) (MOVVstore [0] ptr (MOVVconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpMIPS64MOVVstore)
+ v.AuxInt = int32ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpMIPS64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpMIPS64MOVVstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpMIPS64MOVVstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [s] {t} ptr mem)
+ // cond: s%8 == 0 && s > 24 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice
+ // result: (DUFFZERO [8 * (128 - s/8)] ptr mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(s%8 == 0 && s > 24 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice) {
+ break
+ }
+ v.reset(OpMIPS64DUFFZERO)
+ v.AuxInt = int64ToAuxInt(8 * (128 - s/8))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Zero [s] {t} ptr mem)
+ // cond: (s > 8*128 || config.noDuffDevice) || t.Alignment()%8 != 0
+ // result: (LoweredZero [t.Alignment()] ptr (ADDVconst <ptr.Type> ptr [s-moveSize(t.Alignment(), config)]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !((s > 8*128 || config.noDuffDevice) || t.Alignment()%8 != 0) {
+ break
+ }
+ v.reset(OpMIPS64LoweredZero)
+ v.AuxInt = int64ToAuxInt(t.Alignment())
+ v0 := b.NewValue0(v.Pos, OpMIPS64ADDVconst, ptr.Type)
+ v0.AuxInt = int64ToAuxInt(s - moveSize(t.Alignment(), config))
+ v0.AddArg(ptr)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteBlockMIPS64(b *Block) bool {
+ switch b.Kind {
+ case BlockMIPS64EQ:
+ // match: (EQ (FPFlagTrue cmp) yes no)
+ // result: (FPF cmp yes no)
+ for b.Controls[0].Op == OpMIPS64FPFlagTrue {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockMIPS64FPF, cmp)
+ return true
+ }
+ // match: (EQ (FPFlagFalse cmp) yes no)
+ // result: (FPT cmp yes no)
+ for b.Controls[0].Op == OpMIPS64FPFlagFalse {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockMIPS64FPT, cmp)
+ return true
+ }
+ // match: (EQ (XORconst [1] cmp:(SGT _ _)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpMIPS64XORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPS64SGT {
+ break
+ }
+ b.resetWithControl(BlockMIPS64NE, cmp)
+ return true
+ }
+ // match: (EQ (XORconst [1] cmp:(SGTU _ _)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpMIPS64XORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPS64SGTU {
+ break
+ }
+ b.resetWithControl(BlockMIPS64NE, cmp)
+ return true
+ }
+ // match: (EQ (XORconst [1] cmp:(SGTconst _)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpMIPS64XORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPS64SGTconst {
+ break
+ }
+ b.resetWithControl(BlockMIPS64NE, cmp)
+ return true
+ }
+ // match: (EQ (XORconst [1] cmp:(SGTUconst _)) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpMIPS64XORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPS64SGTUconst {
+ break
+ }
+ b.resetWithControl(BlockMIPS64NE, cmp)
+ return true
+ }
+ // match: (EQ (SGTUconst [1] x) yes no)
+ // result: (NE x yes no)
+ for b.Controls[0].Op == OpMIPS64SGTUconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPS64NE, x)
+ return true
+ }
+ // match: (EQ (SGTU x (MOVVconst [0])) yes no)
+ // result: (EQ x yes no)
+ for b.Controls[0].Op == OpMIPS64SGTU {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 0 {
+ break
+ }
+ b.resetWithControl(BlockMIPS64EQ, x)
+ return true
+ }
+ // match: (EQ (SGTconst [0] x) yes no)
+ // result: (GEZ x yes no)
+ for b.Controls[0].Op == OpMIPS64SGTconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPS64GEZ, x)
+ return true
+ }
+ // match: (EQ (SGT x (MOVVconst [0])) yes no)
+ // result: (LEZ x yes no)
+ for b.Controls[0].Op == OpMIPS64SGT {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 0 {
+ break
+ }
+ b.resetWithControl(BlockMIPS64LEZ, x)
+ return true
+ }
+ // match: (EQ (MOVVconst [0]) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (EQ (MOVVconst [c]) yes no)
+ // cond: c != 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockMIPS64GEZ:
+ // match: (GEZ (MOVVconst [c]) yes no)
+ // cond: c >= 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c >= 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GEZ (MOVVconst [c]) yes no)
+ // cond: c < 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c < 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockMIPS64GTZ:
+ // match: (GTZ (MOVVconst [c]) yes no)
+ // cond: c > 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c > 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GTZ (MOVVconst [c]) yes no)
+ // cond: c <= 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c <= 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockIf:
+ // match: (If cond yes no)
+ // result: (NE cond yes no)
+ for {
+ cond := b.Controls[0]
+ b.resetWithControl(BlockMIPS64NE, cond)
+ return true
+ }
+ case BlockMIPS64LEZ:
+ // match: (LEZ (MOVVconst [c]) yes no)
+ // cond: c <= 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c <= 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LEZ (MOVVconst [c]) yes no)
+ // cond: c > 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c > 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockMIPS64LTZ:
+ // match: (LTZ (MOVVconst [c]) yes no)
+ // cond: c < 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c < 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LTZ (MOVVconst [c]) yes no)
+ // cond: c >= 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c >= 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockMIPS64NE:
+ // match: (NE (FPFlagTrue cmp) yes no)
+ // result: (FPT cmp yes no)
+ for b.Controls[0].Op == OpMIPS64FPFlagTrue {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockMIPS64FPT, cmp)
+ return true
+ }
+ // match: (NE (FPFlagFalse cmp) yes no)
+ // result: (FPF cmp yes no)
+ for b.Controls[0].Op == OpMIPS64FPFlagFalse {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockMIPS64FPF, cmp)
+ return true
+ }
+ // match: (NE (XORconst [1] cmp:(SGT _ _)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpMIPS64XORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPS64SGT {
+ break
+ }
+ b.resetWithControl(BlockMIPS64EQ, cmp)
+ return true
+ }
+ // match: (NE (XORconst [1] cmp:(SGTU _ _)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpMIPS64XORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPS64SGTU {
+ break
+ }
+ b.resetWithControl(BlockMIPS64EQ, cmp)
+ return true
+ }
+ // match: (NE (XORconst [1] cmp:(SGTconst _)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpMIPS64XORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPS64SGTconst {
+ break
+ }
+ b.resetWithControl(BlockMIPS64EQ, cmp)
+ return true
+ }
+ // match: (NE (XORconst [1] cmp:(SGTUconst _)) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpMIPS64XORconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ cmp := v_0.Args[0]
+ if cmp.Op != OpMIPS64SGTUconst {
+ break
+ }
+ b.resetWithControl(BlockMIPS64EQ, cmp)
+ return true
+ }
+ // match: (NE (SGTUconst [1] x) yes no)
+ // result: (EQ x yes no)
+ for b.Controls[0].Op == OpMIPS64SGTUconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPS64EQ, x)
+ return true
+ }
+ // match: (NE (SGTU x (MOVVconst [0])) yes no)
+ // result: (NE x yes no)
+ for b.Controls[0].Op == OpMIPS64SGTU {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 0 {
+ break
+ }
+ b.resetWithControl(BlockMIPS64NE, x)
+ return true
+ }
+ // match: (NE (SGTconst [0] x) yes no)
+ // result: (LTZ x yes no)
+ for b.Controls[0].Op == OpMIPS64SGTconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ b.resetWithControl(BlockMIPS64LTZ, x)
+ return true
+ }
+ // match: (NE (SGT x (MOVVconst [0])) yes no)
+ // result: (GTZ x yes no)
+ for b.Controls[0].Op == OpMIPS64SGT {
+ v_0 := b.Controls[0]
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpMIPS64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 0 {
+ break
+ }
+ b.resetWithControl(BlockMIPS64GTZ, x)
+ return true
+ }
+ // match: (NE (MOVVconst [0]) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (NE (MOVVconst [c]) yes no)
+ // cond: c != 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpMIPS64MOVVconst {
+ v_0 := b.Controls[0]
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go
new file mode 100644
index 0000000..455f9b1
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewritePPC64.go
@@ -0,0 +1,18258 @@
+// Code generated from gen/PPC64.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "math"
+import "cmd/internal/objabi"
+import "cmd/compile/internal/types"
+
+func rewriteValuePPC64(v *Value) bool {
+ switch v.Op {
+ case OpAbs:
+ v.Op = OpPPC64FABS
+ return true
+ case OpAdd16:
+ v.Op = OpPPC64ADD
+ return true
+ case OpAdd32:
+ v.Op = OpPPC64ADD
+ return true
+ case OpAdd32F:
+ v.Op = OpPPC64FADDS
+ return true
+ case OpAdd64:
+ v.Op = OpPPC64ADD
+ return true
+ case OpAdd64F:
+ v.Op = OpPPC64FADD
+ return true
+ case OpAdd64carry:
+ v.Op = OpPPC64LoweredAdd64Carry
+ return true
+ case OpAdd8:
+ v.Op = OpPPC64ADD
+ return true
+ case OpAddPtr:
+ v.Op = OpPPC64ADD
+ return true
+ case OpAddr:
+ return rewriteValuePPC64_OpAddr(v)
+ case OpAnd16:
+ v.Op = OpPPC64AND
+ return true
+ case OpAnd32:
+ v.Op = OpPPC64AND
+ return true
+ case OpAnd64:
+ v.Op = OpPPC64AND
+ return true
+ case OpAnd8:
+ v.Op = OpPPC64AND
+ return true
+ case OpAndB:
+ v.Op = OpPPC64AND
+ return true
+ case OpAtomicAdd32:
+ v.Op = OpPPC64LoweredAtomicAdd32
+ return true
+ case OpAtomicAdd64:
+ v.Op = OpPPC64LoweredAtomicAdd64
+ return true
+ case OpAtomicAnd32:
+ v.Op = OpPPC64LoweredAtomicAnd32
+ return true
+ case OpAtomicAnd8:
+ v.Op = OpPPC64LoweredAtomicAnd8
+ return true
+ case OpAtomicCompareAndSwap32:
+ return rewriteValuePPC64_OpAtomicCompareAndSwap32(v)
+ case OpAtomicCompareAndSwap64:
+ return rewriteValuePPC64_OpAtomicCompareAndSwap64(v)
+ case OpAtomicCompareAndSwapRel32:
+ return rewriteValuePPC64_OpAtomicCompareAndSwapRel32(v)
+ case OpAtomicExchange32:
+ v.Op = OpPPC64LoweredAtomicExchange32
+ return true
+ case OpAtomicExchange64:
+ v.Op = OpPPC64LoweredAtomicExchange64
+ return true
+ case OpAtomicLoad32:
+ return rewriteValuePPC64_OpAtomicLoad32(v)
+ case OpAtomicLoad64:
+ return rewriteValuePPC64_OpAtomicLoad64(v)
+ case OpAtomicLoad8:
+ return rewriteValuePPC64_OpAtomicLoad8(v)
+ case OpAtomicLoadAcq32:
+ return rewriteValuePPC64_OpAtomicLoadAcq32(v)
+ case OpAtomicLoadAcq64:
+ return rewriteValuePPC64_OpAtomicLoadAcq64(v)
+ case OpAtomicLoadPtr:
+ return rewriteValuePPC64_OpAtomicLoadPtr(v)
+ case OpAtomicOr32:
+ v.Op = OpPPC64LoweredAtomicOr32
+ return true
+ case OpAtomicOr8:
+ v.Op = OpPPC64LoweredAtomicOr8
+ return true
+ case OpAtomicStore32:
+ return rewriteValuePPC64_OpAtomicStore32(v)
+ case OpAtomicStore64:
+ return rewriteValuePPC64_OpAtomicStore64(v)
+ case OpAtomicStore8:
+ return rewriteValuePPC64_OpAtomicStore8(v)
+ case OpAtomicStoreRel32:
+ return rewriteValuePPC64_OpAtomicStoreRel32(v)
+ case OpAtomicStoreRel64:
+ return rewriteValuePPC64_OpAtomicStoreRel64(v)
+ case OpAvg64u:
+ return rewriteValuePPC64_OpAvg64u(v)
+ case OpBitLen32:
+ return rewriteValuePPC64_OpBitLen32(v)
+ case OpBitLen64:
+ return rewriteValuePPC64_OpBitLen64(v)
+ case OpCeil:
+ v.Op = OpPPC64FCEIL
+ return true
+ case OpClosureCall:
+ v.Op = OpPPC64CALLclosure
+ return true
+ case OpCom16:
+ return rewriteValuePPC64_OpCom16(v)
+ case OpCom32:
+ return rewriteValuePPC64_OpCom32(v)
+ case OpCom64:
+ return rewriteValuePPC64_OpCom64(v)
+ case OpCom8:
+ return rewriteValuePPC64_OpCom8(v)
+ case OpCondSelect:
+ return rewriteValuePPC64_OpCondSelect(v)
+ case OpConst16:
+ return rewriteValuePPC64_OpConst16(v)
+ case OpConst32:
+ return rewriteValuePPC64_OpConst32(v)
+ case OpConst32F:
+ v.Op = OpPPC64FMOVSconst
+ return true
+ case OpConst64:
+ return rewriteValuePPC64_OpConst64(v)
+ case OpConst64F:
+ v.Op = OpPPC64FMOVDconst
+ return true
+ case OpConst8:
+ return rewriteValuePPC64_OpConst8(v)
+ case OpConstBool:
+ return rewriteValuePPC64_OpConstBool(v)
+ case OpConstNil:
+ return rewriteValuePPC64_OpConstNil(v)
+ case OpCopysign:
+ return rewriteValuePPC64_OpCopysign(v)
+ case OpCtz16:
+ return rewriteValuePPC64_OpCtz16(v)
+ case OpCtz32:
+ return rewriteValuePPC64_OpCtz32(v)
+ case OpCtz32NonZero:
+ v.Op = OpCtz32
+ return true
+ case OpCtz64:
+ return rewriteValuePPC64_OpCtz64(v)
+ case OpCtz64NonZero:
+ v.Op = OpCtz64
+ return true
+ case OpCtz8:
+ return rewriteValuePPC64_OpCtz8(v)
+ case OpCvt32Fto32:
+ return rewriteValuePPC64_OpCvt32Fto32(v)
+ case OpCvt32Fto64:
+ return rewriteValuePPC64_OpCvt32Fto64(v)
+ case OpCvt32Fto64F:
+ v.Op = OpCopy
+ return true
+ case OpCvt32to32F:
+ return rewriteValuePPC64_OpCvt32to32F(v)
+ case OpCvt32to64F:
+ return rewriteValuePPC64_OpCvt32to64F(v)
+ case OpCvt64Fto32:
+ return rewriteValuePPC64_OpCvt64Fto32(v)
+ case OpCvt64Fto32F:
+ v.Op = OpPPC64FRSP
+ return true
+ case OpCvt64Fto64:
+ return rewriteValuePPC64_OpCvt64Fto64(v)
+ case OpCvt64to32F:
+ return rewriteValuePPC64_OpCvt64to32F(v)
+ case OpCvt64to64F:
+ return rewriteValuePPC64_OpCvt64to64F(v)
+ case OpCvtBoolToUint8:
+ v.Op = OpCopy
+ return true
+ case OpDiv16:
+ return rewriteValuePPC64_OpDiv16(v)
+ case OpDiv16u:
+ return rewriteValuePPC64_OpDiv16u(v)
+ case OpDiv32:
+ return rewriteValuePPC64_OpDiv32(v)
+ case OpDiv32F:
+ v.Op = OpPPC64FDIVS
+ return true
+ case OpDiv32u:
+ v.Op = OpPPC64DIVWU
+ return true
+ case OpDiv64:
+ return rewriteValuePPC64_OpDiv64(v)
+ case OpDiv64F:
+ v.Op = OpPPC64FDIV
+ return true
+ case OpDiv64u:
+ v.Op = OpPPC64DIVDU
+ return true
+ case OpDiv8:
+ return rewriteValuePPC64_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValuePPC64_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValuePPC64_OpEq16(v)
+ case OpEq32:
+ return rewriteValuePPC64_OpEq32(v)
+ case OpEq32F:
+ return rewriteValuePPC64_OpEq32F(v)
+ case OpEq64:
+ return rewriteValuePPC64_OpEq64(v)
+ case OpEq64F:
+ return rewriteValuePPC64_OpEq64F(v)
+ case OpEq8:
+ return rewriteValuePPC64_OpEq8(v)
+ case OpEqB:
+ return rewriteValuePPC64_OpEqB(v)
+ case OpEqPtr:
+ return rewriteValuePPC64_OpEqPtr(v)
+ case OpFMA:
+ v.Op = OpPPC64FMADD
+ return true
+ case OpFloor:
+ v.Op = OpPPC64FFLOOR
+ return true
+ case OpGetCallerPC:
+ v.Op = OpPPC64LoweredGetCallerPC
+ return true
+ case OpGetCallerSP:
+ v.Op = OpPPC64LoweredGetCallerSP
+ return true
+ case OpGetClosurePtr:
+ v.Op = OpPPC64LoweredGetClosurePtr
+ return true
+ case OpHmul32:
+ v.Op = OpPPC64MULHW
+ return true
+ case OpHmul32u:
+ v.Op = OpPPC64MULHWU
+ return true
+ case OpHmul64:
+ v.Op = OpPPC64MULHD
+ return true
+ case OpHmul64u:
+ v.Op = OpPPC64MULHDU
+ return true
+ case OpInterCall:
+ v.Op = OpPPC64CALLinter
+ return true
+ case OpIsInBounds:
+ return rewriteValuePPC64_OpIsInBounds(v)
+ case OpIsNonNil:
+ return rewriteValuePPC64_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ return rewriteValuePPC64_OpIsSliceInBounds(v)
+ case OpLeq16:
+ return rewriteValuePPC64_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValuePPC64_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValuePPC64_OpLeq32(v)
+ case OpLeq32F:
+ return rewriteValuePPC64_OpLeq32F(v)
+ case OpLeq32U:
+ return rewriteValuePPC64_OpLeq32U(v)
+ case OpLeq64:
+ return rewriteValuePPC64_OpLeq64(v)
+ case OpLeq64F:
+ return rewriteValuePPC64_OpLeq64F(v)
+ case OpLeq64U:
+ return rewriteValuePPC64_OpLeq64U(v)
+ case OpLeq8:
+ return rewriteValuePPC64_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValuePPC64_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValuePPC64_OpLess16(v)
+ case OpLess16U:
+ return rewriteValuePPC64_OpLess16U(v)
+ case OpLess32:
+ return rewriteValuePPC64_OpLess32(v)
+ case OpLess32F:
+ return rewriteValuePPC64_OpLess32F(v)
+ case OpLess32U:
+ return rewriteValuePPC64_OpLess32U(v)
+ case OpLess64:
+ return rewriteValuePPC64_OpLess64(v)
+ case OpLess64F:
+ return rewriteValuePPC64_OpLess64F(v)
+ case OpLess64U:
+ return rewriteValuePPC64_OpLess64U(v)
+ case OpLess8:
+ return rewriteValuePPC64_OpLess8(v)
+ case OpLess8U:
+ return rewriteValuePPC64_OpLess8U(v)
+ case OpLoad:
+ return rewriteValuePPC64_OpLoad(v)
+ case OpLocalAddr:
+ return rewriteValuePPC64_OpLocalAddr(v)
+ case OpLsh16x16:
+ return rewriteValuePPC64_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValuePPC64_OpLsh16x32(v)
+ case OpLsh16x64:
+ return rewriteValuePPC64_OpLsh16x64(v)
+ case OpLsh16x8:
+ return rewriteValuePPC64_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValuePPC64_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValuePPC64_OpLsh32x32(v)
+ case OpLsh32x64:
+ return rewriteValuePPC64_OpLsh32x64(v)
+ case OpLsh32x8:
+ return rewriteValuePPC64_OpLsh32x8(v)
+ case OpLsh64x16:
+ return rewriteValuePPC64_OpLsh64x16(v)
+ case OpLsh64x32:
+ return rewriteValuePPC64_OpLsh64x32(v)
+ case OpLsh64x64:
+ return rewriteValuePPC64_OpLsh64x64(v)
+ case OpLsh64x8:
+ return rewriteValuePPC64_OpLsh64x8(v)
+ case OpLsh8x16:
+ return rewriteValuePPC64_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValuePPC64_OpLsh8x32(v)
+ case OpLsh8x64:
+ return rewriteValuePPC64_OpLsh8x64(v)
+ case OpLsh8x8:
+ return rewriteValuePPC64_OpLsh8x8(v)
+ case OpMod16:
+ return rewriteValuePPC64_OpMod16(v)
+ case OpMod16u:
+ return rewriteValuePPC64_OpMod16u(v)
+ case OpMod32:
+ return rewriteValuePPC64_OpMod32(v)
+ case OpMod32u:
+ return rewriteValuePPC64_OpMod32u(v)
+ case OpMod64:
+ return rewriteValuePPC64_OpMod64(v)
+ case OpMod64u:
+ return rewriteValuePPC64_OpMod64u(v)
+ case OpMod8:
+ return rewriteValuePPC64_OpMod8(v)
+ case OpMod8u:
+ return rewriteValuePPC64_OpMod8u(v)
+ case OpMove:
+ return rewriteValuePPC64_OpMove(v)
+ case OpMul16:
+ v.Op = OpPPC64MULLW
+ return true
+ case OpMul32:
+ v.Op = OpPPC64MULLW
+ return true
+ case OpMul32F:
+ v.Op = OpPPC64FMULS
+ return true
+ case OpMul64:
+ v.Op = OpPPC64MULLD
+ return true
+ case OpMul64F:
+ v.Op = OpPPC64FMUL
+ return true
+ case OpMul64uhilo:
+ v.Op = OpPPC64LoweredMuluhilo
+ return true
+ case OpMul8:
+ v.Op = OpPPC64MULLW
+ return true
+ case OpNeg16:
+ v.Op = OpPPC64NEG
+ return true
+ case OpNeg32:
+ v.Op = OpPPC64NEG
+ return true
+ case OpNeg32F:
+ v.Op = OpPPC64FNEG
+ return true
+ case OpNeg64:
+ v.Op = OpPPC64NEG
+ return true
+ case OpNeg64F:
+ v.Op = OpPPC64FNEG
+ return true
+ case OpNeg8:
+ v.Op = OpPPC64NEG
+ return true
+ case OpNeq16:
+ return rewriteValuePPC64_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValuePPC64_OpNeq32(v)
+ case OpNeq32F:
+ return rewriteValuePPC64_OpNeq32F(v)
+ case OpNeq64:
+ return rewriteValuePPC64_OpNeq64(v)
+ case OpNeq64F:
+ return rewriteValuePPC64_OpNeq64F(v)
+ case OpNeq8:
+ return rewriteValuePPC64_OpNeq8(v)
+ case OpNeqB:
+ v.Op = OpPPC64XOR
+ return true
+ case OpNeqPtr:
+ return rewriteValuePPC64_OpNeqPtr(v)
+ case OpNilCheck:
+ v.Op = OpPPC64LoweredNilCheck
+ return true
+ case OpNot:
+ return rewriteValuePPC64_OpNot(v)
+ case OpOffPtr:
+ return rewriteValuePPC64_OpOffPtr(v)
+ case OpOr16:
+ v.Op = OpPPC64OR
+ return true
+ case OpOr32:
+ v.Op = OpPPC64OR
+ return true
+ case OpOr64:
+ v.Op = OpPPC64OR
+ return true
+ case OpOr8:
+ v.Op = OpPPC64OR
+ return true
+ case OpOrB:
+ v.Op = OpPPC64OR
+ return true
+ case OpPPC64ADD:
+ return rewriteValuePPC64_OpPPC64ADD(v)
+ case OpPPC64ADDconst:
+ return rewriteValuePPC64_OpPPC64ADDconst(v)
+ case OpPPC64AND:
+ return rewriteValuePPC64_OpPPC64AND(v)
+ case OpPPC64ANDN:
+ return rewriteValuePPC64_OpPPC64ANDN(v)
+ case OpPPC64ANDconst:
+ return rewriteValuePPC64_OpPPC64ANDconst(v)
+ case OpPPC64CLRLSLDI:
+ return rewriteValuePPC64_OpPPC64CLRLSLDI(v)
+ case OpPPC64CMP:
+ return rewriteValuePPC64_OpPPC64CMP(v)
+ case OpPPC64CMPU:
+ return rewriteValuePPC64_OpPPC64CMPU(v)
+ case OpPPC64CMPUconst:
+ return rewriteValuePPC64_OpPPC64CMPUconst(v)
+ case OpPPC64CMPW:
+ return rewriteValuePPC64_OpPPC64CMPW(v)
+ case OpPPC64CMPWU:
+ return rewriteValuePPC64_OpPPC64CMPWU(v)
+ case OpPPC64CMPWUconst:
+ return rewriteValuePPC64_OpPPC64CMPWUconst(v)
+ case OpPPC64CMPWconst:
+ return rewriteValuePPC64_OpPPC64CMPWconst(v)
+ case OpPPC64CMPconst:
+ return rewriteValuePPC64_OpPPC64CMPconst(v)
+ case OpPPC64Equal:
+ return rewriteValuePPC64_OpPPC64Equal(v)
+ case OpPPC64FABS:
+ return rewriteValuePPC64_OpPPC64FABS(v)
+ case OpPPC64FADD:
+ return rewriteValuePPC64_OpPPC64FADD(v)
+ case OpPPC64FADDS:
+ return rewriteValuePPC64_OpPPC64FADDS(v)
+ case OpPPC64FCEIL:
+ return rewriteValuePPC64_OpPPC64FCEIL(v)
+ case OpPPC64FFLOOR:
+ return rewriteValuePPC64_OpPPC64FFLOOR(v)
+ case OpPPC64FGreaterEqual:
+ return rewriteValuePPC64_OpPPC64FGreaterEqual(v)
+ case OpPPC64FGreaterThan:
+ return rewriteValuePPC64_OpPPC64FGreaterThan(v)
+ case OpPPC64FLessEqual:
+ return rewriteValuePPC64_OpPPC64FLessEqual(v)
+ case OpPPC64FLessThan:
+ return rewriteValuePPC64_OpPPC64FLessThan(v)
+ case OpPPC64FMOVDload:
+ return rewriteValuePPC64_OpPPC64FMOVDload(v)
+ case OpPPC64FMOVDstore:
+ return rewriteValuePPC64_OpPPC64FMOVDstore(v)
+ case OpPPC64FMOVSload:
+ return rewriteValuePPC64_OpPPC64FMOVSload(v)
+ case OpPPC64FMOVSstore:
+ return rewriteValuePPC64_OpPPC64FMOVSstore(v)
+ case OpPPC64FNEG:
+ return rewriteValuePPC64_OpPPC64FNEG(v)
+ case OpPPC64FSQRT:
+ return rewriteValuePPC64_OpPPC64FSQRT(v)
+ case OpPPC64FSUB:
+ return rewriteValuePPC64_OpPPC64FSUB(v)
+ case OpPPC64FSUBS:
+ return rewriteValuePPC64_OpPPC64FSUBS(v)
+ case OpPPC64FTRUNC:
+ return rewriteValuePPC64_OpPPC64FTRUNC(v)
+ case OpPPC64GreaterEqual:
+ return rewriteValuePPC64_OpPPC64GreaterEqual(v)
+ case OpPPC64GreaterThan:
+ return rewriteValuePPC64_OpPPC64GreaterThan(v)
+ case OpPPC64ISEL:
+ return rewriteValuePPC64_OpPPC64ISEL(v)
+ case OpPPC64ISELB:
+ return rewriteValuePPC64_OpPPC64ISELB(v)
+ case OpPPC64LessEqual:
+ return rewriteValuePPC64_OpPPC64LessEqual(v)
+ case OpPPC64LessThan:
+ return rewriteValuePPC64_OpPPC64LessThan(v)
+ case OpPPC64MFVSRD:
+ return rewriteValuePPC64_OpPPC64MFVSRD(v)
+ case OpPPC64MOVBZload:
+ return rewriteValuePPC64_OpPPC64MOVBZload(v)
+ case OpPPC64MOVBZloadidx:
+ return rewriteValuePPC64_OpPPC64MOVBZloadidx(v)
+ case OpPPC64MOVBZreg:
+ return rewriteValuePPC64_OpPPC64MOVBZreg(v)
+ case OpPPC64MOVBreg:
+ return rewriteValuePPC64_OpPPC64MOVBreg(v)
+ case OpPPC64MOVBstore:
+ return rewriteValuePPC64_OpPPC64MOVBstore(v)
+ case OpPPC64MOVBstoreidx:
+ return rewriteValuePPC64_OpPPC64MOVBstoreidx(v)
+ case OpPPC64MOVBstorezero:
+ return rewriteValuePPC64_OpPPC64MOVBstorezero(v)
+ case OpPPC64MOVDload:
+ return rewriteValuePPC64_OpPPC64MOVDload(v)
+ case OpPPC64MOVDloadidx:
+ return rewriteValuePPC64_OpPPC64MOVDloadidx(v)
+ case OpPPC64MOVDstore:
+ return rewriteValuePPC64_OpPPC64MOVDstore(v)
+ case OpPPC64MOVDstoreidx:
+ return rewriteValuePPC64_OpPPC64MOVDstoreidx(v)
+ case OpPPC64MOVDstorezero:
+ return rewriteValuePPC64_OpPPC64MOVDstorezero(v)
+ case OpPPC64MOVHBRstore:
+ return rewriteValuePPC64_OpPPC64MOVHBRstore(v)
+ case OpPPC64MOVHZload:
+ return rewriteValuePPC64_OpPPC64MOVHZload(v)
+ case OpPPC64MOVHZloadidx:
+ return rewriteValuePPC64_OpPPC64MOVHZloadidx(v)
+ case OpPPC64MOVHZreg:
+ return rewriteValuePPC64_OpPPC64MOVHZreg(v)
+ case OpPPC64MOVHload:
+ return rewriteValuePPC64_OpPPC64MOVHload(v)
+ case OpPPC64MOVHloadidx:
+ return rewriteValuePPC64_OpPPC64MOVHloadidx(v)
+ case OpPPC64MOVHreg:
+ return rewriteValuePPC64_OpPPC64MOVHreg(v)
+ case OpPPC64MOVHstore:
+ return rewriteValuePPC64_OpPPC64MOVHstore(v)
+ case OpPPC64MOVHstoreidx:
+ return rewriteValuePPC64_OpPPC64MOVHstoreidx(v)
+ case OpPPC64MOVHstorezero:
+ return rewriteValuePPC64_OpPPC64MOVHstorezero(v)
+ case OpPPC64MOVWBRstore:
+ return rewriteValuePPC64_OpPPC64MOVWBRstore(v)
+ case OpPPC64MOVWZload:
+ return rewriteValuePPC64_OpPPC64MOVWZload(v)
+ case OpPPC64MOVWZloadidx:
+ return rewriteValuePPC64_OpPPC64MOVWZloadidx(v)
+ case OpPPC64MOVWZreg:
+ return rewriteValuePPC64_OpPPC64MOVWZreg(v)
+ case OpPPC64MOVWload:
+ return rewriteValuePPC64_OpPPC64MOVWload(v)
+ case OpPPC64MOVWloadidx:
+ return rewriteValuePPC64_OpPPC64MOVWloadidx(v)
+ case OpPPC64MOVWreg:
+ return rewriteValuePPC64_OpPPC64MOVWreg(v)
+ case OpPPC64MOVWstore:
+ return rewriteValuePPC64_OpPPC64MOVWstore(v)
+ case OpPPC64MOVWstoreidx:
+ return rewriteValuePPC64_OpPPC64MOVWstoreidx(v)
+ case OpPPC64MOVWstorezero:
+ return rewriteValuePPC64_OpPPC64MOVWstorezero(v)
+ case OpPPC64MTVSRD:
+ return rewriteValuePPC64_OpPPC64MTVSRD(v)
+ case OpPPC64MULLD:
+ return rewriteValuePPC64_OpPPC64MULLD(v)
+ case OpPPC64MULLW:
+ return rewriteValuePPC64_OpPPC64MULLW(v)
+ case OpPPC64NEG:
+ return rewriteValuePPC64_OpPPC64NEG(v)
+ case OpPPC64NOR:
+ return rewriteValuePPC64_OpPPC64NOR(v)
+ case OpPPC64NotEqual:
+ return rewriteValuePPC64_OpPPC64NotEqual(v)
+ case OpPPC64OR:
+ return rewriteValuePPC64_OpPPC64OR(v)
+ case OpPPC64ORN:
+ return rewriteValuePPC64_OpPPC64ORN(v)
+ case OpPPC64ORconst:
+ return rewriteValuePPC64_OpPPC64ORconst(v)
+ case OpPPC64ROTL:
+ return rewriteValuePPC64_OpPPC64ROTL(v)
+ case OpPPC64ROTLW:
+ return rewriteValuePPC64_OpPPC64ROTLW(v)
+ case OpPPC64ROTLWconst:
+ return rewriteValuePPC64_OpPPC64ROTLWconst(v)
+ case OpPPC64SLD:
+ return rewriteValuePPC64_OpPPC64SLD(v)
+ case OpPPC64SLDconst:
+ return rewriteValuePPC64_OpPPC64SLDconst(v)
+ case OpPPC64SLW:
+ return rewriteValuePPC64_OpPPC64SLW(v)
+ case OpPPC64SLWconst:
+ return rewriteValuePPC64_OpPPC64SLWconst(v)
+ case OpPPC64SRAD:
+ return rewriteValuePPC64_OpPPC64SRAD(v)
+ case OpPPC64SRAW:
+ return rewriteValuePPC64_OpPPC64SRAW(v)
+ case OpPPC64SRD:
+ return rewriteValuePPC64_OpPPC64SRD(v)
+ case OpPPC64SRW:
+ return rewriteValuePPC64_OpPPC64SRW(v)
+ case OpPPC64SRWconst:
+ return rewriteValuePPC64_OpPPC64SRWconst(v)
+ case OpPPC64SUB:
+ return rewriteValuePPC64_OpPPC64SUB(v)
+ case OpPPC64SUBFCconst:
+ return rewriteValuePPC64_OpPPC64SUBFCconst(v)
+ case OpPPC64XOR:
+ return rewriteValuePPC64_OpPPC64XOR(v)
+ case OpPPC64XORconst:
+ return rewriteValuePPC64_OpPPC64XORconst(v)
+ case OpPanicBounds:
+ return rewriteValuePPC64_OpPanicBounds(v)
+ case OpPopCount16:
+ return rewriteValuePPC64_OpPopCount16(v)
+ case OpPopCount32:
+ return rewriteValuePPC64_OpPopCount32(v)
+ case OpPopCount64:
+ v.Op = OpPPC64POPCNTD
+ return true
+ case OpPopCount8:
+ return rewriteValuePPC64_OpPopCount8(v)
+ case OpRotateLeft16:
+ return rewriteValuePPC64_OpRotateLeft16(v)
+ case OpRotateLeft32:
+ return rewriteValuePPC64_OpRotateLeft32(v)
+ case OpRotateLeft64:
+ return rewriteValuePPC64_OpRotateLeft64(v)
+ case OpRotateLeft8:
+ return rewriteValuePPC64_OpRotateLeft8(v)
+ case OpRound:
+ v.Op = OpPPC64FROUND
+ return true
+ case OpRound32F:
+ v.Op = OpPPC64LoweredRound32F
+ return true
+ case OpRound64F:
+ v.Op = OpPPC64LoweredRound64F
+ return true
+ case OpRsh16Ux16:
+ return rewriteValuePPC64_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValuePPC64_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValuePPC64_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValuePPC64_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValuePPC64_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValuePPC64_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValuePPC64_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValuePPC64_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValuePPC64_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValuePPC64_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValuePPC64_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValuePPC64_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValuePPC64_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValuePPC64_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValuePPC64_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValuePPC64_OpRsh32x8(v)
+ case OpRsh64Ux16:
+ return rewriteValuePPC64_OpRsh64Ux16(v)
+ case OpRsh64Ux32:
+ return rewriteValuePPC64_OpRsh64Ux32(v)
+ case OpRsh64Ux64:
+ return rewriteValuePPC64_OpRsh64Ux64(v)
+ case OpRsh64Ux8:
+ return rewriteValuePPC64_OpRsh64Ux8(v)
+ case OpRsh64x16:
+ return rewriteValuePPC64_OpRsh64x16(v)
+ case OpRsh64x32:
+ return rewriteValuePPC64_OpRsh64x32(v)
+ case OpRsh64x64:
+ return rewriteValuePPC64_OpRsh64x64(v)
+ case OpRsh64x8:
+ return rewriteValuePPC64_OpRsh64x8(v)
+ case OpRsh8Ux16:
+ return rewriteValuePPC64_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValuePPC64_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValuePPC64_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValuePPC64_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValuePPC64_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValuePPC64_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValuePPC64_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValuePPC64_OpRsh8x8(v)
+ case OpSignExt16to32:
+ v.Op = OpPPC64MOVHreg
+ return true
+ case OpSignExt16to64:
+ v.Op = OpPPC64MOVHreg
+ return true
+ case OpSignExt32to64:
+ v.Op = OpPPC64MOVWreg
+ return true
+ case OpSignExt8to16:
+ v.Op = OpPPC64MOVBreg
+ return true
+ case OpSignExt8to32:
+ v.Op = OpPPC64MOVBreg
+ return true
+ case OpSignExt8to64:
+ v.Op = OpPPC64MOVBreg
+ return true
+ case OpSlicemask:
+ return rewriteValuePPC64_OpSlicemask(v)
+ case OpSqrt:
+ v.Op = OpPPC64FSQRT
+ return true
+ case OpStaticCall:
+ v.Op = OpPPC64CALLstatic
+ return true
+ case OpStore:
+ return rewriteValuePPC64_OpStore(v)
+ case OpSub16:
+ v.Op = OpPPC64SUB
+ return true
+ case OpSub32:
+ v.Op = OpPPC64SUB
+ return true
+ case OpSub32F:
+ v.Op = OpPPC64FSUBS
+ return true
+ case OpSub64:
+ v.Op = OpPPC64SUB
+ return true
+ case OpSub64F:
+ v.Op = OpPPC64FSUB
+ return true
+ case OpSub8:
+ v.Op = OpPPC64SUB
+ return true
+ case OpSubPtr:
+ v.Op = OpPPC64SUB
+ return true
+ case OpTrunc:
+ v.Op = OpPPC64FTRUNC
+ return true
+ case OpTrunc16to8:
+ return rewriteValuePPC64_OpTrunc16to8(v)
+ case OpTrunc32to16:
+ return rewriteValuePPC64_OpTrunc32to16(v)
+ case OpTrunc32to8:
+ return rewriteValuePPC64_OpTrunc32to8(v)
+ case OpTrunc64to16:
+ return rewriteValuePPC64_OpTrunc64to16(v)
+ case OpTrunc64to32:
+ return rewriteValuePPC64_OpTrunc64to32(v)
+ case OpTrunc64to8:
+ return rewriteValuePPC64_OpTrunc64to8(v)
+ case OpWB:
+ v.Op = OpPPC64LoweredWB
+ return true
+ case OpXor16:
+ v.Op = OpPPC64XOR
+ return true
+ case OpXor32:
+ v.Op = OpPPC64XOR
+ return true
+ case OpXor64:
+ v.Op = OpPPC64XOR
+ return true
+ case OpXor8:
+ v.Op = OpPPC64XOR
+ return true
+ case OpZero:
+ return rewriteValuePPC64_OpZero(v)
+ case OpZeroExt16to32:
+ v.Op = OpPPC64MOVHZreg
+ return true
+ case OpZeroExt16to64:
+ v.Op = OpPPC64MOVHZreg
+ return true
+ case OpZeroExt32to64:
+ v.Op = OpPPC64MOVWZreg
+ return true
+ case OpZeroExt8to16:
+ v.Op = OpPPC64MOVBZreg
+ return true
+ case OpZeroExt8to32:
+ v.Op = OpPPC64MOVBZreg
+ return true
+ case OpZeroExt8to64:
+ v.Op = OpPPC64MOVBZreg
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Addr {sym} base)
+ // result: (MOVDaddr {sym} [0] base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpPPC64MOVDaddr)
+ v.AuxInt = int32ToAuxInt(0)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicCompareAndSwap32(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicCompareAndSwap32 ptr old new_ mem)
+ // result: (LoweredAtomicCas32 [1] ptr old new_ mem)
+ for {
+ ptr := v_0
+ old := v_1
+ new_ := v_2
+ mem := v_3
+ v.reset(OpPPC64LoweredAtomicCas32)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg4(ptr, old, new_, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicCompareAndSwap64(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicCompareAndSwap64 ptr old new_ mem)
+ // result: (LoweredAtomicCas64 [1] ptr old new_ mem)
+ for {
+ ptr := v_0
+ old := v_1
+ new_ := v_2
+ mem := v_3
+ v.reset(OpPPC64LoweredAtomicCas64)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg4(ptr, old, new_, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicCompareAndSwapRel32(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicCompareAndSwapRel32 ptr old new_ mem)
+ // result: (LoweredAtomicCas32 [0] ptr old new_ mem)
+ for {
+ ptr := v_0
+ old := v_1
+ new_ := v_2
+ mem := v_3
+ v.reset(OpPPC64LoweredAtomicCas32)
+ v.AuxInt = int64ToAuxInt(0)
+ v.AddArg4(ptr, old, new_, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicLoad32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoad32 ptr mem)
+ // result: (LoweredAtomicLoad32 [1] ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpPPC64LoweredAtomicLoad32)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicLoad64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoad64 ptr mem)
+ // result: (LoweredAtomicLoad64 [1] ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpPPC64LoweredAtomicLoad64)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicLoad8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoad8 ptr mem)
+ // result: (LoweredAtomicLoad8 [1] ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpPPC64LoweredAtomicLoad8)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicLoadAcq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoadAcq32 ptr mem)
+ // result: (LoweredAtomicLoad32 [0] ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpPPC64LoweredAtomicLoad32)
+ v.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicLoadAcq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoadAcq64 ptr mem)
+ // result: (LoweredAtomicLoad64 [0] ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpPPC64LoweredAtomicLoad64)
+ v.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicLoadPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoadPtr ptr mem)
+ // result: (LoweredAtomicLoadPtr [1] ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpPPC64LoweredAtomicLoadPtr)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicStore32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicStore32 ptr val mem)
+ // result: (LoweredAtomicStore32 [1] ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpPPC64LoweredAtomicStore32)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicStore64(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicStore64 ptr val mem)
+ // result: (LoweredAtomicStore64 [1] ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpPPC64LoweredAtomicStore64)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicStore8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicStore8 ptr val mem)
+ // result: (LoweredAtomicStore8 [1] ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpPPC64LoweredAtomicStore8)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicStoreRel32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicStoreRel32 ptr val mem)
+ // result: (LoweredAtomicStore32 [0] ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpPPC64LoweredAtomicStore32)
+ v.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAtomicStoreRel64(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicStoreRel64 ptr val mem)
+ // result: (LoweredAtomicStore64 [0] ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpPPC64LoweredAtomicStore64)
+ v.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValuePPC64_OpAvg64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Avg64u <t> x y)
+ // result: (ADD (SRDconst <t> (SUB <t> x y) [1]) y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64ADD)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRDconst, t)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpPPC64SUB, t)
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValuePPC64_OpBitLen32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen32 x)
+ // result: (SUBFCconst [32] (CNTLZW <typ.Int> x))
+ for {
+ x := v_0
+ v.reset(OpPPC64SUBFCconst)
+ v.AuxInt = int64ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpPPC64CNTLZW, typ.Int)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpBitLen64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen64 x)
+ // result: (SUBFCconst [64] (CNTLZD <typ.Int> x))
+ for {
+ x := v_0
+ v.reset(OpPPC64SUBFCconst)
+ v.AuxInt = int64ToAuxInt(64)
+ v0 := b.NewValue0(v.Pos, OpPPC64CNTLZD, typ.Int)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCom16(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com16 x)
+ // result: (NOR x x)
+ for {
+ x := v_0
+ v.reset(OpPPC64NOR)
+ v.AddArg2(x, x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCom32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com32 x)
+ // result: (NOR x x)
+ for {
+ x := v_0
+ v.reset(OpPPC64NOR)
+ v.AddArg2(x, x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCom64(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com64 x)
+ // result: (NOR x x)
+ for {
+ x := v_0
+ v.reset(OpPPC64NOR)
+ v.AddArg2(x, x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCom8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com8 x)
+ // result: (NOR x x)
+ for {
+ x := v_0
+ v.reset(OpPPC64NOR)
+ v.AddArg2(x, x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCondSelect(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CondSelect x y bool)
+ // cond: flagArg(bool) != nil
+ // result: (ISEL [2] x y bool)
+ for {
+ x := v_0
+ y := v_1
+ bool := v_2
+ if !(flagArg(bool) != nil) {
+ break
+ }
+ v.reset(OpPPC64ISEL)
+ v.AuxInt = int32ToAuxInt(2)
+ v.AddArg3(x, y, bool)
+ return true
+ }
+ // match: (CondSelect x y bool)
+ // cond: flagArg(bool) == nil
+ // result: (ISEL [2] x y (CMPWconst [0] bool))
+ for {
+ x := v_0
+ y := v_1
+ bool := v_2
+ if !(flagArg(bool) == nil) {
+ break
+ }
+ v.reset(OpPPC64ISEL)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(bool)
+ v.AddArg3(x, y, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpConst16(v *Value) bool {
+ // match: (Const16 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt16(v.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValuePPC64_OpConst32(v *Value) bool {
+ // match: (Const32 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt32(v.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValuePPC64_OpConst64(v *Value) bool {
+ // match: (Const64 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt64(v.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValuePPC64_OpConst8(v *Value) bool {
+ // match: (Const8 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt8(v.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValuePPC64_OpConstBool(v *Value) bool {
+ // match: (ConstBool [b])
+ // result: (MOVDconst [b2i(b)])
+ for {
+ b := auxIntToBool(v.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(b))
+ return true
+ }
+}
+func rewriteValuePPC64_OpConstNil(v *Value) bool {
+ // match: (ConstNil)
+ // result: (MOVDconst [0])
+ for {
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCopysign(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Copysign x y)
+ // result: (FCPSGN y x)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64FCPSGN)
+ v.AddArg2(y, x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCtz16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz16 x)
+ // result: (POPCNTW (MOVHZreg (ANDN <typ.Int16> (ADDconst <typ.Int16> [-1] x) x)))
+ for {
+ x := v_0
+ v.reset(OpPPC64POPCNTW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDN, typ.Int16)
+ v2 := b.NewValue0(v.Pos, OpPPC64ADDconst, typ.Int16)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v2.AddArg(x)
+ v1.AddArg2(v2, x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCtz32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz32 x)
+ // cond: objabi.GOPPC64<=8
+ // result: (POPCNTW (MOVWZreg (ANDN <typ.Int> (ADDconst <typ.Int> [-1] x) x)))
+ for {
+ x := v_0
+ if !(objabi.GOPPC64 <= 8) {
+ break
+ }
+ v.reset(OpPPC64POPCNTW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWZreg, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDN, typ.Int)
+ v2 := b.NewValue0(v.Pos, OpPPC64ADDconst, typ.Int)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v2.AddArg(x)
+ v1.AddArg2(v2, x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Ctz32 x)
+ // result: (CNTTZW (MOVWZreg x))
+ for {
+ x := v_0
+ v.reset(OpPPC64CNTTZW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCtz64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz64 x)
+ // cond: objabi.GOPPC64<=8
+ // result: (POPCNTD (ANDN <typ.Int64> (ADDconst <typ.Int64> [-1] x) x))
+ for {
+ x := v_0
+ if !(objabi.GOPPC64 <= 8) {
+ break
+ }
+ v.reset(OpPPC64POPCNTD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDN, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpPPC64ADDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v1.AddArg(x)
+ v0.AddArg2(v1, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Ctz64 x)
+ // result: (CNTTZD x)
+ for {
+ x := v_0
+ v.reset(OpPPC64CNTTZD)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCtz8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz8 x)
+ // result: (POPCNTB (MOVBZreg (ANDN <typ.UInt8> (ADDconst <typ.UInt8> [-1] x) x)))
+ for {
+ x := v_0
+ v.reset(OpPPC64POPCNTB)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDN, typ.UInt8)
+ v2 := b.NewValue0(v.Pos, OpPPC64ADDconst, typ.UInt8)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v2.AddArg(x)
+ v1.AddArg2(v2, x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCvt32Fto32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt32Fto32 x)
+ // result: (MFVSRD (FCTIWZ x))
+ for {
+ x := v_0
+ v.reset(OpPPC64MFVSRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCTIWZ, typ.Float64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCvt32Fto64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt32Fto64 x)
+ // result: (MFVSRD (FCTIDZ x))
+ for {
+ x := v_0
+ v.reset(OpPPC64MFVSRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCTIDZ, typ.Float64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCvt32to32F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt32to32F x)
+ // result: (FCFIDS (MTVSRD (SignExt32to64 x)))
+ for {
+ x := v_0
+ v.reset(OpPPC64FCFIDS)
+ v0 := b.NewValue0(v.Pos, OpPPC64MTVSRD, typ.Float64)
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCvt32to64F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt32to64F x)
+ // result: (FCFID (MTVSRD (SignExt32to64 x)))
+ for {
+ x := v_0
+ v.reset(OpPPC64FCFID)
+ v0 := b.NewValue0(v.Pos, OpPPC64MTVSRD, typ.Float64)
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCvt64Fto32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt64Fto32 x)
+ // result: (MFVSRD (FCTIWZ x))
+ for {
+ x := v_0
+ v.reset(OpPPC64MFVSRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCTIWZ, typ.Float64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCvt64Fto64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt64Fto64 x)
+ // result: (MFVSRD (FCTIDZ x))
+ for {
+ x := v_0
+ v.reset(OpPPC64MFVSRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCTIDZ, typ.Float64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCvt64to32F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt64to32F x)
+ // result: (FCFIDS (MTVSRD x))
+ for {
+ x := v_0
+ v.reset(OpPPC64FCFIDS)
+ v0 := b.NewValue0(v.Pos, OpPPC64MTVSRD, typ.Float64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpCvt64to64F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt64to64F x)
+ // result: (FCFID (MTVSRD x))
+ for {
+ x := v_0
+ v.reset(OpPPC64FCFID)
+ v0 := b.NewValue0(v.Pos, OpPPC64MTVSRD, typ.Float64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpDiv16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16 [false] x y)
+ // result: (DIVW (SignExt16to32 x) (SignExt16to32 y))
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64DIVW)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpDiv16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16u x y)
+ // result: (DIVWU (ZeroExt16to32 x) (ZeroExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64DIVWU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpDiv32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Div32 [false] x y)
+ // result: (DIVW x y)
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64DIVW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpDiv64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Div64 [false] x y)
+ // result: (DIVD x y)
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64DIVD)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 x y)
+ // result: (DIVW (SignExt8to32 x) (SignExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64DIVW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u x y)
+ // result: (DIVWU (ZeroExt8to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64DIVWU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq16 x y)
+ // cond: isSigned(x.Type) && isSigned(y.Type)
+ // result: (Equal (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ y := v_1
+ if !(isSigned(x.Type) && isSigned(y.Type)) {
+ continue
+ }
+ v.reset(OpPPC64Equal)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (Eq16 x y)
+ // result: (Equal (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64Equal)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32 x y)
+ // result: (Equal (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64Equal)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpEq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32F x y)
+ // result: (Equal (FCMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64Equal)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCMPU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpEq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64 x y)
+ // result: (Equal (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64Equal)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpEq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64F x y)
+ // result: (Equal (FCMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64Equal)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCMPU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq8 x y)
+ // cond: isSigned(x.Type) && isSigned(y.Type)
+ // result: (Equal (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ y := v_1
+ if !(isSigned(x.Type) && isSigned(y.Type)) {
+ continue
+ }
+ v.reset(OpPPC64Equal)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (Eq8 x y)
+ // result: (Equal (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64Equal)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpEqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqB x y)
+ // result: (ANDconst [1] (EQV x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpPPC64EQV, typ.Int64)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpEqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (EqPtr x y)
+ // result: (Equal (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64Equal)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpIsInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsInBounds idx len)
+ // result: (LessThan (CMPU idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpPPC64LessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsNonNil ptr)
+ // result: (NotEqual (CMPconst [0] ptr))
+ for {
+ ptr := v_0
+ v.reset(OpPPC64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(0)
+ v0.AddArg(ptr)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpIsSliceInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (IsSliceInBounds idx len)
+ // result: (LessEqual (CMPU idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpPPC64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v0.AddArg2(idx, len)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16 x y)
+ // result: (LessEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16U x y)
+ // result: (LessEqual (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPWU, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32 x y)
+ // result: (LessEqual (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32F x y)
+ // result: (FLessEqual (FCMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64FLessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCMPU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq32U x y)
+ // result: (LessEqual (CMPWU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPWU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64 x y)
+ // result: (LessEqual (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64F x y)
+ // result: (FLessEqual (FCMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64FLessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCMPU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLeq64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Leq64U x y)
+ // result: (LessEqual (CMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8 x y)
+ // result: (LessEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8U x y)
+ // result: (LessEqual (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPWU, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16 x y)
+ // result: (LessThan (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16U x y)
+ // result: (LessThan (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPWU, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32 x y)
+ // result: (LessThan (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLess32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32F x y)
+ // result: (FLessThan (FCMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64FLessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCMPU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less32U x y)
+ // result: (LessThan (CMPWU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPWU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLess64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64 x y)
+ // result: (LessThan (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLess64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64F x y)
+ // result: (FLessThan (FCMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64FLessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCMPU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLess64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Less64U x y)
+ // result: (LessThan (CMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8 x y)
+ // result: (LessThan (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8U x y)
+ // result: (LessThan (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64LessThan)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPWU, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Load <t> ptr mem)
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (MOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitInt(t) && isSigned(t)
+ // result: (MOVWload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVWload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitInt(t) && !isSigned(t)
+ // result: (MOVWZload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVWZload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is16BitInt(t) && isSigned(t)
+ // result: (MOVHload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVHload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is16BitInt(t) && !isSigned(t)
+ // result: (MOVHZload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVHZload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.IsBoolean()
+ // result: (MOVBZload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsBoolean()) {
+ break
+ }
+ v.reset(OpPPC64MOVBZload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is8BitInt(t) && isSigned(t)
+ // result: (MOVBreg (MOVBZload ptr mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVBreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZload, typ.UInt8)
+ v0.AddArg2(ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is8BitInt(t) && !isSigned(t)
+ // result: (MOVBZload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVBZload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitFloat(t)
+ // result: (FMOVSload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(OpPPC64FMOVSload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitFloat(t)
+ // result: (FMOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(OpPPC64FMOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpLocalAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LocalAddr {sym} base _)
+ // result: (MOVDaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpPPC64MOVDaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh16x16 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(16)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x32 x (MOVDconst [c]))
+ // cond: uint32(c) < 16
+ // result: (SLWconst x [c&31])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 16) {
+ break
+ }
+ v.reset(OpPPC64SLWconst)
+ v.AuxInt = int64ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh16x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh16x32 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(16)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x64 _ (MOVDconst [c]))
+ // cond: uint64(c) >= 16
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh16x64 x (MOVDconst [c]))
+ // cond: uint64(c) < 16
+ // result: (SLWconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 16) {
+ break
+ }
+ v.reset(OpPPC64SLWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh16x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh16x64 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(16)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh16x8 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(16)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh32x16 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x32 x (MOVDconst [c]))
+ // cond: uint32(c) < 32
+ // result: (SLWconst x [c&31])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 32) {
+ break
+ }
+ v.reset(OpPPC64SLWconst)
+ v.AuxInt = int64ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh32x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh32x32 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x64 _ (MOVDconst [c]))
+ // cond: uint64(c) >= 32
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh32x64 x (MOVDconst [c]))
+ // cond: uint64(c) < 32
+ // result: (SLWconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 32) {
+ break
+ }
+ v.reset(OpPPC64SLWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh32x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh32x64 x (AND y (MOVDconst [31])))
+ // result: (SLW x (ANDconst <typ.Int32> [31] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64AND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ y := v_1_0
+ if v_1_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1.AuxInt) != 31 {
+ continue
+ }
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.Int32)
+ v0.AuxInt = int64ToAuxInt(31)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Lsh32x64 x (ANDconst <typ.Int32> [31] y))
+ // result: (SLW x (ANDconst <typ.Int32> [31] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64ANDconst || v_1.Type != typ.Int32 || auxIntToInt64(v_1.AuxInt) != 31 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.Int32)
+ v0.AuxInt = int64ToAuxInt(31)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh32x64 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh32x8 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh64x16 x y)
+ // result: (SLD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x32 x (MOVDconst [c]))
+ // cond: uint32(c) < 64
+ // result: (SLDconst x [c&63])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 64) {
+ break
+ }
+ v.reset(OpPPC64SLDconst)
+ v.AuxInt = int64ToAuxInt(c & 63)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh64x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh64x32 x y)
+ // result: (SLD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x64 _ (MOVDconst [c]))
+ // cond: uint64(c) >= 64
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh64x64 x (MOVDconst [c]))
+ // cond: uint64(c) < 64
+ // result: (SLDconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 64) {
+ break
+ }
+ v.reset(OpPPC64SLDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh64x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh64x64 x (AND y (MOVDconst [63])))
+ // result: (SLD x (ANDconst <typ.Int64> [63] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64AND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ y := v_1_0
+ if v_1_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1.AuxInt) != 63 {
+ continue
+ }
+ v.reset(OpPPC64SLD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(63)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Lsh64x64 x (ANDconst <typ.Int64> [63] y))
+ // result: (SLD x (ANDconst <typ.Int64> [63] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64ANDconst || v_1.Type != typ.Int64 || auxIntToInt64(v_1.AuxInt) != 63 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpPPC64SLD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(63)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh64x64 x y)
+ // result: (SLD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh64x8 x y)
+ // result: (SLD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh8x16 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(8)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x32 x (MOVDconst [c]))
+ // cond: uint32(c) < 8
+ // result: (SLWconst x [c&7])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 8) {
+ break
+ }
+ v.reset(OpPPC64SLWconst)
+ v.AuxInt = int64ToAuxInt(c & 7)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh8x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh8x32 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(8)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x64 _ (MOVDconst [c]))
+ // cond: uint64(c) >= 8
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh8x64 x (MOVDconst [c]))
+ // cond: uint64(c) < 8
+ // result: (SLWconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 8) {
+ break
+ }
+ v.reset(OpPPC64SLWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Lsh8x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh8x64 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(8)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh8x8 x y)
+ // result: (SLW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SLW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(8)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpMod16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16 x y)
+ // result: (Mod32 (SignExt16to32 x) (SignExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMod32)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpMod16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16u x y)
+ // result: (Mod32u (ZeroExt16to32 x) (ZeroExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMod32u)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpMod32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32 x y)
+ // cond: objabi.GOPPC64 >= 9
+ // result: (MODSW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(objabi.GOPPC64 >= 9) {
+ break
+ }
+ v.reset(OpPPC64MODSW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Mod32 x y)
+ // cond: objabi.GOPPC64 <= 8
+ // result: (SUB x (MULLW y (DIVW x y)))
+ for {
+ x := v_0
+ y := v_1
+ if !(objabi.GOPPC64 <= 8) {
+ break
+ }
+ v.reset(OpPPC64SUB)
+ v0 := b.NewValue0(v.Pos, OpPPC64MULLW, typ.Int32)
+ v1 := b.NewValue0(v.Pos, OpPPC64DIVW, typ.Int32)
+ v1.AddArg2(x, y)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpMod32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32u x y)
+ // cond: objabi.GOPPC64 >= 9
+ // result: (MODUW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(objabi.GOPPC64 >= 9) {
+ break
+ }
+ v.reset(OpPPC64MODUW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Mod32u x y)
+ // cond: objabi.GOPPC64 <= 8
+ // result: (SUB x (MULLW y (DIVWU x y)))
+ for {
+ x := v_0
+ y := v_1
+ if !(objabi.GOPPC64 <= 8) {
+ break
+ }
+ v.reset(OpPPC64SUB)
+ v0 := b.NewValue0(v.Pos, OpPPC64MULLW, typ.Int32)
+ v1 := b.NewValue0(v.Pos, OpPPC64DIVWU, typ.Int32)
+ v1.AddArg2(x, y)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpMod64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod64 x y)
+ // cond: objabi.GOPPC64 >=9
+ // result: (MODSD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(objabi.GOPPC64 >= 9) {
+ break
+ }
+ v.reset(OpPPC64MODSD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Mod64 x y)
+ // cond: objabi.GOPPC64 <=8
+ // result: (SUB x (MULLD y (DIVD x y)))
+ for {
+ x := v_0
+ y := v_1
+ if !(objabi.GOPPC64 <= 8) {
+ break
+ }
+ v.reset(OpPPC64SUB)
+ v0 := b.NewValue0(v.Pos, OpPPC64MULLD, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpPPC64DIVD, typ.Int64)
+ v1.AddArg2(x, y)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpMod64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod64u x y)
+ // cond: objabi.GOPPC64 >= 9
+ // result: (MODUD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(objabi.GOPPC64 >= 9) {
+ break
+ }
+ v.reset(OpPPC64MODUD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Mod64u x y)
+ // cond: objabi.GOPPC64 <= 8
+ // result: (SUB x (MULLD y (DIVDU x y)))
+ for {
+ x := v_0
+ y := v_1
+ if !(objabi.GOPPC64 <= 8) {
+ break
+ }
+ v.reset(OpPPC64SUB)
+ v0 := b.NewValue0(v.Pos, OpPPC64MULLD, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpPPC64DIVDU, typ.Int64)
+ v1.AddArg2(x, y)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8 x y)
+ // result: (Mod32 (SignExt8to32 x) (SignExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMod32)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8u x y)
+ // result: (Mod32u (ZeroExt8to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpMod32u)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Move [0] _ _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Move [1] dst src mem)
+ // result: (MOVBstore dst (MOVBZload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpPPC64MOVBstore)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZload, typ.UInt8)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] dst src mem)
+ // result: (MOVHstore dst (MOVHZload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpPPC64MOVHstore)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZload, typ.UInt16)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [4] dst src mem)
+ // result: (MOVWstore dst (MOVWZload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpPPC64MOVWstore)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWZload, typ.UInt32)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [8] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVDstore dst (MOVDload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstore)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDload, typ.Int64)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [8] dst src mem)
+ // result: (MOVWstore [4] dst (MOVWZload [4] src mem) (MOVWstore dst (MOVWZload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWZload, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVWZload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [3] dst src mem)
+ // result: (MOVBstore [2] dst (MOVBZload [2] src mem) (MOVHstore dst (MOVHload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVHstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVHload, typ.Int16)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [5] dst src mem)
+ // result: (MOVBstore [4] dst (MOVBZload [4] src mem) (MOVWstore dst (MOVWZload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVWZload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [6] dst src mem)
+ // result: (MOVHstore [4] dst (MOVHZload [4] src mem) (MOVWstore dst (MOVWZload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVWZload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [7] dst src mem)
+ // result: (MOVBstore [6] dst (MOVBZload [6] src mem) (MOVHstore [4] dst (MOVHZload [4] src mem) (MOVWstore dst (MOVWZload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(6)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVHZload, typ.UInt16)
+ v2.AuxInt = int32ToAuxInt(4)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVWstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVWZload, typ.UInt32)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 8 && objabi.GOPPC64 <= 8 && logLargeCopy(v, s)
+ // result: (LoweredMove [s] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 8 && objabi.GOPPC64 <= 8 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpPPC64LoweredMove)
+ v.AuxInt = int64ToAuxInt(s)
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 8 && s <= 64 && objabi.GOPPC64 >= 9
+ // result: (LoweredQuadMoveShort [s] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 8 && s <= 64 && objabi.GOPPC64 >= 9) {
+ break
+ }
+ v.reset(OpPPC64LoweredQuadMoveShort)
+ v.AuxInt = int64ToAuxInt(s)
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 8 && objabi.GOPPC64 >= 9 && logLargeCopy(v, s)
+ // result: (LoweredQuadMove [s] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 8 && objabi.GOPPC64 >= 9 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpPPC64LoweredQuadMove)
+ v.AuxInt = int64ToAuxInt(s)
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq16 x y)
+ // cond: isSigned(x.Type) && isSigned(y.Type)
+ // result: (NotEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ y := v_1
+ if !(isSigned(x.Type) && isSigned(y.Type)) {
+ continue
+ }
+ v.reset(OpPPC64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (Neq16 x y)
+ // result: (NotEqual (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32 x y)
+ // result: (NotEqual (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpNeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32F x y)
+ // result: (NotEqual (FCMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCMPU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpNeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64 x y)
+ // result: (NotEqual (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpNeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64F x y)
+ // result: (NotEqual (FCMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64FCMPU, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq8 x y)
+ // cond: isSigned(x.Type) && isSigned(y.Type)
+ // result: (NotEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ y := v_1
+ if !(isSigned(x.Type) && isSigned(y.Type)) {
+ continue
+ }
+ v.reset(OpPPC64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (Neq8 x y)
+ // result: (NotEqual (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpNeqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (NeqPtr x y)
+ // result: (NotEqual (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64NotEqual)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpNot(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Not x)
+ // result: (XORconst [1] x)
+ for {
+ x := v_0
+ v.reset(OpPPC64XORconst)
+ v.AuxInt = int64ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpOffPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (OffPtr [off] ptr)
+ // result: (ADD (MOVDconst <typ.Int64> [off]) ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ v.reset(OpPPC64ADD)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(off)
+ v.AddArg2(v0, ptr)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64ADD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ADD l:(MULLD x y) z)
+ // cond: objabi.GOPPC64 >= 9 && l.Uses == 1 && clobber(l)
+ // result: (MADDLD x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ l := v_0
+ if l.Op != OpPPC64MULLD {
+ continue
+ }
+ y := l.Args[1]
+ x := l.Args[0]
+ z := v_1
+ if !(objabi.GOPPC64 >= 9 && l.Uses == 1 && clobber(l)) {
+ continue
+ }
+ v.reset(OpPPC64MADDLD)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SLDconst x [c]) (SRDconst x [d]))
+ // cond: d == 64-c
+ // result: (ROTLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpPPC64SRDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 64-c) {
+ continue
+ }
+ v.reset(OpPPC64ROTLconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SLWconst x [c]) (SRWconst x [d]))
+ // cond: d == 32-c
+ // result: (ROTLWconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLWconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpPPC64SRWconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 32-c) {
+ continue
+ }
+ v.reset(OpPPC64ROTLWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y))))
+ // result: (ROTL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLD {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int64 || auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRD {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUB || v_1_1.Type != typ.UInt {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpPPC64ANDconst || v_1_1_1.Type != typ.UInt || auxIntToInt64(v_1_1_1.AuxInt) != 63 || y != v_1_1_1.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y))))
+ // result: (ROTL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLD {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int64 || auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRD {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUBFCconst || v_1_1.Type != typ.UInt || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64ANDconst || v_1_1_0.Type != typ.UInt || auxIntToInt64(v_1_1_0.AuxInt) != 63 || y != v_1_1_0.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y))))
+ // result: (ROTLW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLW {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int32 || auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRW {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUBFCconst || v_1_1.Type != typ.UInt || auxIntToInt64(v_1_1.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64ANDconst || v_1_1_0.Type != typ.UInt || auxIntToInt64(v_1_1_0.AuxInt) != 31 || y != v_1_1_0.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y))))
+ // result: (ROTLW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLW {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int32 || auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRW {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUB || v_1_1.Type != typ.UInt {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpPPC64ANDconst || v_1_1_1.Type != typ.UInt || auxIntToInt64(v_1_1_1.AuxInt) != 31 || y != v_1_1_1.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (MOVDconst [c]))
+ // cond: is32Bit(c)
+ // result: (ADDconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpPPC64ADDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64ADDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDconst [c] (ADDconst [d] x))
+ // cond: is32Bit(c+d)
+ // result: (ADDconst [c+d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(c + d)) {
+ break
+ }
+ v.reset(OpPPC64ADDconst)
+ v.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ADDconst [c] (MOVDaddr [d] {sym} x))
+ // cond: is32Bit(c+int64(d))
+ // result: (MOVDaddr [int32(c+int64(d))] {sym} x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDaddr {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ if !(is32Bit(c + int64(d))) {
+ break
+ }
+ v.reset(OpPPC64MOVDaddr)
+ v.AuxInt = int32ToAuxInt(int32(c + int64(d)))
+ v.Aux = symToAux(sym)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [c] x:(SP))
+ // cond: is32Bit(c)
+ // result: (MOVDaddr [int32(c)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if x.Op != OpSP || !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVDaddr)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [c] (SUBFCconst [d] x))
+ // cond: is32Bit(c+d)
+ // result: (SUBFCconst [c+d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64SUBFCconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(c + d)) {
+ break
+ }
+ v.reset(OpPPC64SUBFCconst)
+ v.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64AND(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AND (MOVDconst [m]) (ROTLWconst [r] x))
+ // cond: isPPC64WordRotateMask(m)
+ // result: (RLWINM [encodePPC64RotateMask(r,m,32)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpPPC64ROTLWconst {
+ continue
+ }
+ r := auxIntToInt64(v_1.AuxInt)
+ x := v_1.Args[0]
+ if !(isPPC64WordRotateMask(m)) {
+ continue
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(encodePPC64RotateMask(r, m, 32))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVDconst [m]) (ROTLW x r))
+ // cond: isPPC64WordRotateMask(m)
+ // result: (RLWNM [encodePPC64RotateMask(0,m,32)] x r)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpPPC64ROTLW {
+ continue
+ }
+ r := v_1.Args[1]
+ x := v_1.Args[0]
+ if !(isPPC64WordRotateMask(m)) {
+ continue
+ }
+ v.reset(OpPPC64RLWNM)
+ v.AuxInt = int64ToAuxInt(encodePPC64RotateMask(0, m, 32))
+ v.AddArg2(x, r)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVDconst [m]) (SRWconst x [s]))
+ // cond: mergePPC64RShiftMask(m,s,32) == 0
+ // result: (MOVDconst [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpPPC64SRWconst {
+ continue
+ }
+ s := auxIntToInt64(v_1.AuxInt)
+ if !(mergePPC64RShiftMask(m, s, 32) == 0) {
+ continue
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVDconst [m]) (SRWconst x [s]))
+ // cond: mergePPC64AndSrwi(m,s) != 0
+ // result: (RLWINM [mergePPC64AndSrwi(m,s)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpPPC64SRWconst {
+ continue
+ }
+ s := auxIntToInt64(v_1.AuxInt)
+ x := v_1.Args[0]
+ if !(mergePPC64AndSrwi(m, s) != 0) {
+ continue
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(mergePPC64AndSrwi(m, s))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND x (NOR y y))
+ // result: (ANDN x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpPPC64NOR {
+ continue
+ }
+ y := v_1.Args[1]
+ if y != v_1.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ANDN)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [c&d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpPPC64MOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c & d)
+ return true
+ }
+ break
+ }
+ // match: (AND x (MOVDconst [c]))
+ // cond: isU16Bit(c)
+ // result: (ANDconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isU16Bit(c)) {
+ continue
+ }
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVDconst [c]) y:(MOVWZreg _))
+ // cond: c&0xFFFFFFFF == 0xFFFFFFFF
+ // result: y
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if y.Op != OpPPC64MOVWZreg || !(c&0xFFFFFFFF == 0xFFFFFFFF) {
+ continue
+ }
+ v.copyOf(y)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVDconst [0xFFFFFFFF]) y:(MOVWreg x))
+ // result: (MOVWZreg x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_0.AuxInt) != 0xFFFFFFFF {
+ continue
+ }
+ y := v_1
+ if y.Op != OpPPC64MOVWreg {
+ continue
+ }
+ x := y.Args[0]
+ v.reset(OpPPC64MOVWZreg)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVDconst [c]) x:(MOVBZload _ _))
+ // result: (ANDconst [c&0xFF] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if x.Op != OpPPC64MOVBZload {
+ continue
+ }
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & 0xFF)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64ANDN(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ANDN (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [c&^d])
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c &^ d)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64ANDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ANDconst [m] (ROTLWconst [r] x))
+ // cond: isPPC64WordRotateMask(m)
+ // result: (RLWINM [encodePPC64RotateMask(r,m,32)] x)
+ for {
+ m := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64ROTLWconst {
+ break
+ }
+ r := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isPPC64WordRotateMask(m)) {
+ break
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(encodePPC64RotateMask(r, m, 32))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [m] (ROTLW x r))
+ // cond: isPPC64WordRotateMask(m)
+ // result: (RLWNM [encodePPC64RotateMask(0,m,32)] x r)
+ for {
+ m := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64ROTLW {
+ break
+ }
+ r := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(isPPC64WordRotateMask(m)) {
+ break
+ }
+ v.reset(OpPPC64RLWNM)
+ v.AuxInt = int64ToAuxInt(encodePPC64RotateMask(0, m, 32))
+ v.AddArg2(x, r)
+ return true
+ }
+ // match: (ANDconst [m] (SRWconst x [s]))
+ // cond: mergePPC64RShiftMask(m,s,32) == 0
+ // result: (MOVDconst [0])
+ for {
+ m := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ s := auxIntToInt64(v_0.AuxInt)
+ if !(mergePPC64RShiftMask(m, s, 32) == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ANDconst [m] (SRWconst x [s]))
+ // cond: mergePPC64AndSrwi(m,s) != 0
+ // result: (RLWINM [mergePPC64AndSrwi(m,s)] x)
+ for {
+ m := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ s := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(mergePPC64AndSrwi(m, s) != 0) {
+ break
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(mergePPC64AndSrwi(m, s))
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] (ANDconst [d] x))
+ // result: (ANDconst [c&d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64ANDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [-1] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDconst [0] _)
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ANDconst [c] y:(MOVBZreg _))
+ // cond: c&0xFF == 0xFF
+ // result: y
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ y := v_0
+ if y.Op != OpPPC64MOVBZreg || !(c&0xFF == 0xFF) {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ANDconst [0xFF] y:(MOVBreg _))
+ // result: y
+ for {
+ if auxIntToInt64(v.AuxInt) != 0xFF {
+ break
+ }
+ y := v_0
+ if y.Op != OpPPC64MOVBreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ANDconst [c] y:(MOVHZreg _))
+ // cond: c&0xFFFF == 0xFFFF
+ // result: y
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ y := v_0
+ if y.Op != OpPPC64MOVHZreg || !(c&0xFFFF == 0xFFFF) {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ANDconst [0xFFFF] y:(MOVHreg _))
+ // result: y
+ for {
+ if auxIntToInt64(v.AuxInt) != 0xFFFF {
+ break
+ }
+ y := v_0
+ if y.Op != OpPPC64MOVHreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ANDconst [c] (MOVBreg x))
+ // result: (ANDconst [c&0xFF] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & 0xFF)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVBZreg x))
+ // result: (ANDconst [c&0xFF] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & 0xFF)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVHreg x))
+ // result: (ANDconst [c&0xFFFF] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & 0xFFFF)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVHZreg x))
+ // result: (ANDconst [c&0xFFFF] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & 0xFFFF)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVWreg x))
+ // result: (ANDconst [c&0xFFFFFFFF] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & 0xFFFFFFFF)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVWZreg x))
+ // result: (ANDconst [c&0xFFFFFFFF] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(c & 0xFFFFFFFF)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64CLRLSLDI(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CLRLSLDI [c] (SRWconst [s] x))
+ // cond: mergePPC64ClrlsldiSrw(int64(c),s) != 0
+ // result: (RLWINM [mergePPC64ClrlsldiSrw(int64(c),s)] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ s := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(mergePPC64ClrlsldiSrw(int64(c), s) != 0) {
+ break
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(mergePPC64ClrlsldiSrw(int64(c), s))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CLRLSLDI [c] i:(RLWINM [s] x))
+ // cond: mergePPC64ClrlsldiRlwinm(c,s) != 0
+ // result: (RLWINM [mergePPC64ClrlsldiRlwinm(c,s)] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ i := v_0
+ if i.Op != OpPPC64RLWINM {
+ break
+ }
+ s := auxIntToInt64(i.AuxInt)
+ x := i.Args[0]
+ if !(mergePPC64ClrlsldiRlwinm(c, s) != 0) {
+ break
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(mergePPC64ClrlsldiRlwinm(c, s))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64CMP(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMP x (MOVDconst [c]))
+ // cond: is16Bit(c)
+ // result: (CMPconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64CMPconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMP (MOVDconst [c]) y)
+ // cond: is16Bit(c)
+ // result: (InvertFlags (CMPconst y [c]))
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMP y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpPPC64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMP, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64CMPU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPU x (MOVDconst [c]))
+ // cond: isU16Bit(c)
+ // result: (CMPUconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isU16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64CMPUconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPU (MOVDconst [c]) y)
+ // cond: isU16Bit(c)
+ // result: (InvertFlags (CMPUconst y [c]))
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(isU16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPUconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPU x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPU y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpPPC64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64CMPUconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPUconst (MOVDconst [x]) [y])
+ // cond: x==y
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x == y) {
+ break
+ }
+ v.reset(OpPPC64FlagEQ)
+ return true
+ }
+ // match: (CMPUconst (MOVDconst [x]) [y])
+ // cond: uint64(x)<uint64(y)
+ // result: (FlagLT)
+ for {
+ y := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(uint64(x) < uint64(y)) {
+ break
+ }
+ v.reset(OpPPC64FlagLT)
+ return true
+ }
+ // match: (CMPUconst (MOVDconst [x]) [y])
+ // cond: uint64(x)>uint64(y)
+ // result: (FlagGT)
+ for {
+ y := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(uint64(x) > uint64(y)) {
+ break
+ }
+ v.reset(OpPPC64FlagGT)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64CMPW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPW x (MOVWreg y))
+ // result: (CMPW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVWreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpPPC64CMPW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPW (MOVWreg x) y)
+ // result: (CMPW x y)
+ for {
+ if v_0.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpPPC64CMPW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPW x (MOVDconst [c]))
+ // cond: is16Bit(c)
+ // result: (CMPWconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64CMPWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPW (MOVDconst [c]) y)
+ // cond: is16Bit(c)
+ // result: (InvertFlags (CMPWconst y [int32(c)]))
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPW x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPW y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpPPC64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPW, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64CMPWU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPWU x (MOVWZreg y))
+ // result: (CMPWU x y)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVWZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpPPC64CMPWU)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPWU (MOVWZreg x) y)
+ // result: (CMPWU x y)
+ for {
+ if v_0.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpPPC64CMPWU)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPWU x (MOVDconst [c]))
+ // cond: isU16Bit(c)
+ // result: (CMPWUconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isU16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64CMPWUconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPWU (MOVDconst [c]) y)
+ // cond: isU16Bit(c)
+ // result: (InvertFlags (CMPWUconst y [int32(c)]))
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(isU16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPWUconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPWU x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPWU y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpPPC64InvertFlags)
+ v0 := b.NewValue0(v.Pos, OpPPC64CMPWU, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64CMPWUconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPWUconst (MOVDconst [x]) [y])
+ // cond: int32(x)==int32(y)
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(int32(x) == int32(y)) {
+ break
+ }
+ v.reset(OpPPC64FlagEQ)
+ return true
+ }
+ // match: (CMPWUconst (MOVDconst [x]) [y])
+ // cond: uint32(x)<uint32(y)
+ // result: (FlagLT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(uint32(x) < uint32(y)) {
+ break
+ }
+ v.reset(OpPPC64FlagLT)
+ return true
+ }
+ // match: (CMPWUconst (MOVDconst [x]) [y])
+ // cond: uint32(x)>uint32(y)
+ // result: (FlagGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(uint32(x) > uint32(y)) {
+ break
+ }
+ v.reset(OpPPC64FlagGT)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64CMPWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPWconst (MOVDconst [x]) [y])
+ // cond: int32(x)==int32(y)
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(int32(x) == int32(y)) {
+ break
+ }
+ v.reset(OpPPC64FlagEQ)
+ return true
+ }
+ // match: (CMPWconst (MOVDconst [x]) [y])
+ // cond: int32(x)<int32(y)
+ // result: (FlagLT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(int32(x) < int32(y)) {
+ break
+ }
+ v.reset(OpPPC64FlagLT)
+ return true
+ }
+ // match: (CMPWconst (MOVDconst [x]) [y])
+ // cond: int32(x)>int32(y)
+ // result: (FlagGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(int32(x) > int32(y)) {
+ break
+ }
+ v.reset(OpPPC64FlagGT)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64CMPconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPconst (MOVDconst [x]) [y])
+ // cond: x==y
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x == y) {
+ break
+ }
+ v.reset(OpPPC64FlagEQ)
+ return true
+ }
+ // match: (CMPconst (MOVDconst [x]) [y])
+ // cond: x<y
+ // result: (FlagLT)
+ for {
+ y := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x < y) {
+ break
+ }
+ v.reset(OpPPC64FlagLT)
+ return true
+ }
+ // match: (CMPconst (MOVDconst [x]) [y])
+ // cond: x>y
+ // result: (FlagGT)
+ for {
+ y := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x > y) {
+ break
+ }
+ v.reset(OpPPC64FlagGT)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64Equal(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Equal (FlagEQ))
+ // result: (MOVDconst [1])
+ for {
+ if v_0.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (Equal (FlagLT))
+ // result: (MOVDconst [0])
+ for {
+ if v_0.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Equal (FlagGT))
+ // result: (MOVDconst [0])
+ for {
+ if v_0.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Equal (InvertFlags x))
+ // result: (Equal x)
+ for {
+ if v_0.Op != OpPPC64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64Equal)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Equal cmp)
+ // result: (ISELB [2] (MOVDconst [1]) cmp)
+ for {
+ cmp := v_0
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, cmp)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64FABS(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (FABS (FMOVDconst [x]))
+ // result: (FMOVDconst [math.Abs(x)])
+ for {
+ if v_0.Op != OpPPC64FMOVDconst {
+ break
+ }
+ x := auxIntToFloat64(v_0.AuxInt)
+ v.reset(OpPPC64FMOVDconst)
+ v.AuxInt = float64ToAuxInt(math.Abs(x))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FADD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FADD (FMUL x y) z)
+ // result: (FMADD x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64FMUL {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_1
+ v.reset(OpPPC64FMADD)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FADDS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FADDS (FMULS x y) z)
+ // result: (FMADDS x y z)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64FMULS {
+ continue
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_1
+ v.reset(OpPPC64FMADDS)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FCEIL(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (FCEIL (FMOVDconst [x]))
+ // result: (FMOVDconst [math.Ceil(x)])
+ for {
+ if v_0.Op != OpPPC64FMOVDconst {
+ break
+ }
+ x := auxIntToFloat64(v_0.AuxInt)
+ v.reset(OpPPC64FMOVDconst)
+ v.AuxInt = float64ToAuxInt(math.Ceil(x))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FFLOOR(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (FFLOOR (FMOVDconst [x]))
+ // result: (FMOVDconst [math.Floor(x)])
+ for {
+ if v_0.Op != OpPPC64FMOVDconst {
+ break
+ }
+ x := auxIntToFloat64(v_0.AuxInt)
+ v.reset(OpPPC64FMOVDconst)
+ v.AuxInt = float64ToAuxInt(math.Floor(x))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FGreaterEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (FGreaterEqual cmp)
+ // result: (ISEL [2] (MOVDconst [1]) (ISELB [1] (MOVDconst [1]) cmp) cmp)
+ for {
+ cmp := v_0
+ v.reset(OpPPC64ISEL)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISELB, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(1)
+ v1.AddArg2(v0, cmp)
+ v.AddArg3(v0, v1, cmp)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64FGreaterThan(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (FGreaterThan cmp)
+ // result: (ISELB [1] (MOVDconst [1]) cmp)
+ for {
+ cmp := v_0
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, cmp)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64FLessEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (FLessEqual cmp)
+ // result: (ISEL [2] (MOVDconst [1]) (ISELB [0] (MOVDconst [1]) cmp) cmp)
+ for {
+ cmp := v_0
+ v.reset(OpPPC64ISEL)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISELB, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg2(v0, cmp)
+ v.AddArg3(v0, v1, cmp)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64FLessThan(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (FLessThan cmp)
+ // result: (ISELB [0] (MOVDconst [1]) cmp)
+ for {
+ cmp := v_0
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, cmp)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64FMOVDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVDload [off] {sym} ptr (MOVDstore [off] {sym} ptr x _))
+ // result: (MTVSRD x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ v.reset(OpPPC64MTVSRD)
+ v.AddArg(x)
+ return true
+ }
+ // match: (FMOVDload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64FMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (FMOVDload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64FMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FMOVDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVDstore [off] {sym} ptr (MTVSRD x) mem)
+ // result: (MOVDstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MTVSRD {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVDstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (FMOVDstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64FMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (FMOVDstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64FMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FMOVSload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVSload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64FMOVSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (FMOVSload [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64FMOVSload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FMOVSstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (FMOVSstore [off1+int32(off2)] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64FMOVSstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (FMOVSstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64FMOVSstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FNEG(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (FNEG (FABS x))
+ // result: (FNABS x)
+ for {
+ if v_0.Op != OpPPC64FABS {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64FNABS)
+ v.AddArg(x)
+ return true
+ }
+ // match: (FNEG (FNABS x))
+ // result: (FABS x)
+ for {
+ if v_0.Op != OpPPC64FNABS {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64FABS)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FSQRT(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (FSQRT (FMOVDconst [x]))
+ // cond: x >= 0
+ // result: (FMOVDconst [math.Sqrt(x)])
+ for {
+ if v_0.Op != OpPPC64FMOVDconst {
+ break
+ }
+ x := auxIntToFloat64(v_0.AuxInt)
+ if !(x >= 0) {
+ break
+ }
+ v.reset(OpPPC64FMOVDconst)
+ v.AuxInt = float64ToAuxInt(math.Sqrt(x))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FSUB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FSUB (FMUL x y) z)
+ // result: (FMSUB x y z)
+ for {
+ if v_0.Op != OpPPC64FMUL {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_1
+ v.reset(OpPPC64FMSUB)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FSUBS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FSUBS (FMULS x y) z)
+ // result: (FMSUBS x y z)
+ for {
+ if v_0.Op != OpPPC64FMULS {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ z := v_1
+ v.reset(OpPPC64FMSUBS)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64FTRUNC(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (FTRUNC (FMOVDconst [x]))
+ // result: (FMOVDconst [math.Trunc(x)])
+ for {
+ if v_0.Op != OpPPC64FMOVDconst {
+ break
+ }
+ x := auxIntToFloat64(v_0.AuxInt)
+ v.reset(OpPPC64FMOVDconst)
+ v.AuxInt = float64ToAuxInt(math.Trunc(x))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64GreaterEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (GreaterEqual (FlagEQ))
+ // result: (MOVDconst [1])
+ for {
+ if v_0.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (GreaterEqual (FlagLT))
+ // result: (MOVDconst [0])
+ for {
+ if v_0.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (GreaterEqual (FlagGT))
+ // result: (MOVDconst [1])
+ for {
+ if v_0.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (GreaterEqual (InvertFlags x))
+ // result: (LessEqual x)
+ for {
+ if v_0.Op != OpPPC64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64LessEqual)
+ v.AddArg(x)
+ return true
+ }
+ // match: (GreaterEqual cmp)
+ // result: (ISELB [4] (MOVDconst [1]) cmp)
+ for {
+ cmp := v_0
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, cmp)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64GreaterThan(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (GreaterThan (FlagEQ))
+ // result: (MOVDconst [0])
+ for {
+ if v_0.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (GreaterThan (FlagLT))
+ // result: (MOVDconst [0])
+ for {
+ if v_0.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (GreaterThan (FlagGT))
+ // result: (MOVDconst [1])
+ for {
+ if v_0.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (GreaterThan (InvertFlags x))
+ // result: (LessThan x)
+ for {
+ if v_0.Op != OpPPC64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64LessThan)
+ v.AddArg(x)
+ return true
+ }
+ // match: (GreaterThan cmp)
+ // result: (ISELB [1] (MOVDconst [1]) cmp)
+ for {
+ cmp := v_0
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, cmp)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64ISEL(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ISEL [0] (ANDconst [d] y) (MOVDconst [-1]) (CMPU (ANDconst [d] y) (MOVDconst [c])))
+ // cond: c >= d
+ // result: (ANDconst [d] y)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 || v_0.Op != OpPPC64ANDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ y := v_0.Args[0]
+ if v_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 || v_2.Op != OpPPC64CMPU {
+ break
+ }
+ _ = v_2.Args[1]
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpPPC64ANDconst || auxIntToInt64(v_2_0.AuxInt) != d || y != v_2_0.Args[0] {
+ break
+ }
+ v_2_1 := v_2.Args[1]
+ if v_2_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_2_1.AuxInt)
+ if !(c >= d) {
+ break
+ }
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(d)
+ v.AddArg(y)
+ return true
+ }
+ // match: (ISEL [0] (ANDconst [d] y) (MOVDconst [-1]) (CMPUconst [c] (ANDconst [d] y)))
+ // cond: c >= d
+ // result: (ANDconst [d] y)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 || v_0.Op != OpPPC64ANDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ y := v_0.Args[0]
+ if v_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 || v_2.Op != OpPPC64CMPUconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpPPC64ANDconst || auxIntToInt64(v_2_0.AuxInt) != d || y != v_2_0.Args[0] || !(c >= d) {
+ break
+ }
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = int64ToAuxInt(d)
+ v.AddArg(y)
+ return true
+ }
+ // match: (ISEL [2] x _ (FlagEQ))
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ x := v_0
+ if v_2.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ISEL [2] _ y (FlagLT))
+ // result: y
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ y := v_1
+ if v_2.Op != OpPPC64FlagLT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ISEL [2] _ y (FlagGT))
+ // result: y
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 {
+ break
+ }
+ y := v_1
+ if v_2.Op != OpPPC64FlagGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ISEL [6] _ y (FlagEQ))
+ // result: y
+ for {
+ if auxIntToInt32(v.AuxInt) != 6 {
+ break
+ }
+ y := v_1
+ if v_2.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ISEL [6] x _ (FlagLT))
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 6 {
+ break
+ }
+ x := v_0
+ if v_2.Op != OpPPC64FlagLT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ISEL [6] x _ (FlagGT))
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 6 {
+ break
+ }
+ x := v_0
+ if v_2.Op != OpPPC64FlagGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ISEL [0] _ y (FlagEQ))
+ // result: y
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ y := v_1
+ if v_2.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ISEL [0] _ y (FlagGT))
+ // result: y
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ y := v_1
+ if v_2.Op != OpPPC64FlagGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ISEL [0] x _ (FlagLT))
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ if v_2.Op != OpPPC64FlagLT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ISEL [5] _ x (FlagEQ))
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 5 {
+ break
+ }
+ x := v_1
+ if v_2.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ISEL [5] _ x (FlagLT))
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 5 {
+ break
+ }
+ x := v_1
+ if v_2.Op != OpPPC64FlagLT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ISEL [5] y _ (FlagGT))
+ // result: y
+ for {
+ if auxIntToInt32(v.AuxInt) != 5 {
+ break
+ }
+ y := v_0
+ if v_2.Op != OpPPC64FlagGT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ISEL [1] _ y (FlagEQ))
+ // result: y
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ y := v_1
+ if v_2.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ISEL [1] _ y (FlagLT))
+ // result: y
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ y := v_1
+ if v_2.Op != OpPPC64FlagLT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ISEL [1] x _ (FlagGT))
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 {
+ break
+ }
+ x := v_0
+ if v_2.Op != OpPPC64FlagGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ISEL [4] x _ (FlagEQ))
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 {
+ break
+ }
+ x := v_0
+ if v_2.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ISEL [4] x _ (FlagGT))
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 {
+ break
+ }
+ x := v_0
+ if v_2.Op != OpPPC64FlagGT {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ISEL [4] _ y (FlagLT))
+ // result: y
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 {
+ break
+ }
+ y := v_1
+ if v_2.Op != OpPPC64FlagLT {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (ISEL [n] x y (InvertFlags bool))
+ // cond: n%4 == 0
+ // result: (ISEL [n+1] x y bool)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ x := v_0
+ y := v_1
+ if v_2.Op != OpPPC64InvertFlags {
+ break
+ }
+ bool := v_2.Args[0]
+ if !(n%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64ISEL)
+ v.AuxInt = int32ToAuxInt(n + 1)
+ v.AddArg3(x, y, bool)
+ return true
+ }
+ // match: (ISEL [n] x y (InvertFlags bool))
+ // cond: n%4 == 1
+ // result: (ISEL [n-1] x y bool)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ x := v_0
+ y := v_1
+ if v_2.Op != OpPPC64InvertFlags {
+ break
+ }
+ bool := v_2.Args[0]
+ if !(n%4 == 1) {
+ break
+ }
+ v.reset(OpPPC64ISEL)
+ v.AuxInt = int32ToAuxInt(n - 1)
+ v.AddArg3(x, y, bool)
+ return true
+ }
+ // match: (ISEL [n] x y (InvertFlags bool))
+ // cond: n%4 == 2
+ // result: (ISEL [n] x y bool)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ x := v_0
+ y := v_1
+ if v_2.Op != OpPPC64InvertFlags {
+ break
+ }
+ bool := v_2.Args[0]
+ if !(n%4 == 2) {
+ break
+ }
+ v.reset(OpPPC64ISEL)
+ v.AuxInt = int32ToAuxInt(n)
+ v.AddArg3(x, y, bool)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64ISELB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ISELB [0] _ (FlagLT))
+ // result: (MOVDconst [1])
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 || v_1.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (ISELB [0] _ (FlagGT))
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 || v_1.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ISELB [0] _ (FlagEQ))
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 || v_1.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ISELB [1] _ (FlagGT))
+ // result: (MOVDconst [1])
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_1.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (ISELB [1] _ (FlagLT))
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_1.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ISELB [1] _ (FlagEQ))
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 1 || v_1.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ISELB [2] _ (FlagEQ))
+ // result: (MOVDconst [1])
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 || v_1.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (ISELB [2] _ (FlagLT))
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 || v_1.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ISELB [2] _ (FlagGT))
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 2 || v_1.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ISELB [4] _ (FlagLT))
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 || v_1.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ISELB [4] _ (FlagGT))
+ // result: (MOVDconst [1])
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 || v_1.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (ISELB [4] _ (FlagEQ))
+ // result: (MOVDconst [1])
+ for {
+ if auxIntToInt32(v.AuxInt) != 4 || v_1.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (ISELB [5] _ (FlagGT))
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 5 || v_1.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ISELB [5] _ (FlagLT))
+ // result: (MOVDconst [1])
+ for {
+ if auxIntToInt32(v.AuxInt) != 5 || v_1.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (ISELB [5] _ (FlagEQ))
+ // result: (MOVDconst [1])
+ for {
+ if auxIntToInt32(v.AuxInt) != 5 || v_1.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (ISELB [6] _ (FlagEQ))
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt32(v.AuxInt) != 6 || v_1.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ISELB [6] _ (FlagLT))
+ // result: (MOVDconst [1])
+ for {
+ if auxIntToInt32(v.AuxInt) != 6 || v_1.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (ISELB [6] _ (FlagGT))
+ // result: (MOVDconst [1])
+ for {
+ if auxIntToInt32(v.AuxInt) != 6 || v_1.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (ISELB [n] (MOVDconst [1]) (InvertFlags bool))
+ // cond: n%4 == 0
+ // result: (ISELB [n+1] (MOVDconst [1]) bool)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_0.AuxInt) != 1 || v_1.Op != OpPPC64InvertFlags {
+ break
+ }
+ bool := v_1.Args[0]
+ if !(n%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(n + 1)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, bool)
+ return true
+ }
+ // match: (ISELB [n] (MOVDconst [1]) (InvertFlags bool))
+ // cond: n%4 == 1
+ // result: (ISELB [n-1] (MOVDconst [1]) bool)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_0.AuxInt) != 1 || v_1.Op != OpPPC64InvertFlags {
+ break
+ }
+ bool := v_1.Args[0]
+ if !(n%4 == 1) {
+ break
+ }
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(n - 1)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, bool)
+ return true
+ }
+ // match: (ISELB [n] (MOVDconst [1]) (InvertFlags bool))
+ // cond: n%4 == 2
+ // result: (ISELB [n] (MOVDconst [1]) bool)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_0.AuxInt) != 1 || v_1.Op != OpPPC64InvertFlags {
+ break
+ }
+ bool := v_1.Args[0]
+ if !(n%4 == 2) {
+ break
+ }
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(n)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, bool)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64LessEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (LessEqual (FlagEQ))
+ // result: (MOVDconst [1])
+ for {
+ if v_0.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (LessEqual (FlagLT))
+ // result: (MOVDconst [1])
+ for {
+ if v_0.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (LessEqual (FlagGT))
+ // result: (MOVDconst [0])
+ for {
+ if v_0.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (LessEqual (InvertFlags x))
+ // result: (GreaterEqual x)
+ for {
+ if v_0.Op != OpPPC64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64GreaterEqual)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LessEqual cmp)
+ // result: (ISELB [5] (MOVDconst [1]) cmp)
+ for {
+ cmp := v_0
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(5)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, cmp)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64LessThan(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (LessThan (FlagEQ))
+ // result: (MOVDconst [0])
+ for {
+ if v_0.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (LessThan (FlagLT))
+ // result: (MOVDconst [1])
+ for {
+ if v_0.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (LessThan (FlagGT))
+ // result: (MOVDconst [0])
+ for {
+ if v_0.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (LessThan (InvertFlags x))
+ // result: (GreaterThan x)
+ for {
+ if v_0.Op != OpPPC64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64GreaterThan)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LessThan cmp)
+ // result: (ISELB [0] (MOVDconst [1]) cmp)
+ for {
+ cmp := v_0
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(0)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, cmp)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64MFVSRD(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MFVSRD (FMOVDconst [c]))
+ // result: (MOVDconst [int64(math.Float64bits(c))])
+ for {
+ if v_0.Op != OpPPC64FMOVDconst {
+ break
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(math.Float64bits(c)))
+ return true
+ }
+ // match: (MFVSRD x:(FMOVDload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVDload [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpPPC64FMOVDload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpPPC64MOVDload, typ.Int64)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBZload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBZload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (MOVBZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64MOVBZload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBZload [off1] {sym} (ADDconst [off2] x) mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (MOVBZload [off1+int32(off2)] {sym} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64MOVBZload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, mem)
+ return true
+ }
+ // match: (MOVBZload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVBZloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ idx := p.Args[1]
+ ptr := p.Args[0]
+ mem := v_1
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVBZloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBZloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBZloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c)
+ // result: (MOVBZload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVBZload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBZloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c)
+ // result: (MOVBZload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVBZload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBZreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVBZreg y:(ANDconst [c] _))
+ // cond: uint64(c) <= 0xFF
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(y.AuxInt)
+ if !(uint64(c) <= 0xFF) {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVBZreg (SRWconst [c] (MOVBZreg x)))
+ // result: (SRWconst [c] (MOVBZreg x))
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVBZreg (SRWconst [c] x))
+ // cond: sizeof(x.Type) == 8
+ // result: (SRWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) == 8) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg (SRDconst [c] x))
+ // cond: c>=56
+ // result: (SRDconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c >= 56) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg (SRWconst [c] x))
+ // cond: c>=24
+ // result: (SRWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c >= 24) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg y:(MOVBZreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVBZreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVBZreg (MOVBreg x))
+ // result: (MOVBZreg x)
+ for {
+ if v_0.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg (OR <t> x (MOVWZreg y)))
+ // result: (MOVBZreg (OR <t> x y))
+ for {
+ if v_0.Op != OpPPC64OR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVWZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64OR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVBZreg (XOR <t> x (MOVWZreg y)))
+ // result: (MOVBZreg (XOR <t> x y))
+ for {
+ if v_0.Op != OpPPC64XOR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVWZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64XOR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVBZreg (AND <t> x (MOVWZreg y)))
+ // result: (MOVBZreg (AND <t> x y))
+ for {
+ if v_0.Op != OpPPC64AND {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVWZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64AND, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVBZreg (OR <t> x (MOVHZreg y)))
+ // result: (MOVBZreg (OR <t> x y))
+ for {
+ if v_0.Op != OpPPC64OR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVHZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64OR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVBZreg (XOR <t> x (MOVHZreg y)))
+ // result: (MOVBZreg (XOR <t> x y))
+ for {
+ if v_0.Op != OpPPC64XOR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVHZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64XOR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVBZreg (AND <t> x (MOVHZreg y)))
+ // result: (MOVBZreg (AND <t> x y))
+ for {
+ if v_0.Op != OpPPC64AND {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVHZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64AND, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVBZreg (OR <t> x (MOVBZreg y)))
+ // result: (MOVBZreg (OR <t> x y))
+ for {
+ if v_0.Op != OpPPC64OR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVBZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64OR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVBZreg (XOR <t> x (MOVBZreg y)))
+ // result: (MOVBZreg (XOR <t> x y))
+ for {
+ if v_0.Op != OpPPC64XOR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVBZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64XOR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVBZreg (AND <t> x (MOVBZreg y)))
+ // result: (MOVBZreg (AND <t> x y))
+ for {
+ if v_0.Op != OpPPC64AND {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVBZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64AND, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVBZreg z:(ANDconst [c] (MOVBZload ptr x)))
+ // result: z
+ for {
+ z := v_0
+ if z.Op != OpPPC64ANDconst {
+ break
+ }
+ z_0 := z.Args[0]
+ if z_0.Op != OpPPC64MOVBZload {
+ break
+ }
+ v.copyOf(z)
+ return true
+ }
+ // match: (MOVBZreg z:(AND y (MOVBZload ptr x)))
+ // result: z
+ for {
+ z := v_0
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ if z_1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ v.copyOf(z)
+ return true
+ }
+ break
+ }
+ // match: (MOVBZreg x:(MOVBZload _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVBZload {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVBZreg x:(MOVBZloadidx _ _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVBZloadidx {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVBZreg x:(Arg <t>))
+ // cond: is8BitInt(t) && !isSigned(t)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !(is8BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVBZreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(uint8(c))])
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVBreg y:(ANDconst [c] _))
+ // cond: uint64(c) <= 0x7F
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(y.AuxInt)
+ if !(uint64(c) <= 0x7F) {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVBreg (SRAWconst [c] (MOVBreg x)))
+ // result: (SRAWconst [c] (MOVBreg x))
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVBreg (SRAWconst [c] x))
+ // cond: sizeof(x.Type) == 8
+ // result: (SRAWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) == 8) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (SRDconst [c] x))
+ // cond: c>56
+ // result: (SRDconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c > 56) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (SRDconst [c] x))
+ // cond: c==56
+ // result: (SRADconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c == 56) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (SRADconst [c] x))
+ // cond: c>=56
+ // result: (SRADconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRADconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c >= 56) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (SRWconst [c] x))
+ // cond: c>24
+ // result: (SRWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c > 24) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (SRWconst [c] x))
+ // cond: c==24
+ // result: (SRAWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c == 24) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (SRAWconst [c] x))
+ // cond: c>=24
+ // result: (SRAWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c >= 24) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg y:(MOVBreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVBreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVBreg (MOVBZreg x))
+ // result: (MOVBreg x)
+ for {
+ if v_0.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64MOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg x:(Arg <t>))
+ // cond: is8BitInt(t) && isSigned(t)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !(is8BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVBreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(int8(c))])
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int8(c)))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (MOVBstore [off1] {sym} (ADDconst [off2] x) val mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (MOVBstore [off1+int32(off2)] {sym} x val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // result: (MOVBstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpPPC64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstore [0] {sym} p:(ADD ptr idx) val mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVBstoreidx ptr idx val mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ idx := p.Args[1]
+ ptr := p.Args[0]
+ val := v_1
+ mem := v_2
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBZreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHZreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVWZreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (SRWconst (MOVHreg x) [c]) mem)
+ // cond: c <= 8
+ // result: (MOVBstore [off] {sym} ptr (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_1_0.Args[0]
+ mem := v_2
+ if !(c <= 8) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (SRWconst (MOVHZreg x) [c]) mem)
+ // cond: c <= 8
+ // result: (MOVBstore [off] {sym} ptr (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_1_0.Args[0]
+ mem := v_2
+ if !(c <= 8) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (SRWconst (MOVWreg x) [c]) mem)
+ // cond: c <= 24
+ // result: (MOVBstore [off] {sym} ptr (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_1_0.Args[0]
+ mem := v_2
+ if !(c <= 24) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (SRWconst (MOVWZreg x) [c]) mem)
+ // cond: c <= 24
+ // result: (MOVBstore [off] {sym} ptr (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_1_0.Args[0]
+ mem := v_2
+ if !(c <= 24) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [i1] {s} p (SRWconst w [24]) x0:(MOVBstore [i0] {s} p (SRWconst w [16]) mem))
+ // cond: !config.BigEndian && x0.Uses == 1 && i1 == i0+1 && clobber(x0)
+ // result: (MOVHstore [i0] {s} p (SRWconst <typ.UInt16> w [16]) mem)
+ for {
+ i1 := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpPPC64SRWconst || auxIntToInt64(v_1.AuxInt) != 24 {
+ break
+ }
+ w := v_1.Args[0]
+ x0 := v_2
+ if x0.Op != OpPPC64MOVBstore {
+ break
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpPPC64SRWconst || auxIntToInt64(x0_1.AuxInt) != 16 || w != x0_1.Args[0] || !(!config.BigEndian && x0.Uses == 1 && i1 == i0+1 && clobber(x0)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i0)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x0.Pos, OpPPC64SRWconst, typ.UInt16)
+ v0.AuxInt = int64ToAuxInt(16)
+ v0.AddArg(w)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [i1] {s} p (SRDconst w [24]) x0:(MOVBstore [i0] {s} p (SRDconst w [16]) mem))
+ // cond: !config.BigEndian && x0.Uses == 1 && i1 == i0+1 && clobber(x0)
+ // result: (MOVHstore [i0] {s} p (SRWconst <typ.UInt16> w [16]) mem)
+ for {
+ i1 := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpPPC64SRDconst || auxIntToInt64(v_1.AuxInt) != 24 {
+ break
+ }
+ w := v_1.Args[0]
+ x0 := v_2
+ if x0.Op != OpPPC64MOVBstore {
+ break
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpPPC64SRDconst || auxIntToInt64(x0_1.AuxInt) != 16 || w != x0_1.Args[0] || !(!config.BigEndian && x0.Uses == 1 && i1 == i0+1 && clobber(x0)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i0)
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x0.Pos, OpPPC64SRWconst, typ.UInt16)
+ v0.AuxInt = int64ToAuxInt(16)
+ v0.AddArg(w)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ // match: (MOVBstore [i1] {s} p (SRWconst w [8]) x0:(MOVBstore [i0] {s} p w mem))
+ // cond: !config.BigEndian && x0.Uses == 1 && i1 == i0+1 && clobber(x0)
+ // result: (MOVHstore [i0] {s} p w mem)
+ for {
+ i1 := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpPPC64SRWconst || auxIntToInt64(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x0 := v_2
+ if x0.Op != OpPPC64MOVBstore {
+ break
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ if p != x0.Args[0] || w != x0.Args[1] || !(!config.BigEndian && x0.Uses == 1 && i1 == i0+1 && clobber(x0)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i0)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i1] {s} p (SRDconst w [8]) x0:(MOVBstore [i0] {s} p w mem))
+ // cond: !config.BigEndian && x0.Uses == 1 && i1 == i0+1 && clobber(x0)
+ // result: (MOVHstore [i0] {s} p w mem)
+ for {
+ i1 := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpPPC64SRDconst || auxIntToInt64(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x0 := v_2
+ if x0.Op != OpPPC64MOVBstore {
+ break
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ if p != x0.Args[0] || w != x0.Args[1] || !(!config.BigEndian && x0.Uses == 1 && i1 == i0+1 && clobber(x0)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(i0)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i3] {s} p w x0:(MOVBstore [i2] {s} p (SRWconst w [8]) x1:(MOVBstore [i1] {s} p (SRWconst w [16]) x2:(MOVBstore [i0] {s} p (SRWconst w [24]) mem))))
+ // cond: !config.BigEndian && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && clobber(x0, x1, x2)
+ // result: (MOVWBRstore (MOVDaddr <typ.Uintptr> [i0] {s} p) w mem)
+ for {
+ i3 := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpPPC64MOVBstore {
+ break
+ }
+ i2 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpPPC64SRWconst || auxIntToInt64(x0_1.AuxInt) != 8 || w != x0_1.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpPPC64MOVBstore {
+ break
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ if p != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpPPC64SRWconst || auxIntToInt64(x1_1.AuxInt) != 16 || w != x1_1.Args[0] {
+ break
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpPPC64MOVBstore {
+ break
+ }
+ i0 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ break
+ }
+ mem := x2.Args[2]
+ if p != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpPPC64SRWconst || auxIntToInt64(x2_1.AuxInt) != 24 || w != x2_1.Args[0] || !(!config.BigEndian && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && clobber(x0, x1, x2)) {
+ break
+ }
+ v.reset(OpPPC64MOVWBRstore)
+ v0 := b.NewValue0(x2.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg(p)
+ v.AddArg3(v0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i1] {s} p w x0:(MOVBstore [i0] {s} p (SRWconst w [8]) mem))
+ // cond: !config.BigEndian && x0.Uses == 1 && i1 == i0+1 && clobber(x0)
+ // result: (MOVHBRstore (MOVDaddr <typ.Uintptr> [i0] {s} p) w mem)
+ for {
+ i1 := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpPPC64MOVBstore {
+ break
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpPPC64SRWconst || auxIntToInt64(x0_1.AuxInt) != 8 || w != x0_1.Args[0] || !(!config.BigEndian && x0.Uses == 1 && i1 == i0+1 && clobber(x0)) {
+ break
+ }
+ v.reset(OpPPC64MOVHBRstore)
+ v0 := b.NewValue0(x0.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg(p)
+ v.AddArg3(v0, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i7] {s} p (SRDconst w [56]) x0:(MOVBstore [i6] {s} p (SRDconst w [48]) x1:(MOVBstore [i5] {s} p (SRDconst w [40]) x2:(MOVBstore [i4] {s} p (SRDconst w [32]) x3:(MOVWstore [i0] {s} p w mem)))))
+ // cond: !config.BigEndian && i0%4 == 0 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && clobber(x0, x1, x2, x3)
+ // result: (MOVDstore [i0] {s} p w mem)
+ for {
+ i7 := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpPPC64SRDconst || auxIntToInt64(v_1.AuxInt) != 56 {
+ break
+ }
+ w := v_1.Args[0]
+ x0 := v_2
+ if x0.Op != OpPPC64MOVBstore {
+ break
+ }
+ i6 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpPPC64SRDconst || auxIntToInt64(x0_1.AuxInt) != 48 || w != x0_1.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpPPC64MOVBstore {
+ break
+ }
+ i5 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ if p != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpPPC64SRDconst || auxIntToInt64(x1_1.AuxInt) != 40 || w != x1_1.Args[0] {
+ break
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpPPC64MOVBstore {
+ break
+ }
+ i4 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[2]
+ if p != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpPPC64SRDconst || auxIntToInt64(x2_1.AuxInt) != 32 || w != x2_1.Args[0] {
+ break
+ }
+ x3 := x2.Args[2]
+ if x3.Op != OpPPC64MOVWstore {
+ break
+ }
+ i0 := auxIntToInt32(x3.AuxInt)
+ if auxToSym(x3.Aux) != s {
+ break
+ }
+ mem := x3.Args[2]
+ if p != x3.Args[0] || w != x3.Args[1] || !(!config.BigEndian && i0%4 == 0 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && clobber(x0, x1, x2, x3)) {
+ break
+ }
+ v.reset(OpPPC64MOVDstore)
+ v.AuxInt = int32ToAuxInt(i0)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i7] {s} p w x0:(MOVBstore [i6] {s} p (SRDconst w [8]) x1:(MOVBstore [i5] {s} p (SRDconst w [16]) x2:(MOVBstore [i4] {s} p (SRDconst w [24]) x3:(MOVBstore [i3] {s} p (SRDconst w [32]) x4:(MOVBstore [i2] {s} p (SRDconst w [40]) x5:(MOVBstore [i1] {s} p (SRDconst w [48]) x6:(MOVBstore [i0] {s} p (SRDconst w [56]) mem))))))))
+ // cond: !config.BigEndian && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && clobber(x0, x1, x2, x3, x4, x5, x6)
+ // result: (MOVDBRstore (MOVDaddr <typ.Uintptr> [i0] {s} p) w mem)
+ for {
+ i7 := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x0 := v_2
+ if x0.Op != OpPPC64MOVBstore {
+ break
+ }
+ i6 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ break
+ }
+ _ = x0.Args[2]
+ if p != x0.Args[0] {
+ break
+ }
+ x0_1 := x0.Args[1]
+ if x0_1.Op != OpPPC64SRDconst || auxIntToInt64(x0_1.AuxInt) != 8 || w != x0_1.Args[0] {
+ break
+ }
+ x1 := x0.Args[2]
+ if x1.Op != OpPPC64MOVBstore {
+ break
+ }
+ i5 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ break
+ }
+ _ = x1.Args[2]
+ if p != x1.Args[0] {
+ break
+ }
+ x1_1 := x1.Args[1]
+ if x1_1.Op != OpPPC64SRDconst || auxIntToInt64(x1_1.AuxInt) != 16 || w != x1_1.Args[0] {
+ break
+ }
+ x2 := x1.Args[2]
+ if x2.Op != OpPPC64MOVBstore {
+ break
+ }
+ i4 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ break
+ }
+ _ = x2.Args[2]
+ if p != x2.Args[0] {
+ break
+ }
+ x2_1 := x2.Args[1]
+ if x2_1.Op != OpPPC64SRDconst || auxIntToInt64(x2_1.AuxInt) != 24 || w != x2_1.Args[0] {
+ break
+ }
+ x3 := x2.Args[2]
+ if x3.Op != OpPPC64MOVBstore {
+ break
+ }
+ i3 := auxIntToInt32(x3.AuxInt)
+ if auxToSym(x3.Aux) != s {
+ break
+ }
+ _ = x3.Args[2]
+ if p != x3.Args[0] {
+ break
+ }
+ x3_1 := x3.Args[1]
+ if x3_1.Op != OpPPC64SRDconst || auxIntToInt64(x3_1.AuxInt) != 32 || w != x3_1.Args[0] {
+ break
+ }
+ x4 := x3.Args[2]
+ if x4.Op != OpPPC64MOVBstore {
+ break
+ }
+ i2 := auxIntToInt32(x4.AuxInt)
+ if auxToSym(x4.Aux) != s {
+ break
+ }
+ _ = x4.Args[2]
+ if p != x4.Args[0] {
+ break
+ }
+ x4_1 := x4.Args[1]
+ if x4_1.Op != OpPPC64SRDconst || auxIntToInt64(x4_1.AuxInt) != 40 || w != x4_1.Args[0] {
+ break
+ }
+ x5 := x4.Args[2]
+ if x5.Op != OpPPC64MOVBstore {
+ break
+ }
+ i1 := auxIntToInt32(x5.AuxInt)
+ if auxToSym(x5.Aux) != s {
+ break
+ }
+ _ = x5.Args[2]
+ if p != x5.Args[0] {
+ break
+ }
+ x5_1 := x5.Args[1]
+ if x5_1.Op != OpPPC64SRDconst || auxIntToInt64(x5_1.AuxInt) != 48 || w != x5_1.Args[0] {
+ break
+ }
+ x6 := x5.Args[2]
+ if x6.Op != OpPPC64MOVBstore {
+ break
+ }
+ i0 := auxIntToInt32(x6.AuxInt)
+ if auxToSym(x6.Aux) != s {
+ break
+ }
+ mem := x6.Args[2]
+ if p != x6.Args[0] {
+ break
+ }
+ x6_1 := x6.Args[1]
+ if x6_1.Op != OpPPC64SRDconst || auxIntToInt64(x6_1.AuxInt) != 56 || w != x6_1.Args[0] || !(!config.BigEndian && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && clobber(x0, x1, x2, x3, x4, x5, x6)) {
+ break
+ }
+ v.reset(OpPPC64MOVDBRstore)
+ v0 := b.NewValue0(x6.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg(p)
+ v.AddArg3(v0, w, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVBstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is16Bit(c)
+ // result: (MOVBstore [int32(c)] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstoreidx (MOVDconst [c]) ptr val mem)
+ // cond: is16Bit(c)
+ // result: (MOVBstore [int32(c)] ptr val mem)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVBreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVBZreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVHreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVHZreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVWreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (MOVWZreg x) mem)
+ // result: (MOVBstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (SRWconst (MOVHreg x) [c]) mem)
+ // cond: c <= 8
+ // result: (MOVBstoreidx ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_2_0.Args[0]
+ mem := v_3
+ if !(c <= 8) {
+ break
+ }
+ v.reset(OpPPC64MOVBstoreidx)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg4(ptr, idx, v0, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (SRWconst (MOVHZreg x) [c]) mem)
+ // cond: c <= 8
+ // result: (MOVBstoreidx ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_2_0.Args[0]
+ mem := v_3
+ if !(c <= 8) {
+ break
+ }
+ v.reset(OpPPC64MOVBstoreidx)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg4(ptr, idx, v0, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (SRWconst (MOVWreg x) [c]) mem)
+ // cond: c <= 24
+ // result: (MOVBstoreidx ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_2_0.Args[0]
+ mem := v_3
+ if !(c <= 24) {
+ break
+ }
+ v.reset(OpPPC64MOVBstoreidx)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg4(ptr, idx, v0, mem)
+ return true
+ }
+ // match: (MOVBstoreidx ptr idx (SRWconst (MOVWZreg x) [c]) mem)
+ // cond: c <= 24
+ // result: (MOVBstoreidx ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_2.AuxInt)
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_2_0.Args[0]
+ mem := v_3
+ if !(c <= 24) {
+ break
+ }
+ v.reset(OpPPC64MOVBstoreidx)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ v.AddArg4(ptr, idx, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstorezero [off1] {sym} (ADDconst [off2] x) mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (MOVBstorezero [off1+int32(off2)] {sym} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, mem)
+ return true
+ }
+ // match: (MOVBstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem)
+ // cond: canMergeSym(sym1,sym2) && (x.Op != OpSB || p.Uses == 1)
+ // result: (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ x := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && (x.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDload [off] {sym} ptr (FMOVDstore [off] {sym} ptr x _))
+ // result: (MFVSRD x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64FMOVDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ v.reset(OpPPC64MFVSRD)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVDload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0
+ // result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDload [off1] {sym} (ADDconst [off2] x) mem)
+ // cond: is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0
+ // result: (MOVDload [off1+int32(off2)] {sym} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, mem)
+ return true
+ }
+ // match: (MOVDload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVDloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ idx := p.Args[1]
+ ptr := p.Args[0]
+ mem := v_1
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVDloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVDloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c) && c%4 == 0
+ // result: (MOVDload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is16Bit(c) && c%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c) && c%4 == 0
+ // result: (MOVDload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is16Bit(c) && c%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstore [off] {sym} ptr (MFVSRD x) mem)
+ // result: (FMOVDstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MFVSRD {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64FMOVDstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVDstore [off1] {sym} (ADDconst [off2] x) val mem)
+ // cond: is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0
+ // result: (MOVDstore [off1+int32(off2)] {sym} x val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0
+ // result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // result: (MOVDstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpPPC64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDstore [0] {sym} p:(ADD ptr idx) val mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVDstoreidx ptr idx val mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ idx := p.Args[1]
+ ptr := p.Args[0]
+ val := v_1
+ mem := v_2
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVDstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVDstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is16Bit(c) && c%4 == 0
+ // result: (MOVDstore [int32(c)] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is16Bit(c) && c%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstoreidx (MOVDconst [c]) ptr val mem)
+ // cond: is16Bit(c) && c%4 == 0
+ // result: (MOVDstore [int32(c)] ptr val mem)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ if !(is16Bit(c) && c%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVDstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstorezero [off1] {sym} (ADDconst [off2] x) mem)
+ // cond: is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0
+ // result: (MOVDstorezero [off1+int32(off2)] {sym} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, mem)
+ return true
+ }
+ // match: (MOVDstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem)
+ // cond: canMergeSym(sym1,sym2) && (x.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0
+ // result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ x := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && (x.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHBRstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHBRstore {sym} ptr (MOVHreg x) mem)
+ // result: (MOVHBRstore {sym} ptr x mem)
+ for {
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVHBRstore)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHBRstore {sym} ptr (MOVHZreg x) mem)
+ // result: (MOVHBRstore {sym} ptr x mem)
+ for {
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVHBRstore)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHBRstore {sym} ptr (MOVWreg x) mem)
+ // result: (MOVHBRstore {sym} ptr x mem)
+ for {
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVHBRstore)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHBRstore {sym} ptr (MOVWZreg x) mem)
+ // result: (MOVHBRstore {sym} ptr x mem)
+ for {
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVHBRstore)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHZload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHZload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (MOVHZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64MOVHZload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHZload [off1] {sym} (ADDconst [off2] x) mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (MOVHZload [off1+int32(off2)] {sym} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64MOVHZload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, mem)
+ return true
+ }
+ // match: (MOVHZload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVHZloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ idx := p.Args[1]
+ ptr := p.Args[0]
+ mem := v_1
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVHZloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHZloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHZloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c)
+ // result: (MOVHZload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHZload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHZloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c)
+ // result: (MOVHZload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHZload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHZreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVHZreg y:(ANDconst [c] _))
+ // cond: uint64(c) <= 0xFFFF
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(y.AuxInt)
+ if !(uint64(c) <= 0xFFFF) {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVHZreg (SRWconst [c] (MOVBZreg x)))
+ // result: (SRWconst [c] (MOVBZreg x))
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVHZreg (SRWconst [c] (MOVHZreg x)))
+ // result: (SRWconst [c] (MOVHZreg x))
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVHZreg (SRWconst [c] x))
+ // cond: sizeof(x.Type) <= 16
+ // result: (SRWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) <= 16) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg (SRDconst [c] x))
+ // cond: c>=48
+ // result: (SRDconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c >= 48) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg (SRWconst [c] x))
+ // cond: c>=16
+ // result: (SRWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c >= 16) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg y:(MOVHZreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVHZreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVHZreg y:(MOVBZreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVBZreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVHZreg y:(MOVHBRload _ _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVHBRload {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVHZreg y:(MOVHreg x))
+ // result: (MOVHZreg x)
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := y.Args[0]
+ v.reset(OpPPC64MOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg (OR <t> x (MOVWZreg y)))
+ // result: (MOVHZreg (OR <t> x y))
+ for {
+ if v_0.Op != OpPPC64OR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVWZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVHZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64OR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVHZreg (XOR <t> x (MOVWZreg y)))
+ // result: (MOVHZreg (XOR <t> x y))
+ for {
+ if v_0.Op != OpPPC64XOR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVWZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVHZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64XOR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVHZreg (AND <t> x (MOVWZreg y)))
+ // result: (MOVHZreg (AND <t> x y))
+ for {
+ if v_0.Op != OpPPC64AND {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVWZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVHZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64AND, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVHZreg (OR <t> x (MOVHZreg y)))
+ // result: (MOVHZreg (OR <t> x y))
+ for {
+ if v_0.Op != OpPPC64OR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVHZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVHZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64OR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVHZreg (XOR <t> x (MOVHZreg y)))
+ // result: (MOVHZreg (XOR <t> x y))
+ for {
+ if v_0.Op != OpPPC64XOR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVHZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVHZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64XOR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVHZreg (AND <t> x (MOVHZreg y)))
+ // result: (MOVHZreg (AND <t> x y))
+ for {
+ if v_0.Op != OpPPC64AND {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVHZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVHZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64AND, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVHZreg z:(ANDconst [c] (MOVBZload ptr x)))
+ // result: z
+ for {
+ z := v_0
+ if z.Op != OpPPC64ANDconst {
+ break
+ }
+ z_0 := z.Args[0]
+ if z_0.Op != OpPPC64MOVBZload {
+ break
+ }
+ v.copyOf(z)
+ return true
+ }
+ // match: (MOVHZreg z:(ANDconst [c] (MOVHZload ptr x)))
+ // result: z
+ for {
+ z := v_0
+ if z.Op != OpPPC64ANDconst {
+ break
+ }
+ z_0 := z.Args[0]
+ if z_0.Op != OpPPC64MOVHZload {
+ break
+ }
+ v.copyOf(z)
+ return true
+ }
+ // match: (MOVHZreg z:(AND y (MOVHZload ptr x)))
+ // result: z
+ for {
+ z := v_0
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ if z_1.Op != OpPPC64MOVHZload {
+ continue
+ }
+ v.copyOf(z)
+ return true
+ }
+ break
+ }
+ // match: (MOVHZreg x:(MOVBZload _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVBZload {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHZreg x:(MOVBZloadidx _ _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVBZloadidx {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHZreg x:(MOVHZload _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVHZload {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHZreg x:(MOVHZloadidx _ _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVHZloadidx {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHZreg x:(Arg <t>))
+ // cond: (is8BitInt(t) || is16BitInt(t)) && !isSigned(t)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !((is8BitInt(t) || is16BitInt(t)) && !isSigned(t)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHZreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(uint16(c))])
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64MOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHload [off1] {sym} (ADDconst [off2] x) mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (MOVHload [off1+int32(off2)] {sym} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64MOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, mem)
+ return true
+ }
+ // match: (MOVHload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVHloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ idx := p.Args[1]
+ ptr := p.Args[0]
+ mem := v_1
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVHloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c)
+ // result: (MOVHload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c)
+ // result: (MOVHload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVHreg y:(ANDconst [c] _))
+ // cond: uint64(c) <= 0x7FFF
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(y.AuxInt)
+ if !(uint64(c) <= 0x7FFF) {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVHreg (SRAWconst [c] (MOVBreg x)))
+ // result: (SRAWconst [c] (MOVBreg x))
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVHreg (SRAWconst [c] (MOVHreg x)))
+ // result: (SRAWconst [c] (MOVHreg x))
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVHreg (SRAWconst [c] x))
+ // cond: sizeof(x.Type) <= 16
+ // result: (SRAWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) <= 16) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (SRDconst [c] x))
+ // cond: c>48
+ // result: (SRDconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c > 48) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (SRDconst [c] x))
+ // cond: c==48
+ // result: (SRADconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c == 48) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (SRADconst [c] x))
+ // cond: c>=48
+ // result: (SRADconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRADconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c >= 48) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (SRWconst [c] x))
+ // cond: c>16
+ // result: (SRWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c > 16) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (SRAWconst [c] x))
+ // cond: c>=16
+ // result: (SRAWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c >= 16) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (SRWconst [c] x))
+ // cond: c==16
+ // result: (SRAWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c == 16) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg y:(MOVHreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVHreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVHreg y:(MOVBreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVBreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVHreg y:(MOVHZreg x))
+ // result: (MOVHreg x)
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := y.Args[0]
+ v.reset(OpPPC64MOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHload _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVHload {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHloadidx _ _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVHloadidx {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHreg x:(Arg <t>))
+ // cond: (is8BitInt(t) || is16BitInt(t)) && isSigned(t)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !((is8BitInt(t) || is16BitInt(t)) && isSigned(t)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(int16(c))])
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int16(c)))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (MOVHstore [off1] {sym} (ADDconst [off2] x) val mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (MOVHstore [off1+int32(off2)] {sym} x val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // result: (MOVHstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpPPC64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstore [0] {sym} p:(ADD ptr idx) val mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVHstoreidx ptr idx val mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ idx := p.Args[1]
+ ptr := p.Args[0]
+ val := v_1
+ mem := v_2
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVHstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHZreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVWZreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [i1] {s} p (SRWconst w [16]) x0:(MOVHstore [i0] {s} p w mem))
+ // cond: !config.BigEndian && x0.Uses == 1 && i1 == i0+2 && clobber(x0)
+ // result: (MOVWstore [i0] {s} p w mem)
+ for {
+ i1 := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpPPC64SRWconst || auxIntToInt64(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x0 := v_2
+ if x0.Op != OpPPC64MOVHstore {
+ break
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ if p != x0.Args[0] || w != x0.Args[1] || !(!config.BigEndian && x0.Uses == 1 && i1 == i0+2 && clobber(x0)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i0)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVHstore [i1] {s} p (SRDconst w [16]) x0:(MOVHstore [i0] {s} p w mem))
+ // cond: !config.BigEndian && x0.Uses == 1 && i1 == i0+2 && clobber(x0)
+ // result: (MOVWstore [i0] {s} p w mem)
+ for {
+ i1 := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpPPC64SRDconst || auxIntToInt64(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x0 := v_2
+ if x0.Op != OpPPC64MOVHstore {
+ break
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ break
+ }
+ mem := x0.Args[2]
+ if p != x0.Args[0] || w != x0.Args[1] || !(!config.BigEndian && x0.Uses == 1 && i1 == i0+2 && clobber(x0)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = int32ToAuxInt(i0)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is16Bit(c)
+ // result: (MOVHstore [int32(c)] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstoreidx (MOVDconst [c]) ptr val mem)
+ // cond: is16Bit(c)
+ // result: (MOVHstore [int32(c)] ptr val mem)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr idx (MOVHreg x) mem)
+ // result: (MOVHstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVHstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr idx (MOVHZreg x) mem)
+ // result: (MOVHstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVHstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr idx (MOVWreg x) mem)
+ // result: (MOVHstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVHstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVHstoreidx ptr idx (MOVWZreg x) mem)
+ // result: (MOVHstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVHstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstorezero [off1] {sym} (ADDconst [off2] x) mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (MOVHstorezero [off1+int32(off2)] {sym} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, mem)
+ return true
+ }
+ // match: (MOVHstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem)
+ // cond: canMergeSym(sym1,sym2) && (x.Op != OpSB || p.Uses == 1)
+ // result: (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ x := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && (x.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWBRstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWBRstore {sym} ptr (MOVWreg x) mem)
+ // result: (MOVWBRstore {sym} ptr x mem)
+ for {
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVWBRstore)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWBRstore {sym} ptr (MOVWZreg x) mem)
+ // result: (MOVWBRstore {sym} ptr x mem)
+ for {
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVWBRstore)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWZload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWZload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (MOVWZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64MOVWZload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWZload [off1] {sym} (ADDconst [off2] x) mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (MOVWZload [off1+int32(off2)] {sym} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64MOVWZload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, mem)
+ return true
+ }
+ // match: (MOVWZload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVWZloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ idx := p.Args[1]
+ ptr := p.Args[0]
+ mem := v_1
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVWZloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWZloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWZloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c)
+ // result: (MOVWZload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVWZload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWZloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c)
+ // result: (MOVWZload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVWZload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWZreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVWZreg y:(ANDconst [c] _))
+ // cond: uint64(c) <= 0xFFFFFFFF
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(y.AuxInt)
+ if !(uint64(c) <= 0xFFFFFFFF) {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVWZreg y:(AND (MOVDconst [c]) _))
+ // cond: uint64(c) <= 0xFFFFFFFF
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64AND {
+ break
+ }
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ if y_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(y_0.AuxInt)
+ if !(uint64(c) <= 0xFFFFFFFF) {
+ continue
+ }
+ v.copyOf(y)
+ return true
+ }
+ break
+ }
+ // match: (MOVWZreg (SRWconst [c] (MOVBZreg x)))
+ // result: (SRWconst [c] (MOVBZreg x))
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWZreg (SRWconst [c] (MOVHZreg x)))
+ // result: (SRWconst [c] (MOVHZreg x))
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWZreg (SRWconst [c] (MOVWZreg x)))
+ // result: (SRWconst [c] (MOVWZreg x))
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWZreg (SRWconst [c] x))
+ // cond: sizeof(x.Type) <= 32
+ // result: (SRWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) <= 32) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg (SRDconst [c] x))
+ // cond: c>=32
+ // result: (SRDconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c >= 32) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg y:(MOVWZreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVWZreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVWZreg y:(MOVHZreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVHZreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVWZreg y:(MOVBZreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVBZreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVWZreg y:(MOVHBRload _ _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVHBRload {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVWZreg y:(MOVWBRload _ _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVWBRload {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVWZreg y:(MOVWreg x))
+ // result: (MOVWZreg x)
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := y.Args[0]
+ v.reset(OpPPC64MOVWZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg (OR <t> x (MOVWZreg y)))
+ // result: (MOVWZreg (OR <t> x y))
+ for {
+ if v_0.Op != OpPPC64OR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVWZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVWZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64OR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVWZreg (XOR <t> x (MOVWZreg y)))
+ // result: (MOVWZreg (XOR <t> x y))
+ for {
+ if v_0.Op != OpPPC64XOR {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVWZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVWZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64XOR, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVWZreg (AND <t> x (MOVWZreg y)))
+ // result: (MOVWZreg (AND <t> x y))
+ for {
+ if v_0.Op != OpPPC64AND {
+ break
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpPPC64MOVWZreg {
+ continue
+ }
+ y := v_0_1.Args[0]
+ v.reset(OpPPC64MOVWZreg)
+ v0 := b.NewValue0(v.Pos, OpPPC64AND, t)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (MOVWZreg z:(ANDconst [c] (MOVBZload ptr x)))
+ // result: z
+ for {
+ z := v_0
+ if z.Op != OpPPC64ANDconst {
+ break
+ }
+ z_0 := z.Args[0]
+ if z_0.Op != OpPPC64MOVBZload {
+ break
+ }
+ v.copyOf(z)
+ return true
+ }
+ // match: (MOVWZreg z:(ANDconst [c] (MOVHZload ptr x)))
+ // result: z
+ for {
+ z := v_0
+ if z.Op != OpPPC64ANDconst {
+ break
+ }
+ z_0 := z.Args[0]
+ if z_0.Op != OpPPC64MOVHZload {
+ break
+ }
+ v.copyOf(z)
+ return true
+ }
+ // match: (MOVWZreg z:(ANDconst [c] (MOVWZload ptr x)))
+ // result: z
+ for {
+ z := v_0
+ if z.Op != OpPPC64ANDconst {
+ break
+ }
+ z_0 := z.Args[0]
+ if z_0.Op != OpPPC64MOVWZload {
+ break
+ }
+ v.copyOf(z)
+ return true
+ }
+ // match: (MOVWZreg z:(AND y (MOVWZload ptr x)))
+ // result: z
+ for {
+ z := v_0
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ if z_1.Op != OpPPC64MOVWZload {
+ continue
+ }
+ v.copyOf(z)
+ return true
+ }
+ break
+ }
+ // match: (MOVWZreg x:(MOVBZload _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVBZload {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVBZloadidx _ _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVBZloadidx {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVHZload _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVHZload {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVHZloadidx _ _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVHZloadidx {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVWZload _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVWZload {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVWZloadidx _ _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVWZloadidx {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg x:(Arg <t>))
+ // cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !((is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(uint32(c))])
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0
+ // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym} (ADDconst [off2] x) mem)
+ // cond: is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0
+ // result: (MOVWload [off1+int32(off2)] {sym} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1)+off2) && (int64(off1)+off2)%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, mem)
+ return true
+ }
+ // match: (MOVWload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVWloadidx ptr idx mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ idx := p.Args[1]
+ ptr := p.Args[0]
+ mem := v_1
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVWloadidx)
+ v.AddArg3(ptr, idx, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWloadidx(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c) && c%4 == 0
+ // result: (MOVWload [int32(c)] ptr mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is16Bit(c) && c%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVWload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c) && c%4 == 0
+ // result: (MOVWload [int32(c)] ptr mem)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ mem := v_2
+ if !(is16Bit(c) && c%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVWload)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVWreg y:(ANDconst [c] _))
+ // cond: uint64(c) <= 0xFFFF
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(y.AuxInt)
+ if !(uint64(c) <= 0xFFFF) {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVWreg y:(AND (MOVDconst [c]) _))
+ // cond: uint64(c) <= 0x7FFFFFFF
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64AND {
+ break
+ }
+ y_0 := y.Args[0]
+ y_1 := y.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 {
+ if y_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(y_0.AuxInt)
+ if !(uint64(c) <= 0x7FFFFFFF) {
+ continue
+ }
+ v.copyOf(y)
+ return true
+ }
+ break
+ }
+ // match: (MOVWreg (SRAWconst [c] (MOVBreg x)))
+ // result: (SRAWconst [c] (MOVBreg x))
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWreg (SRAWconst [c] (MOVHreg x)))
+ // result: (SRAWconst [c] (MOVHreg x))
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWreg (SRAWconst [c] (MOVWreg x)))
+ // result: (SRAWconst [c] (MOVWreg x))
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWreg (SRAWconst [c] x))
+ // cond: sizeof(x.Type) <= 32
+ // result: (SRAWconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) <= 32) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg (SRDconst [c] x))
+ // cond: c>32
+ // result: (SRDconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c > 32) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg (SRADconst [c] x))
+ // cond: c>=32
+ // result: (SRADconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRADconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c >= 32) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg (SRDconst [c] x))
+ // cond: c==32
+ // result: (SRADconst [c] x)
+ for {
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(c == 32) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg y:(MOVWreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVWreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVWreg y:(MOVHreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVHreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVWreg y:(MOVBreg _))
+ // result: y
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVBreg {
+ break
+ }
+ v.copyOf(y)
+ return true
+ }
+ // match: (MOVWreg y:(MOVWZreg x))
+ // result: (MOVWreg x)
+ for {
+ y := v_0
+ if y.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := y.Args[0]
+ v.reset(OpPPC64MOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHload _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVHload {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHloadidx _ _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVHloadidx {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWload _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVWload {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWloadidx _ _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVWloadidx {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg x:(Arg <t>))
+ // cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !((is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(int32(c))])
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstore [off1] {sym} (ADDconst [off2] x) val mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (MOVWstore [off1+int32(off2)] {sym} x val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem)
+ // cond: canMergeSym(sym1,sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)
+ // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ ptr := p.Args[0]
+ val := v_1
+ mem := v_2
+ if !(canMergeSym(sym1, sym2) && is16Bit(int64(off1+off2)) && (ptr.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // result: (MOVWstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpPPC64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstore [0] {sym} p:(ADD ptr idx) val mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVWstoreidx ptr idx val mem)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ sym := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ idx := p.Args[1]
+ ptr := p.Args[0]
+ val := v_1
+ mem := v_2
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVWstoreidx)
+ v.AddArg4(ptr, idx, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWZreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWstoreidx(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is16Bit(c)
+ // result: (MOVWstore [int32(c)] ptr val mem)
+ for {
+ ptr := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ val := v_2
+ mem := v_3
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx (MOVDconst [c]) ptr val mem)
+ // cond: is16Bit(c)
+ // result: (MOVWstore [int32(c)] ptr val mem)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ ptr := v_1
+ val := v_2
+ mem := v_3
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstoreidx ptr idx (MOVWreg x) mem)
+ // result: (MOVWstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVWstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ // match: (MOVWstoreidx ptr idx (MOVWZreg x) mem)
+ // result: (MOVWstoreidx ptr idx x mem)
+ for {
+ ptr := v_0
+ idx := v_1
+ if v_2.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v_3
+ v.reset(OpPPC64MOVWstoreidx)
+ v.AddArg4(ptr, idx, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstorezero [off1] {sym} (ADDconst [off2] x) mem)
+ // cond: is16Bit(int64(off1)+off2)
+ // result: (MOVWstorezero [off1+int32(off2)] {sym} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ mem := v_1
+ if !(is16Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(x, mem)
+ return true
+ }
+ // match: (MOVWstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem)
+ // cond: canMergeSym(sym1,sym2) && (x.Op != OpSB || p.Uses == 1)
+ // result: (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ p := v_0
+ if p.Op != OpPPC64MOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(p.AuxInt)
+ sym2 := auxToSym(p.Aux)
+ x := p.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && (x.Op != OpSB || p.Uses == 1)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MTVSRD(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MTVSRD (MOVDconst [c]))
+ // cond: !math.IsNaN(math.Float64frombits(uint64(c)))
+ // result: (FMOVDconst [math.Float64frombits(uint64(c))])
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(!math.IsNaN(math.Float64frombits(uint64(c)))) {
+ break
+ }
+ v.reset(OpPPC64FMOVDconst)
+ v.AuxInt = float64ToAuxInt(math.Float64frombits(uint64(c)))
+ return true
+ }
+ // match: (MTVSRD x:(MOVDload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (FMOVDload [off] {sym} ptr mem)
+ for {
+ x := v_0
+ if x.Op != OpPPC64MOVDload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpPPC64FMOVDload, typ.Float64)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MULLD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULLD x (MOVDconst [c]))
+ // cond: is16Bit(c)
+ // result: (MULLDconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is16Bit(c)) {
+ continue
+ }
+ v.reset(OpPPC64MULLDconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MULLW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULLW x (MOVDconst [c]))
+ // cond: is16Bit(c)
+ // result: (MULLWconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is16Bit(c)) {
+ continue
+ }
+ v.reset(OpPPC64MULLWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64NEG(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEG (ADDconst [c] x))
+ // cond: is32Bit(-c)
+ // result: (SUBFCconst [-c] x)
+ for {
+ if v_0.Op != OpPPC64ADDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(-c)) {
+ break
+ }
+ v.reset(OpPPC64SUBFCconst)
+ v.AuxInt = int64ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (NEG (SUBFCconst [c] x))
+ // cond: is32Bit(-c)
+ // result: (ADDconst [-c] x)
+ for {
+ if v_0.Op != OpPPC64SUBFCconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(-c)) {
+ break
+ }
+ v.reset(OpPPC64ADDconst)
+ v.AuxInt = int64ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64NOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (NOR (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [^(c|d)])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpPPC64MOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(^(c | d))
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64NotEqual(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (NotEqual (FlagEQ))
+ // result: (MOVDconst [0])
+ for {
+ if v_0.Op != OpPPC64FlagEQ {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (NotEqual (FlagLT))
+ // result: (MOVDconst [1])
+ for {
+ if v_0.Op != OpPPC64FlagLT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (NotEqual (FlagGT))
+ // result: (MOVDconst [1])
+ for {
+ if v_0.Op != OpPPC64FlagGT {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (NotEqual (InvertFlags x))
+ // result: (NotEqual x)
+ for {
+ if v_0.Op != OpPPC64InvertFlags {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64NotEqual)
+ v.AddArg(x)
+ return true
+ }
+ // match: (NotEqual cmp)
+ // result: (ISELB [6] (MOVDconst [1]) cmp)
+ for {
+ cmp := v_0
+ v.reset(OpPPC64ISELB)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, cmp)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPPC64OR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: ( OR (SLDconst x [c]) (SRDconst x [d]))
+ // cond: d == 64-c
+ // result: (ROTLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpPPC64SRDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 64-c) {
+ continue
+ }
+ v.reset(OpPPC64ROTLconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: ( OR (SLWconst x [c]) (SRWconst x [d]))
+ // cond: d == 32-c
+ // result: (ROTLWconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLWconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpPPC64SRWconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 32-c) {
+ continue
+ }
+ v.reset(OpPPC64ROTLWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: ( OR (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y))))
+ // result: (ROTL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLD {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int64 || auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRD {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUB || v_1_1.Type != typ.UInt {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpPPC64ANDconst || v_1_1_1.Type != typ.UInt || auxIntToInt64(v_1_1_1.AuxInt) != 63 || y != v_1_1_1.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: ( OR (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y))))
+ // result: (ROTL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLD {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int64 || auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRD {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUBFCconst || v_1_1.Type != typ.UInt || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64ANDconst || v_1_1_0.Type != typ.UInt || auxIntToInt64(v_1_1_0.AuxInt) != 63 || y != v_1_1_0.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: ( OR (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y))))
+ // result: (ROTLW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLW {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int32 || auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRW {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUBFCconst || v_1_1.Type != typ.UInt || auxIntToInt64(v_1_1.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64ANDconst || v_1_1_0.Type != typ.UInt || auxIntToInt64(v_1_1_0.AuxInt) != 31 || y != v_1_1_0.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: ( OR (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y))))
+ // result: (ROTLW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLW {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int32 || auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRW {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUB || v_1_1.Type != typ.UInt {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpPPC64ANDconst || v_1_1_1.Type != typ.UInt || auxIntToInt64(v_1_1_1.AuxInt) != 31 || y != v_1_1_1.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (OR (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [c|d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpPPC64MOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c | d)
+ return true
+ }
+ break
+ }
+ // match: (OR x (MOVDconst [c]))
+ // cond: isU32Bit(c)
+ // result: (ORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isU32Bit(c)) {
+ continue
+ }
+ v.reset(OpPPC64ORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> x0:(MOVBZload [i0] {s} p mem) o1:(SLWconst x1:(MOVBZload [i1] {s} p mem) [8]))
+ // cond: !config.BigEndian && i1 == i0+1 && x0.Uses ==1 && x1.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, o1)
+ // result: @mergePoint(b,x0,x1) (MOVHZload <t> {s} [i0] p mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ o1 := v_1
+ if o1.Op != OpPPC64SLWconst || auxIntToInt64(o1.AuxInt) != 8 {
+ continue
+ }
+ x1 := o1.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(!config.BigEndian && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, o1)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpPPC64MOVHZload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> x0:(MOVBZload [i0] {s} p mem) o1:(SLDconst x1:(MOVBZload [i1] {s} p mem) [8]))
+ // cond: !config.BigEndian && i1 == i0+1 && x0.Uses ==1 && x1.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, o1)
+ // result: @mergePoint(b,x0,x1) (MOVHZload <t> {s} [i0] p mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ o1 := v_1
+ if o1.Op != OpPPC64SLDconst || auxIntToInt64(o1.AuxInt) != 8 {
+ continue
+ }
+ x1 := o1.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(!config.BigEndian && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, o1)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpPPC64MOVHZload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> x0:(MOVBZload [i1] {s} p mem) o1:(SLWconst x1:(MOVBZload [i0] {s} p mem) [8]))
+ // cond: !config.BigEndian && i1 == i0+1 && x0.Uses ==1 && x1.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, o1)
+ // result: @mergePoint(b,x0,x1) (MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ o1 := v_1
+ if o1.Op != OpPPC64SLWconst || auxIntToInt64(o1.AuxInt) != 8 {
+ continue
+ }
+ x1 := o1.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(!config.BigEndian && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, o1)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpPPC64MOVHBRload, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> x0:(MOVBZload [i1] {s} p mem) o1:(SLDconst x1:(MOVBZload [i0] {s} p mem) [8]))
+ // cond: !config.BigEndian && i1 == i0+1 && x0.Uses ==1 && x1.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, o1)
+ // result: @mergePoint(b,x0,x1) (MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ o1 := v_1
+ if o1.Op != OpPPC64SLDconst || auxIntToInt64(o1.AuxInt) != 8 {
+ continue
+ }
+ x1 := o1.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(!config.BigEndian && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, o1)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpPPC64MOVHBRload, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> s0:(SLWconst x0:(MOVBZload [i1] {s} p mem) [n1]) s1:(SLWconst x1:(MOVBZload [i0] {s} p mem) [n2]))
+ // cond: !config.BigEndian && i1 == i0+1 && n1%8 == 0 && n2 == n1+8 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, s0, s1)
+ // result: @mergePoint(b,x0,x1) (SLDconst <t> (MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [n1])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpPPC64SLWconst {
+ continue
+ }
+ n1 := auxIntToInt64(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ s1 := v_1
+ if s1.Op != OpPPC64SLWconst {
+ continue
+ }
+ n2 := auxIntToInt64(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(!config.BigEndian && i1 == i0+1 && n1%8 == 0 && n2 == n1+8 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, s0, s1)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpPPC64SLDconst, t)
+ v.copyOf(v0)
+ v0.AuxInt = int64ToAuxInt(n1)
+ v1 := b.NewValue0(x1.Pos, OpPPC64MOVHBRload, t)
+ v2 := b.NewValue0(x1.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v2.AuxInt = int32ToAuxInt(i0)
+ v2.Aux = symToAux(s)
+ v2.AddArg(p)
+ v1.AddArg2(v2, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> s0:(SLDconst x0:(MOVBZload [i1] {s} p mem) [n1]) s1:(SLDconst x1:(MOVBZload [i0] {s} p mem) [n2]))
+ // cond: !config.BigEndian && i1 == i0+1 && n1%8 == 0 && n2 == n1+8 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, s0, s1)
+ // result: @mergePoint(b,x0,x1) (SLDconst <t> (MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [n1])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpPPC64SLDconst {
+ continue
+ }
+ n1 := auxIntToInt64(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ s1 := v_1
+ if s1.Op != OpPPC64SLDconst {
+ continue
+ }
+ n2 := auxIntToInt64(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(!config.BigEndian && i1 == i0+1 && n1%8 == 0 && n2 == n1+8 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, s0, s1)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpPPC64SLDconst, t)
+ v.copyOf(v0)
+ v0.AuxInt = int64ToAuxInt(n1)
+ v1 := b.NewValue0(x1.Pos, OpPPC64MOVHBRload, t)
+ v2 := b.NewValue0(x1.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v2.AuxInt = int32ToAuxInt(i0)
+ v2.Aux = symToAux(s)
+ v2.AddArg(p)
+ v1.AddArg2(v2, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (OR <t> s1:(SLWconst x2:(MOVBZload [i3] {s} p mem) [24]) o0:(OR <t> s0:(SLWconst x1:(MOVBZload [i2] {s} p mem) [16]) x0:(MOVHZload [i0] {s} p mem)))
+ // cond: !config.BigEndian && i2 == i0+2 && i3 == i0+3 && x0.Uses ==1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVWZload <t> {s} [i0] p mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpPPC64SLWconst || auxIntToInt64(s1.AuxInt) != 24 {
+ continue
+ }
+ x2 := s1.Args[0]
+ if x2.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i3 := auxIntToInt32(x2.AuxInt)
+ s := auxToSym(x2.Aux)
+ mem := x2.Args[1]
+ p := x2.Args[0]
+ o0 := v_1
+ if o0.Op != OpPPC64OR || o0.Type != t {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ s0 := o0_0
+ if s0.Op != OpPPC64SLWconst || auxIntToInt64(s0.AuxInt) != 16 {
+ continue
+ }
+ x1 := s0.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i2 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ x0 := o0_1
+ if x0.Op != OpPPC64MOVHZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(!config.BigEndian && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x0.Pos, OpPPC64MOVWZload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> s1:(SLDconst x2:(MOVBZload [i3] {s} p mem) [24]) o0:(OR <t> s0:(SLDconst x1:(MOVBZload [i2] {s} p mem) [16]) x0:(MOVHZload [i0] {s} p mem)))
+ // cond: !config.BigEndian && i2 == i0+2 && i3 == i0+3 && x0.Uses ==1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVWZload <t> {s} [i0] p mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpPPC64SLDconst || auxIntToInt64(s1.AuxInt) != 24 {
+ continue
+ }
+ x2 := s1.Args[0]
+ if x2.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i3 := auxIntToInt32(x2.AuxInt)
+ s := auxToSym(x2.Aux)
+ mem := x2.Args[1]
+ p := x2.Args[0]
+ o0 := v_1
+ if o0.Op != OpPPC64OR || o0.Type != t {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ s0 := o0_0
+ if s0.Op != OpPPC64SLDconst || auxIntToInt64(s0.AuxInt) != 16 {
+ continue
+ }
+ x1 := s0.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i2 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ x0 := o0_1
+ if x0.Op != OpPPC64MOVHZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(!config.BigEndian && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x0.Pos, OpPPC64MOVWZload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> s1:(SLWconst x2:(MOVBZload [i0] {s} p mem) [24]) o0:(OR <t> s0:(SLWconst x1:(MOVBZload [i1] {s} p mem) [16]) x0:(MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i2] {s} p) mem)))
+ // cond: !config.BigEndian && i1 == i0+1 && i2 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpPPC64SLWconst || auxIntToInt64(s1.AuxInt) != 24 {
+ continue
+ }
+ x2 := s1.Args[0]
+ if x2.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x2.AuxInt)
+ s := auxToSym(x2.Aux)
+ mem := x2.Args[1]
+ p := x2.Args[0]
+ o0 := v_1
+ if o0.Op != OpPPC64OR || o0.Type != t {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ s0 := o0_0
+ if s0.Op != OpPPC64SLWconst || auxIntToInt64(s0.AuxInt) != 16 {
+ continue
+ }
+ x1 := s0.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ x0 := o0_1
+ if x0.Op != OpPPC64MOVHBRload || x0.Type != t {
+ continue
+ }
+ _ = x0.Args[1]
+ x0_0 := x0.Args[0]
+ if x0_0.Op != OpPPC64MOVDaddr || x0_0.Type != typ.Uintptr {
+ continue
+ }
+ i2 := auxIntToInt32(x0_0.AuxInt)
+ if auxToSym(x0_0.Aux) != s || p != x0_0.Args[0] || mem != x0.Args[1] || !(!config.BigEndian && i1 == i0+1 && i2 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x0.Pos, OpPPC64MOVWBRload, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> s1:(SLDconst x2:(MOVBZload [i0] {s} p mem) [24]) o0:(OR <t> s0:(SLDconst x1:(MOVBZload [i1] {s} p mem) [16]) x0:(MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i2] {s} p) mem)))
+ // cond: !config.BigEndian && i1 == i0+1 && i2 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpPPC64SLDconst || auxIntToInt64(s1.AuxInt) != 24 {
+ continue
+ }
+ x2 := s1.Args[0]
+ if x2.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x2.AuxInt)
+ s := auxToSym(x2.Aux)
+ mem := x2.Args[1]
+ p := x2.Args[0]
+ o0 := v_1
+ if o0.Op != OpPPC64OR || o0.Type != t {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ s0 := o0_0
+ if s0.Op != OpPPC64SLDconst || auxIntToInt64(s0.AuxInt) != 16 {
+ continue
+ }
+ x1 := s0.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ x0 := o0_1
+ if x0.Op != OpPPC64MOVHBRload || x0.Type != t {
+ continue
+ }
+ _ = x0.Args[1]
+ x0_0 := x0.Args[0]
+ if x0_0.Op != OpPPC64MOVDaddr || x0_0.Type != typ.Uintptr {
+ continue
+ }
+ i2 := auxIntToInt32(x0_0.AuxInt)
+ if auxToSym(x0_0.Aux) != s || p != x0_0.Args[0] || mem != x0.Args[1] || !(!config.BigEndian && i1 == i0+1 && i2 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x0.Pos, OpPPC64MOVWBRload, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> x0:(MOVBZload [i3] {s} p mem) o0:(OR <t> s0:(SLWconst x1:(MOVBZload [i2] {s} p mem) [8]) s1:(SLWconst x2:(MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [16])))
+ // cond: !config.BigEndian && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i3 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ o0 := v_1
+ if o0.Op != OpPPC64OR || o0.Type != t {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ s0 := o0_0
+ if s0.Op != OpPPC64SLWconst || auxIntToInt64(s0.AuxInt) != 8 {
+ continue
+ }
+ x1 := s0.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i2 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ s1 := o0_1
+ if s1.Op != OpPPC64SLWconst || auxIntToInt64(s1.AuxInt) != 16 {
+ continue
+ }
+ x2 := s1.Args[0]
+ if x2.Op != OpPPC64MOVHBRload || x2.Type != t {
+ continue
+ }
+ _ = x2.Args[1]
+ x2_0 := x2.Args[0]
+ if x2_0.Op != OpPPC64MOVDaddr || x2_0.Type != typ.Uintptr {
+ continue
+ }
+ i0 := auxIntToInt32(x2_0.AuxInt)
+ if auxToSym(x2_0.Aux) != s || p != x2_0.Args[0] || mem != x2.Args[1] || !(!config.BigEndian && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x2.Pos, OpPPC64MOVWBRload, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x2.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> x0:(MOVBZload [i3] {s} p mem) o0:(OR <t> s0:(SLDconst x1:(MOVBZload [i2] {s} p mem) [8]) s1:(SLDconst x2:(MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [16])))
+ // cond: !config.BigEndian && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)
+ // result: @mergePoint(b,x0,x1,x2) (MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i3 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ o0 := v_1
+ if o0.Op != OpPPC64OR || o0.Type != t {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ s0 := o0_0
+ if s0.Op != OpPPC64SLDconst || auxIntToInt64(s0.AuxInt) != 8 {
+ continue
+ }
+ x1 := s0.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i2 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ s1 := o0_1
+ if s1.Op != OpPPC64SLDconst || auxIntToInt64(s1.AuxInt) != 16 {
+ continue
+ }
+ x2 := s1.Args[0]
+ if x2.Op != OpPPC64MOVHBRload || x2.Type != t {
+ continue
+ }
+ _ = x2.Args[1]
+ x2_0 := x2.Args[0]
+ if x2_0.Op != OpPPC64MOVDaddr || x2_0.Type != typ.Uintptr {
+ continue
+ }
+ i0 := auxIntToInt32(x2_0.AuxInt)
+ if auxToSym(x2_0.Aux) != s || p != x2_0.Args[0] || mem != x2.Args[1] || !(!config.BigEndian && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x2.Pos, OpPPC64MOVWBRload, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x2.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> s2:(SLDconst x2:(MOVBZload [i3] {s} p mem) [32]) o0:(OR <t> s1:(SLDconst x1:(MOVBZload [i2] {s} p mem) [40]) s0:(SLDconst x0:(MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [48])))
+ // cond: !config.BigEndian && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, s2, o0)
+ // result: @mergePoint(b,x0,x1,x2) (SLDconst <t> (MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [32])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s2 := v_0
+ if s2.Op != OpPPC64SLDconst || auxIntToInt64(s2.AuxInt) != 32 {
+ continue
+ }
+ x2 := s2.Args[0]
+ if x2.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i3 := auxIntToInt32(x2.AuxInt)
+ s := auxToSym(x2.Aux)
+ mem := x2.Args[1]
+ p := x2.Args[0]
+ o0 := v_1
+ if o0.Op != OpPPC64OR || o0.Type != t {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ s1 := o0_0
+ if s1.Op != OpPPC64SLDconst || auxIntToInt64(s1.AuxInt) != 40 {
+ continue
+ }
+ x1 := s1.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i2 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ s0 := o0_1
+ if s0.Op != OpPPC64SLDconst || auxIntToInt64(s0.AuxInt) != 48 {
+ continue
+ }
+ x0 := s0.Args[0]
+ if x0.Op != OpPPC64MOVHBRload || x0.Type != t {
+ continue
+ }
+ _ = x0.Args[1]
+ x0_0 := x0.Args[0]
+ if x0_0.Op != OpPPC64MOVDaddr || x0_0.Type != typ.Uintptr {
+ continue
+ }
+ i0 := auxIntToInt32(x0_0.AuxInt)
+ if auxToSym(x0_0.Aux) != s || p != x0_0.Args[0] || mem != x0.Args[1] || !(!config.BigEndian && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, s2, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x0.Pos, OpPPC64SLDconst, t)
+ v.copyOf(v0)
+ v0.AuxInt = int64ToAuxInt(32)
+ v1 := b.NewValue0(x0.Pos, OpPPC64MOVWBRload, t)
+ v2 := b.NewValue0(x0.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v2.AuxInt = int32ToAuxInt(i0)
+ v2.Aux = symToAux(s)
+ v2.AddArg(p)
+ v1.AddArg2(v2, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> s2:(SLDconst x2:(MOVBZload [i0] {s} p mem) [56]) o0:(OR <t> s1:(SLDconst x1:(MOVBZload [i1] {s} p mem) [48]) s0:(SLDconst x0:(MOVHBRload <t> (MOVDaddr <typ.Uintptr> [i2] {s} p) mem) [32])))
+ // cond: !config.BigEndian && i1 == i0+1 && i2 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, s2, o0)
+ // result: @mergePoint(b,x0,x1,x2) (SLDconst <t> (MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [32])
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s2 := v_0
+ if s2.Op != OpPPC64SLDconst || auxIntToInt64(s2.AuxInt) != 56 {
+ continue
+ }
+ x2 := s2.Args[0]
+ if x2.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x2.AuxInt)
+ s := auxToSym(x2.Aux)
+ mem := x2.Args[1]
+ p := x2.Args[0]
+ o0 := v_1
+ if o0.Op != OpPPC64OR || o0.Type != t {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ s1 := o0_0
+ if s1.Op != OpPPC64SLDconst || auxIntToInt64(s1.AuxInt) != 48 {
+ continue
+ }
+ x1 := s1.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ s0 := o0_1
+ if s0.Op != OpPPC64SLDconst || auxIntToInt64(s0.AuxInt) != 32 {
+ continue
+ }
+ x0 := s0.Args[0]
+ if x0.Op != OpPPC64MOVHBRload || x0.Type != t {
+ continue
+ }
+ _ = x0.Args[1]
+ x0_0 := x0.Args[0]
+ if x0_0.Op != OpPPC64MOVDaddr || x0_0.Type != typ.Uintptr {
+ continue
+ }
+ i2 := auxIntToInt32(x0_0.AuxInt)
+ if auxToSym(x0_0.Aux) != s || p != x0_0.Args[0] || mem != x0.Args[1] || !(!config.BigEndian && i1 == i0+1 && i2 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && o0.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, s2, o0)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2)
+ v0 := b.NewValue0(x0.Pos, OpPPC64SLDconst, t)
+ v.copyOf(v0)
+ v0.AuxInt = int64ToAuxInt(32)
+ v1 := b.NewValue0(x0.Pos, OpPPC64MOVWBRload, t)
+ v2 := b.NewValue0(x0.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v2.AuxInt = int32ToAuxInt(i0)
+ v2.Aux = symToAux(s)
+ v2.AddArg(p)
+ v1.AddArg2(v2, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR <t> s6:(SLDconst x7:(MOVBZload [i7] {s} p mem) [56]) o5:(OR <t> s5:(SLDconst x6:(MOVBZload [i6] {s} p mem) [48]) o4:(OR <t> s4:(SLDconst x5:(MOVBZload [i5] {s} p mem) [40]) o3:(OR <t> s3:(SLDconst x4:(MOVBZload [i4] {s} p mem) [32]) x0:(MOVWZload {s} [i0] p mem)))))
+ // cond: !config.BigEndian && i0%4 == 0 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x0.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses ==1 && x7.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s3.Uses == 1 && s4.Uses == 1 && s5.Uses == 1 && s6.Uses == 1 && mergePoint(b, x0, x4, x5, x6, x7) != nil && clobber(x0, x4, x5, x6, x7, s3, s4, s5, s6, o3, o4, o5)
+ // result: @mergePoint(b,x0,x4,x5,x6,x7) (MOVDload <t> {s} [i0] p mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s6 := v_0
+ if s6.Op != OpPPC64SLDconst || auxIntToInt64(s6.AuxInt) != 56 {
+ continue
+ }
+ x7 := s6.Args[0]
+ if x7.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i7 := auxIntToInt32(x7.AuxInt)
+ s := auxToSym(x7.Aux)
+ mem := x7.Args[1]
+ p := x7.Args[0]
+ o5 := v_1
+ if o5.Op != OpPPC64OR || o5.Type != t {
+ continue
+ }
+ _ = o5.Args[1]
+ o5_0 := o5.Args[0]
+ o5_1 := o5.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o5_0, o5_1 = _i1+1, o5_1, o5_0 {
+ s5 := o5_0
+ if s5.Op != OpPPC64SLDconst || auxIntToInt64(s5.AuxInt) != 48 {
+ continue
+ }
+ x6 := s5.Args[0]
+ if x6.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i6 := auxIntToInt32(x6.AuxInt)
+ if auxToSym(x6.Aux) != s {
+ continue
+ }
+ _ = x6.Args[1]
+ if p != x6.Args[0] || mem != x6.Args[1] {
+ continue
+ }
+ o4 := o5_1
+ if o4.Op != OpPPC64OR || o4.Type != t {
+ continue
+ }
+ _ = o4.Args[1]
+ o4_0 := o4.Args[0]
+ o4_1 := o4.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, o4_0, o4_1 = _i2+1, o4_1, o4_0 {
+ s4 := o4_0
+ if s4.Op != OpPPC64SLDconst || auxIntToInt64(s4.AuxInt) != 40 {
+ continue
+ }
+ x5 := s4.Args[0]
+ if x5.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i5 := auxIntToInt32(x5.AuxInt)
+ if auxToSym(x5.Aux) != s {
+ continue
+ }
+ _ = x5.Args[1]
+ if p != x5.Args[0] || mem != x5.Args[1] {
+ continue
+ }
+ o3 := o4_1
+ if o3.Op != OpPPC64OR || o3.Type != t {
+ continue
+ }
+ _ = o3.Args[1]
+ o3_0 := o3.Args[0]
+ o3_1 := o3.Args[1]
+ for _i3 := 0; _i3 <= 1; _i3, o3_0, o3_1 = _i3+1, o3_1, o3_0 {
+ s3 := o3_0
+ if s3.Op != OpPPC64SLDconst || auxIntToInt64(s3.AuxInt) != 32 {
+ continue
+ }
+ x4 := s3.Args[0]
+ if x4.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i4 := auxIntToInt32(x4.AuxInt)
+ if auxToSym(x4.Aux) != s {
+ continue
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] {
+ continue
+ }
+ x0 := o3_1
+ if x0.Op != OpPPC64MOVWZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(!config.BigEndian && i0%4 == 0 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x0.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s3.Uses == 1 && s4.Uses == 1 && s5.Uses == 1 && s6.Uses == 1 && mergePoint(b, x0, x4, x5, x6, x7) != nil && clobber(x0, x4, x5, x6, x7, s3, s4, s5, s6, o3, o4, o5)) {
+ continue
+ }
+ b = mergePoint(b, x0, x4, x5, x6, x7)
+ v0 := b.NewValue0(x0.Pos, OpPPC64MOVDload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ }
+ }
+ }
+ break
+ }
+ // match: (OR <t> s0:(SLDconst x0:(MOVBZload [i0] {s} p mem) [56]) o0:(OR <t> s1:(SLDconst x1:(MOVBZload [i1] {s} p mem) [48]) o1:(OR <t> s2:(SLDconst x2:(MOVBZload [i2] {s} p mem) [40]) o2:(OR <t> s3:(SLDconst x3:(MOVBZload [i3] {s} p mem) [32]) x4:(MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i4] p) mem)))))
+ // cond: !config.BigEndian && i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4) != nil && clobber(x0, x1, x2, x3, x4, o0, o1, o2, s0, s1, s2, s3)
+ // result: @mergePoint(b,x0,x1,x2,x3,x4) (MOVDBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpPPC64SLDconst || auxIntToInt64(s0.AuxInt) != 56 {
+ continue
+ }
+ x0 := s0.Args[0]
+ if x0.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ o0 := v_1
+ if o0.Op != OpPPC64OR || o0.Type != t {
+ continue
+ }
+ _ = o0.Args[1]
+ o0_0 := o0.Args[0]
+ o0_1 := o0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 {
+ s1 := o0_0
+ if s1.Op != OpPPC64SLDconst || auxIntToInt64(s1.AuxInt) != 48 {
+ continue
+ }
+ x1 := s1.Args[0]
+ if x1.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ o1 := o0_1
+ if o1.Op != OpPPC64OR || o1.Type != t {
+ continue
+ }
+ _ = o1.Args[1]
+ o1_0 := o1.Args[0]
+ o1_1 := o1.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, o1_0, o1_1 = _i2+1, o1_1, o1_0 {
+ s2 := o1_0
+ if s2.Op != OpPPC64SLDconst || auxIntToInt64(s2.AuxInt) != 40 {
+ continue
+ }
+ x2 := s2.Args[0]
+ if x2.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i2 := auxIntToInt32(x2.AuxInt)
+ if auxToSym(x2.Aux) != s {
+ continue
+ }
+ _ = x2.Args[1]
+ if p != x2.Args[0] || mem != x2.Args[1] {
+ continue
+ }
+ o2 := o1_1
+ if o2.Op != OpPPC64OR || o2.Type != t {
+ continue
+ }
+ _ = o2.Args[1]
+ o2_0 := o2.Args[0]
+ o2_1 := o2.Args[1]
+ for _i3 := 0; _i3 <= 1; _i3, o2_0, o2_1 = _i3+1, o2_1, o2_0 {
+ s3 := o2_0
+ if s3.Op != OpPPC64SLDconst || auxIntToInt64(s3.AuxInt) != 32 {
+ continue
+ }
+ x3 := s3.Args[0]
+ if x3.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i3 := auxIntToInt32(x3.AuxInt)
+ if auxToSym(x3.Aux) != s {
+ continue
+ }
+ _ = x3.Args[1]
+ if p != x3.Args[0] || mem != x3.Args[1] {
+ continue
+ }
+ x4 := o2_1
+ if x4.Op != OpPPC64MOVWBRload || x4.Type != t {
+ continue
+ }
+ _ = x4.Args[1]
+ x4_0 := x4.Args[0]
+ if x4_0.Op != OpPPC64MOVDaddr || x4_0.Type != typ.Uintptr {
+ continue
+ }
+ i4 := auxIntToInt32(x4_0.AuxInt)
+ if p != x4_0.Args[0] || mem != x4.Args[1] || !(!config.BigEndian && i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && mergePoint(b, x0, x1, x2, x3, x4) != nil && clobber(x0, x1, x2, x3, x4, o0, o1, o2, s0, s1, s2, s3)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, x2, x3, x4)
+ v0 := b.NewValue0(x4.Pos, OpPPC64MOVDBRload, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x4.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ }
+ }
+ }
+ break
+ }
+ // match: (OR <t> x7:(MOVBZload [i7] {s} p mem) o5:(OR <t> s6:(SLDconst x6:(MOVBZload [i6] {s} p mem) [8]) o4:(OR <t> s5:(SLDconst x5:(MOVBZload [i5] {s} p mem) [16]) o3:(OR <t> s4:(SLDconst x4:(MOVBZload [i4] {s} p mem) [24]) s0:(SLWconst x3:(MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [32])))))
+ // cond: !config.BigEndian && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && s4.Uses == 1 && s5.Uses == 1 && s6.Uses == 1 && mergePoint(b, x3, x4, x5, x6, x7) != nil && clobber(x3, x4, x5, x6, x7, o3, o4, o5, s0, s4, s5, s6)
+ // result: @mergePoint(b,x3,x4,x5,x6,x7) (MOVDBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x7 := v_0
+ if x7.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i7 := auxIntToInt32(x7.AuxInt)
+ s := auxToSym(x7.Aux)
+ mem := x7.Args[1]
+ p := x7.Args[0]
+ o5 := v_1
+ if o5.Op != OpPPC64OR || o5.Type != t {
+ continue
+ }
+ _ = o5.Args[1]
+ o5_0 := o5.Args[0]
+ o5_1 := o5.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o5_0, o5_1 = _i1+1, o5_1, o5_0 {
+ s6 := o5_0
+ if s6.Op != OpPPC64SLDconst || auxIntToInt64(s6.AuxInt) != 8 {
+ continue
+ }
+ x6 := s6.Args[0]
+ if x6.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i6 := auxIntToInt32(x6.AuxInt)
+ if auxToSym(x6.Aux) != s {
+ continue
+ }
+ _ = x6.Args[1]
+ if p != x6.Args[0] || mem != x6.Args[1] {
+ continue
+ }
+ o4 := o5_1
+ if o4.Op != OpPPC64OR || o4.Type != t {
+ continue
+ }
+ _ = o4.Args[1]
+ o4_0 := o4.Args[0]
+ o4_1 := o4.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, o4_0, o4_1 = _i2+1, o4_1, o4_0 {
+ s5 := o4_0
+ if s5.Op != OpPPC64SLDconst || auxIntToInt64(s5.AuxInt) != 16 {
+ continue
+ }
+ x5 := s5.Args[0]
+ if x5.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i5 := auxIntToInt32(x5.AuxInt)
+ if auxToSym(x5.Aux) != s {
+ continue
+ }
+ _ = x5.Args[1]
+ if p != x5.Args[0] || mem != x5.Args[1] {
+ continue
+ }
+ o3 := o4_1
+ if o3.Op != OpPPC64OR || o3.Type != t {
+ continue
+ }
+ _ = o3.Args[1]
+ o3_0 := o3.Args[0]
+ o3_1 := o3.Args[1]
+ for _i3 := 0; _i3 <= 1; _i3, o3_0, o3_1 = _i3+1, o3_1, o3_0 {
+ s4 := o3_0
+ if s4.Op != OpPPC64SLDconst || auxIntToInt64(s4.AuxInt) != 24 {
+ continue
+ }
+ x4 := s4.Args[0]
+ if x4.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i4 := auxIntToInt32(x4.AuxInt)
+ if auxToSym(x4.Aux) != s {
+ continue
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] {
+ continue
+ }
+ s0 := o3_1
+ if s0.Op != OpPPC64SLWconst || auxIntToInt64(s0.AuxInt) != 32 {
+ continue
+ }
+ x3 := s0.Args[0]
+ if x3.Op != OpPPC64MOVWBRload || x3.Type != t {
+ continue
+ }
+ _ = x3.Args[1]
+ x3_0 := x3.Args[0]
+ if x3_0.Op != OpPPC64MOVDaddr || x3_0.Type != typ.Uintptr {
+ continue
+ }
+ i0 := auxIntToInt32(x3_0.AuxInt)
+ if auxToSym(x3_0.Aux) != s || p != x3_0.Args[0] || mem != x3.Args[1] || !(!config.BigEndian && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && s4.Uses == 1 && s5.Uses == 1 && s6.Uses == 1 && mergePoint(b, x3, x4, x5, x6, x7) != nil && clobber(x3, x4, x5, x6, x7, o3, o4, o5, s0, s4, s5, s6)) {
+ continue
+ }
+ b = mergePoint(b, x3, x4, x5, x6, x7)
+ v0 := b.NewValue0(x3.Pos, OpPPC64MOVDBRload, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x3.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ }
+ }
+ }
+ break
+ }
+ // match: (OR <t> x7:(MOVBZload [i7] {s} p mem) o5:(OR <t> s6:(SLDconst x6:(MOVBZload [i6] {s} p mem) [8]) o4:(OR <t> s5:(SLDconst x5:(MOVBZload [i5] {s} p mem) [16]) o3:(OR <t> s4:(SLDconst x4:(MOVBZload [i4] {s} p mem) [24]) s0:(SLDconst x3:(MOVWBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem) [32])))))
+ // cond: !config.BigEndian && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && s4.Uses == 1 && s5.Uses == 1 && s6.Uses == 1 && mergePoint(b, x3, x4, x5, x6, x7) != nil && clobber(x3, x4, x5, x6, x7, o3, o4, o5, s0, s4, s5, s6)
+ // result: @mergePoint(b,x3,x4,x5,x6,x7) (MOVDBRload <t> (MOVDaddr <typ.Uintptr> [i0] {s} p) mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x7 := v_0
+ if x7.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i7 := auxIntToInt32(x7.AuxInt)
+ s := auxToSym(x7.Aux)
+ mem := x7.Args[1]
+ p := x7.Args[0]
+ o5 := v_1
+ if o5.Op != OpPPC64OR || o5.Type != t {
+ continue
+ }
+ _ = o5.Args[1]
+ o5_0 := o5.Args[0]
+ o5_1 := o5.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, o5_0, o5_1 = _i1+1, o5_1, o5_0 {
+ s6 := o5_0
+ if s6.Op != OpPPC64SLDconst || auxIntToInt64(s6.AuxInt) != 8 {
+ continue
+ }
+ x6 := s6.Args[0]
+ if x6.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i6 := auxIntToInt32(x6.AuxInt)
+ if auxToSym(x6.Aux) != s {
+ continue
+ }
+ _ = x6.Args[1]
+ if p != x6.Args[0] || mem != x6.Args[1] {
+ continue
+ }
+ o4 := o5_1
+ if o4.Op != OpPPC64OR || o4.Type != t {
+ continue
+ }
+ _ = o4.Args[1]
+ o4_0 := o4.Args[0]
+ o4_1 := o4.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, o4_0, o4_1 = _i2+1, o4_1, o4_0 {
+ s5 := o4_0
+ if s5.Op != OpPPC64SLDconst || auxIntToInt64(s5.AuxInt) != 16 {
+ continue
+ }
+ x5 := s5.Args[0]
+ if x5.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i5 := auxIntToInt32(x5.AuxInt)
+ if auxToSym(x5.Aux) != s {
+ continue
+ }
+ _ = x5.Args[1]
+ if p != x5.Args[0] || mem != x5.Args[1] {
+ continue
+ }
+ o3 := o4_1
+ if o3.Op != OpPPC64OR || o3.Type != t {
+ continue
+ }
+ _ = o3.Args[1]
+ o3_0 := o3.Args[0]
+ o3_1 := o3.Args[1]
+ for _i3 := 0; _i3 <= 1; _i3, o3_0, o3_1 = _i3+1, o3_1, o3_0 {
+ s4 := o3_0
+ if s4.Op != OpPPC64SLDconst || auxIntToInt64(s4.AuxInt) != 24 {
+ continue
+ }
+ x4 := s4.Args[0]
+ if x4.Op != OpPPC64MOVBZload {
+ continue
+ }
+ i4 := auxIntToInt32(x4.AuxInt)
+ if auxToSym(x4.Aux) != s {
+ continue
+ }
+ _ = x4.Args[1]
+ if p != x4.Args[0] || mem != x4.Args[1] {
+ continue
+ }
+ s0 := o3_1
+ if s0.Op != OpPPC64SLDconst || auxIntToInt64(s0.AuxInt) != 32 {
+ continue
+ }
+ x3 := s0.Args[0]
+ if x3.Op != OpPPC64MOVWBRload || x3.Type != t {
+ continue
+ }
+ _ = x3.Args[1]
+ x3_0 := x3.Args[0]
+ if x3_0.Op != OpPPC64MOVDaddr || x3_0.Type != typ.Uintptr {
+ continue
+ }
+ i0 := auxIntToInt32(x3_0.AuxInt)
+ if auxToSym(x3_0.Aux) != s || p != x3_0.Args[0] || mem != x3.Args[1] || !(!config.BigEndian && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && s4.Uses == 1 && s5.Uses == 1 && s6.Uses == 1 && mergePoint(b, x3, x4, x5, x6, x7) != nil && clobber(x3, x4, x5, x6, x7, o3, o4, o5, s0, s4, s5, s6)) {
+ continue
+ }
+ b = mergePoint(b, x3, x4, x5, x6, x7)
+ v0 := b.NewValue0(x3.Pos, OpPPC64MOVDBRload, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x3.Pos, OpPPC64MOVDaddr, typ.Uintptr)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg(p)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ }
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64ORN(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ORN x (MOVDconst [-1]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORN (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [c|^d])
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c | ^d)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64ORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ORconst [c] (ORconst [d] x))
+ // result: (ORconst [c|d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64ORconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpPPC64ORconst)
+ v.AuxInt = int64ToAuxInt(c | d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORconst [-1] _)
+ // result: (MOVDconst [-1])
+ for {
+ if auxIntToInt64(v.AuxInt) != -1 {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (ORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64ROTL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ROTL x (MOVDconst [c]))
+ // result: (ROTLconst x [c&63])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64ROTLconst)
+ v.AuxInt = int64ToAuxInt(c & 63)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64ROTLW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ROTLW x (MOVDconst [c]))
+ // result: (ROTLWconst x [c&31])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64ROTLWconst)
+ v.AuxInt = int64ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64ROTLWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ROTLWconst [r] (AND (MOVDconst [m]) x))
+ // cond: isPPC64WordRotateMask(m)
+ // result: (RLWINM [encodePPC64RotateMask(r,rotateLeft32(m,r),32)] x)
+ for {
+ r := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64AND {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ m := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_1
+ if !(isPPC64WordRotateMask(m)) {
+ continue
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(encodePPC64RotateMask(r, rotateLeft32(m, r), 32))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ROTLWconst [r] (ANDconst [m] x))
+ // cond: isPPC64WordRotateMask(m)
+ // result: (RLWINM [encodePPC64RotateMask(r,rotateLeft32(m,r),32)] x)
+ for {
+ r := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64ANDconst {
+ break
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(isPPC64WordRotateMask(m)) {
+ break
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(encodePPC64RotateMask(r, rotateLeft32(m, r), 32))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SLD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SLD x (MOVDconst [c]))
+ // result: (SLDconst [c&63 | (c>>6&1*63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64SLDconst)
+ v.AuxInt = int64ToAuxInt(c&63 | (c >> 6 & 1 * 63))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SLDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SLDconst [l] (SRWconst [r] x))
+ // cond: mergePPC64SldiSrw(l,r) != 0
+ // result: (RLWINM [mergePPC64SldiSrw(l,r)] x)
+ for {
+ l := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ r := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(mergePPC64SldiSrw(l, r) != 0) {
+ break
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(mergePPC64SldiSrw(l, r))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLDconst [c] z:(MOVBZreg x))
+ // cond: c < 8 && z.Uses == 1
+ // result: (CLRLSLDI [newPPC64ShiftAuxInt(c,56,63,64)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := z.Args[0]
+ if !(c < 8 && z.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64CLRLSLDI)
+ v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 56, 63, 64))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLDconst [c] z:(MOVHZreg x))
+ // cond: c < 16 && z.Uses == 1
+ // result: (CLRLSLDI [newPPC64ShiftAuxInt(c,48,63,64)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := z.Args[0]
+ if !(c < 16 && z.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64CLRLSLDI)
+ v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 48, 63, 64))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLDconst [c] z:(MOVWZreg x))
+ // cond: c < 32 && z.Uses == 1
+ // result: (CLRLSLDI [newPPC64ShiftAuxInt(c,32,63,64)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := z.Args[0]
+ if !(c < 32 && z.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64CLRLSLDI)
+ v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 32, 63, 64))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLDconst [c] z:(ANDconst [d] x))
+ // cond: z.Uses == 1 && isPPC64ValidShiftMask(d) && c <= (64-getPPC64ShiftMaskLength(d))
+ // result: (CLRLSLDI [newPPC64ShiftAuxInt(c,64-getPPC64ShiftMaskLength(d),63,64)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64ANDconst {
+ break
+ }
+ d := auxIntToInt64(z.AuxInt)
+ x := z.Args[0]
+ if !(z.Uses == 1 && isPPC64ValidShiftMask(d) && c <= (64-getPPC64ShiftMaskLength(d))) {
+ break
+ }
+ v.reset(OpPPC64CLRLSLDI)
+ v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 64-getPPC64ShiftMaskLength(d), 63, 64))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLDconst [c] z:(AND (MOVDconst [d]) x))
+ // cond: z.Uses == 1 && isPPC64ValidShiftMask(d) && c<=(64-getPPC64ShiftMaskLength(d))
+ // result: (CLRLSLDI [newPPC64ShiftAuxInt(c,64-getPPC64ShiftMaskLength(d),63,64)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ if z_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ d := auxIntToInt64(z_0.AuxInt)
+ x := z_1
+ if !(z.Uses == 1 && isPPC64ValidShiftMask(d) && c <= (64-getPPC64ShiftMaskLength(d))) {
+ continue
+ }
+ v.reset(OpPPC64CLRLSLDI)
+ v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 64-getPPC64ShiftMaskLength(d), 63, 64))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (SLDconst [c] z:(MOVWreg x))
+ // cond: c < 32 && objabi.GOPPC64 >= 9
+ // result: (EXTSWSLconst [c] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := z.Args[0]
+ if !(c < 32 && objabi.GOPPC64 >= 9) {
+ break
+ }
+ v.reset(OpPPC64EXTSWSLconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SLW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SLW x (MOVDconst [c]))
+ // result: (SLWconst [c&31 | (c>>5&1*31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64SLWconst)
+ v.AuxInt = int64ToAuxInt(c&31 | (c >> 5 & 1 * 31))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SLWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SLWconst [c] z:(MOVBZreg x))
+ // cond: z.Uses == 1 && c < 8
+ // result: (CLRLSLWI [newPPC64ShiftAuxInt(c,24,31,32)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := z.Args[0]
+ if !(z.Uses == 1 && c < 8) {
+ break
+ }
+ v.reset(OpPPC64CLRLSLWI)
+ v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 24, 31, 32))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLWconst [c] z:(MOVHZreg x))
+ // cond: z.Uses == 1 && c < 16
+ // result: (CLRLSLWI [newPPC64ShiftAuxInt(c,16,31,32)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := z.Args[0]
+ if !(z.Uses == 1 && c < 16) {
+ break
+ }
+ v.reset(OpPPC64CLRLSLWI)
+ v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 16, 31, 32))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLWconst [c] z:(ANDconst [d] x))
+ // cond: z.Uses == 1 && isPPC64ValidShiftMask(d) && c<=(32-getPPC64ShiftMaskLength(d))
+ // result: (CLRLSLWI [newPPC64ShiftAuxInt(c,32-getPPC64ShiftMaskLength(d),31,32)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64ANDconst {
+ break
+ }
+ d := auxIntToInt64(z.AuxInt)
+ x := z.Args[0]
+ if !(z.Uses == 1 && isPPC64ValidShiftMask(d) && c <= (32-getPPC64ShiftMaskLength(d))) {
+ break
+ }
+ v.reset(OpPPC64CLRLSLWI)
+ v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 32-getPPC64ShiftMaskLength(d), 31, 32))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLWconst [c] z:(AND (MOVDconst [d]) x))
+ // cond: z.Uses == 1 && isPPC64ValidShiftMask(d) && c<=(32-getPPC64ShiftMaskLength(d))
+ // result: (CLRLSLWI [newPPC64ShiftAuxInt(c,32-getPPC64ShiftMaskLength(d),31,32)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ if z_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ d := auxIntToInt64(z_0.AuxInt)
+ x := z_1
+ if !(z.Uses == 1 && isPPC64ValidShiftMask(d) && c <= (32-getPPC64ShiftMaskLength(d))) {
+ continue
+ }
+ v.reset(OpPPC64CLRLSLWI)
+ v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 32-getPPC64ShiftMaskLength(d), 31, 32))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (SLWconst [c] z:(MOVWreg x))
+ // cond: c < 32 && objabi.GOPPC64 >= 9
+ // result: (EXTSWSLconst [c] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ z := v_0
+ if z.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := z.Args[0]
+ if !(c < 32 && objabi.GOPPC64 >= 9) {
+ break
+ }
+ v.reset(OpPPC64EXTSWSLconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SRAD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRAD x (MOVDconst [c]))
+ // result: (SRADconst [c&63 | (c>>6&1*63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(c&63 | (c >> 6 & 1 * 63))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SRAW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRAW x (MOVDconst [c]))
+ // result: (SRAWconst [c&31 | (c>>5&1*31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c&31 | (c >> 5 & 1 * 31))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SRD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRD x (MOVDconst [c]))
+ // result: (SRDconst [c&63 | (c>>6&1*63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = int64ToAuxInt(c&63 | (c >> 6 & 1 * 63))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SRW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRW x (MOVDconst [c]))
+ // result: (SRWconst [c&31 | (c>>5&1*31)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c&31 | (c >> 5 & 1 * 31))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SRWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRWconst (ANDconst [m] x) [s])
+ // cond: mergePPC64RShiftMask(m>>uint(s),s,32) == 0
+ // result: (MOVDconst [0])
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64ANDconst {
+ break
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ if !(mergePPC64RShiftMask(m>>uint(s), s, 32) == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SRWconst (ANDconst [m] x) [s])
+ // cond: mergePPC64AndSrwi(m>>uint(s),s) != 0
+ // result: (RLWINM [mergePPC64AndSrwi(m>>uint(s),s)] x)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64ANDconst {
+ break
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(mergePPC64AndSrwi(m>>uint(s), s) != 0) {
+ break
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(mergePPC64AndSrwi(m>>uint(s), s))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRWconst (AND (MOVDconst [m]) x) [s])
+ // cond: mergePPC64RShiftMask(m>>uint(s),s,32) == 0
+ // result: (MOVDconst [0])
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64AND {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ m := auxIntToInt64(v_0_0.AuxInt)
+ if !(mergePPC64RShiftMask(m>>uint(s), s, 32) == 0) {
+ continue
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (SRWconst (AND (MOVDconst [m]) x) [s])
+ // cond: mergePPC64AndSrwi(m>>uint(s),s) != 0
+ // result: (RLWINM [mergePPC64AndSrwi(m>>uint(s),s)] x)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64AND {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ m := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_1
+ if !(mergePPC64AndSrwi(m>>uint(s), s) != 0) {
+ continue
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(mergePPC64AndSrwi(m>>uint(s), s))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SUB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUB x (MOVDconst [c]))
+ // cond: is32Bit(-c)
+ // result: (ADDconst [-c] x)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(-c)) {
+ break
+ }
+ v.reset(OpPPC64ADDconst)
+ v.AuxInt = int64ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB (MOVDconst [c]) x)
+ // cond: is32Bit(c)
+ // result: (SUBFCconst [c] x)
+ for {
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64SUBFCconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64SUBFCconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SUBFCconst [c] (NEG x))
+ // result: (ADDconst [c] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64NEG {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64ADDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBFCconst [c] (SUBFCconst [d] x))
+ // cond: is32Bit(c-d)
+ // result: (ADDconst [c-d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64SUBFCconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(c - d)) {
+ break
+ }
+ v.reset(OpPPC64ADDconst)
+ v.AuxInt = int64ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBFCconst [0] x)
+ // result: (NEG x)
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.reset(OpPPC64NEG)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64XOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (XOR (SLDconst x [c]) (SRDconst x [d]))
+ // cond: d == 64-c
+ // result: (ROTLconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpPPC64SRDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 64-c) {
+ continue
+ }
+ v.reset(OpPPC64ROTLconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR (SLWconst x [c]) (SRWconst x [d]))
+ // cond: d == 32-c
+ // result: (ROTLWconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLWconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpPPC64SRWconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if x != v_1.Args[0] || !(d == 32-c) {
+ continue
+ }
+ v.reset(OpPPC64ROTLWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y))))
+ // result: (ROTL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLD {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int64 || auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRD {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUB || v_1_1.Type != typ.UInt {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1_0.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpPPC64ANDconst || v_1_1_1.Type != typ.UInt || auxIntToInt64(v_1_1_1.AuxInt) != 63 || y != v_1_1_1.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR (SLD x (ANDconst <typ.Int64> [63] y)) (SRD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y))))
+ // result: (ROTL x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLD {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int64 || auxIntToInt64(v_0_1.AuxInt) != 63 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRD {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUBFCconst || v_1_1.Type != typ.UInt || auxIntToInt64(v_1_1.AuxInt) != 64 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64ANDconst || v_1_1_0.Type != typ.UInt || auxIntToInt64(v_1_1_0.AuxInt) != 63 || y != v_1_1_0.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTL)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y))))
+ // result: (ROTLW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLW {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int32 || auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRW {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUBFCconst || v_1_1.Type != typ.UInt || auxIntToInt64(v_1_1.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64ANDconst || v_1_1_0.Type != typ.UInt || auxIntToInt64(v_1_1_0.AuxInt) != 31 || y != v_1_1_0.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR (SLW x (ANDconst <typ.Int32> [31] y)) (SRW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y))))
+ // result: (ROTLW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64SLW {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpPPC64ANDconst || v_0_1.Type != typ.Int32 || auxIntToInt64(v_0_1.AuxInt) != 31 {
+ continue
+ }
+ y := v_0_1.Args[0]
+ if v_1.Op != OpPPC64SRW {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64SUB || v_1_1.Type != typ.UInt {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1_0.AuxInt) != 32 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpPPC64ANDconst || v_1_1_1.Type != typ.UInt || auxIntToInt64(v_1_1_1.AuxInt) != 31 || y != v_1_1_1.Args[0] {
+ continue
+ }
+ v.reset(OpPPC64ROTLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (XOR (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [c^d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpPPC64MOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(c ^ d)
+ return true
+ }
+ break
+ }
+ // match: (XOR x (MOVDconst [c]))
+ // cond: isU32Bit(c)
+ // result: (XORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isU32Bit(c)) {
+ continue
+ }
+ v.reset(OpPPC64XORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64XORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (XORconst [c] (XORconst [d] x))
+ // result: (XORconst [c^d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpPPC64XORconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpPPC64XORconst)
+ v.AuxInt = int64ToAuxInt(c ^ d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (XORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPanicBounds(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicBoundsA [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(OpPPC64LoweredPanicBoundsA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicBoundsB [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(OpPPC64LoweredPanicBoundsB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicBoundsC [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(OpPPC64LoweredPanicBoundsC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPopCount16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount16 x)
+ // result: (POPCNTW (MOVHZreg x))
+ for {
+ x := v_0
+ v.reset(OpPPC64POPCNTW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPopCount32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount32 x)
+ // result: (POPCNTW (MOVWZreg x))
+ for {
+ x := v_0
+ v.reset(OpPPC64POPCNTW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpPopCount8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount8 x)
+ // result: (POPCNTB (MOVBZreg x))
+ for {
+ x := v_0
+ v.reset(OpPPC64POPCNTB)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRotateLeft16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft16 <t> x (MOVDconst [c]))
+ // result: (Or16 (Lsh16x64 <t> x (MOVDconst [c&15])) (Rsh16Ux64 <t> x (MOVDconst [-c&15])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpLsh16x64, t)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(c & 15)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh16Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(-c & 15)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpRotateLeft32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RotateLeft32 x (MOVDconst [c]))
+ // result: (ROTLWconst [c&31] x)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64ROTLWconst)
+ v.AuxInt = int64ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RotateLeft32 x y)
+ // result: (ROTLW x y)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64ROTLW)
+ v.AddArg2(x, y)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRotateLeft64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RotateLeft64 x (MOVDconst [c]))
+ // result: (ROTLconst [c&63] x)
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpPPC64ROTLconst)
+ v.AuxInt = int64ToAuxInt(c & 63)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RotateLeft64 x y)
+ // result: (ROTL x y)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64ROTL)
+ v.AddArg2(x, y)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRotateLeft8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft8 <t> x (MOVDconst [c]))
+ // result: (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpLsh8x64, t)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(c & 7)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh8Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(-c & 7)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16Ux16 x y)
+ // result: (SRW (ZeroExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v5.AuxInt = int64ToAuxInt(16)
+ v3.AddArg2(v4, v5)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux32 x (MOVDconst [c]))
+ // cond: uint32(c) < 16
+ // result: (SRWconst (ZeroExt16to32 x) [c&15])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 16) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c & 15)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh16Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16Ux32 x y)
+ // result: (SRW (ZeroExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(16)
+ v3.AddArg2(y, v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux64 _ (MOVDconst [c]))
+ // cond: uint64(c) >= 16
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh16Ux64 x (MOVDconst [c]))
+ // cond: uint64(c) < 16
+ // result: (SRWconst (ZeroExt16to32 x) [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 16) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh16Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16Ux64 x y)
+ // result: (SRW (ZeroExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(16)
+ v3.AddArg2(y, v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16Ux8 x y)
+ // result: (SRW (ZeroExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v5.AuxInt = int64ToAuxInt(16)
+ v3.AddArg2(v4, v5)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16x16 x y)
+ // result: (SRAW (SignExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v5.AuxInt = int64ToAuxInt(16)
+ v3.AddArg2(v4, v5)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x32 x (MOVDconst [c]))
+ // cond: uint32(c) < 16
+ // result: (SRAWconst (SignExt16to32 x) [c&15])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 16) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c & 15)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh16x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16x32 x y)
+ // result: (SRAW (SignExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(16)
+ v3.AddArg2(y, v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x64 x (MOVDconst [c]))
+ // cond: uint64(c) >= 16
+ // result: (SRAWconst (SignExt16to32 x) [63])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(63)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh16x64 x (MOVDconst [c]))
+ // cond: uint64(c) < 16
+ // result: (SRAWconst (SignExt16to32 x) [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 16) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh16x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16x64 x y)
+ // result: (SRAW (SignExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(16)
+ v3.AddArg2(y, v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16x8 x y)
+ // result: (SRAW (SignExt16to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [16]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v5.AuxInt = int64ToAuxInt(16)
+ v3.AddArg2(v4, v5)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32Ux16 x y)
+ // result: (SRW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux32 x (MOVDconst [c]))
+ // cond: uint32(c) < 32
+ // result: (SRWconst x [c&31])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 32) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32Ux32 x y)
+ // result: (SRW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux64 _ (MOVDconst [c]))
+ // cond: uint64(c) >= 32
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh32Ux64 x (MOVDconst [c]))
+ // cond: uint64(c) < 32
+ // result: (SRWconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 32) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32Ux64 x (AND y (MOVDconst [31])))
+ // result: (SRW x (ANDconst <typ.Int32> [31] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64AND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ y := v_1_0
+ if v_1_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1.AuxInt) != 31 {
+ continue
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.Int32)
+ v0.AuxInt = int64ToAuxInt(31)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh32Ux64 x (ANDconst <typ.UInt> [31] y))
+ // result: (SRW x (ANDconst <typ.UInt> [31] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64ANDconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 31 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(31)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32Ux64 x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))
+ // result: (SRW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUB || v_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != 32 {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64ANDconst || v_1_1.Type != typ.UInt || auxIntToInt64(v_1_1.AuxInt) != 31 {
+ break
+ }
+ y := v_1_1.Args[0]
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUB, typ.UInt)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(32)
+ v2 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v2.AuxInt = int64ToAuxInt(31)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32Ux64 x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))
+ // result: (SRW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUBFCconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 32 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64ANDconst || v_1_0.Type != typ.UInt || auxIntToInt64(v_1_0.AuxInt) != 31 {
+ break
+ }
+ y := v_1_0.Args[0]
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUBFCconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(32)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v1.AuxInt = int64ToAuxInt(31)
+ v1.AddArg(y)
+ v0.AddArg(v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32Ux64 x (SUB <typ.UInt> (MOVDconst [32]) (AND <typ.UInt> y (MOVDconst [31]))))
+ // result: (SRW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUB || v_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != 32 {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64AND || v_1_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ v_1_1_1 := v_1_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_1_0, v_1_1_1 = _i0+1, v_1_1_1, v_1_1_0 {
+ y := v_1_1_0
+ if v_1_1_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1_1.AuxInt) != 31 {
+ continue
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUB, typ.UInt)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(32)
+ v2 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v2.AuxInt = int64ToAuxInt(31)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh32Ux64 x (SUBFCconst <typ.UInt> [32] (AND <typ.UInt> y (MOVDconst [31]))))
+ // result: (SRW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUBFCconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 32 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64AND || v_1_0.Type != typ.UInt {
+ break
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ v_1_0_1 := v_1_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0_0, v_1_0_1 = _i0+1, v_1_0_1, v_1_0_0 {
+ y := v_1_0_0
+ if v_1_0_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0_1.AuxInt) != 31 {
+ continue
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUBFCconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(32)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v1.AuxInt = int64ToAuxInt(31)
+ v1.AddArg(y)
+ v0.AddArg(v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh32Ux64 x y)
+ // result: (SRW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32Ux8 x y)
+ // result: (SRW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32x16 x y)
+ // result: (SRAW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x32 x (MOVDconst [c]))
+ // cond: uint32(c) < 32
+ // result: (SRAWconst x [c&31])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 32) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32x32 x y)
+ // result: (SRAW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x64 x (MOVDconst [c]))
+ // cond: uint64(c) >= 32
+ // result: (SRAWconst x [63])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(63)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32x64 x (MOVDconst [c]))
+ // cond: uint64(c) < 32
+ // result: (SRAWconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 32) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32x64 x (AND y (MOVDconst [31])))
+ // result: (SRAW x (ANDconst <typ.Int32> [31] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64AND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ y := v_1_0
+ if v_1_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1.AuxInt) != 31 {
+ continue
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.Int32)
+ v0.AuxInt = int64ToAuxInt(31)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh32x64 x (ANDconst <typ.UInt> [31] y))
+ // result: (SRAW x (ANDconst <typ.UInt> [31] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64ANDconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 31 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(31)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x64 x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))
+ // result: (SRAW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUB || v_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != 32 {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64ANDconst || v_1_1.Type != typ.UInt || auxIntToInt64(v_1_1.AuxInt) != 31 {
+ break
+ }
+ y := v_1_1.Args[0]
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUB, typ.UInt)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(32)
+ v2 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v2.AuxInt = int64ToAuxInt(31)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x64 x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))
+ // result: (SRAW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUBFCconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 32 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64ANDconst || v_1_0.Type != typ.UInt || auxIntToInt64(v_1_0.AuxInt) != 31 {
+ break
+ }
+ y := v_1_0.Args[0]
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUBFCconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(32)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v1.AuxInt = int64ToAuxInt(31)
+ v1.AddArg(y)
+ v0.AddArg(v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x64 x (SUB <typ.UInt> (MOVDconst [32]) (AND <typ.UInt> y (MOVDconst [31]))))
+ // result: (SRAW x (SUB <typ.UInt> (MOVDconst [32]) (ANDconst <typ.UInt> [31] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUB || v_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != 32 {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64AND || v_1_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ v_1_1_1 := v_1_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_1_0, v_1_1_1 = _i0+1, v_1_1_1, v_1_1_0 {
+ y := v_1_1_0
+ if v_1_1_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1_1.AuxInt) != 31 {
+ continue
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUB, typ.UInt)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(32)
+ v2 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v2.AuxInt = int64ToAuxInt(31)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh32x64 x (SUBFCconst <typ.UInt> [32] (AND <typ.UInt> y (MOVDconst [31]))))
+ // result: (SRAW x (SUBFCconst <typ.UInt> [32] (ANDconst <typ.UInt> [31] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUBFCconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 32 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64AND || v_1_0.Type != typ.UInt {
+ break
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ v_1_0_1 := v_1_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0_0, v_1_0_1 = _i0+1, v_1_0_1, v_1_0_0 {
+ y := v_1_0_0
+ if v_1_0_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0_1.AuxInt) != 31 {
+ continue
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUBFCconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(32)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v1.AuxInt = int64ToAuxInt(31)
+ v1.AddArg(y)
+ v0.AddArg(v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh32x64 x y)
+ // result: (SRAW x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32x8 x y)
+ // result: (SRAW x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [32]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh64Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64Ux16 x y)
+ // result: (SRD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh64Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux32 x (MOVDconst [c]))
+ // cond: uint32(c) < 64
+ // result: (SRDconst x [c&63])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 64) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = int64ToAuxInt(c & 63)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh64Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64Ux32 x y)
+ // result: (SRD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh64Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux64 _ (MOVDconst [c]))
+ // cond: uint64(c) >= 64
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh64Ux64 x (MOVDconst [c]))
+ // cond: uint64(c) < 64
+ // result: (SRDconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 64) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh64Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64Ux64 x (AND y (MOVDconst [63])))
+ // result: (SRD x (ANDconst <typ.Int64> [63] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64AND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ y := v_1_0
+ if v_1_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1.AuxInt) != 63 {
+ continue
+ }
+ v.reset(OpPPC64SRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(63)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh64Ux64 x (ANDconst <typ.UInt> [63] y))
+ // result: (SRD x (ANDconst <typ.UInt> [63] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64ANDconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 63 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpPPC64SRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(63)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux64 x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))
+ // result: (SRD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUB || v_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != 64 {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64ANDconst || v_1_1.Type != typ.UInt || auxIntToInt64(v_1_1.AuxInt) != 63 {
+ break
+ }
+ y := v_1_1.Args[0]
+ v.reset(OpPPC64SRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUB, typ.UInt)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(64)
+ v2 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v2.AuxInt = int64ToAuxInt(63)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux64 x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))
+ // result: (SRD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUBFCconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 64 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64ANDconst || v_1_0.Type != typ.UInt || auxIntToInt64(v_1_0.AuxInt) != 63 {
+ break
+ }
+ y := v_1_0.Args[0]
+ v.reset(OpPPC64SRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUBFCconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(64)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v1.AuxInt = int64ToAuxInt(63)
+ v1.AddArg(y)
+ v0.AddArg(v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux64 x (SUB <typ.UInt> (MOVDconst [64]) (AND <typ.UInt> y (MOVDconst [63]))))
+ // result: (SRD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUB || v_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != 64 {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64AND || v_1_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ v_1_1_1 := v_1_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_1_0, v_1_1_1 = _i0+1, v_1_1_1, v_1_1_0 {
+ y := v_1_1_0
+ if v_1_1_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1_1.AuxInt) != 63 {
+ continue
+ }
+ v.reset(OpPPC64SRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUB, typ.UInt)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(64)
+ v2 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v2.AuxInt = int64ToAuxInt(63)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh64Ux64 x (SUBFCconst <typ.UInt> [64] (AND <typ.UInt> y (MOVDconst [63]))))
+ // result: (SRD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUBFCconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 64 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64AND || v_1_0.Type != typ.UInt {
+ break
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ v_1_0_1 := v_1_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0_0, v_1_0_1 = _i0+1, v_1_0_1, v_1_0_0 {
+ y := v_1_0_0
+ if v_1_0_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0_1.AuxInt) != 63 {
+ continue
+ }
+ v.reset(OpPPC64SRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUBFCconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(64)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v1.AuxInt = int64ToAuxInt(63)
+ v1.AddArg(y)
+ v0.AddArg(v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh64Ux64 x y)
+ // result: (SRD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh64Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64Ux8 x y)
+ // result: (SRD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64x16 x y)
+ // result: (SRAD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x32 x (MOVDconst [c]))
+ // cond: uint32(c) < 64
+ // result: (SRADconst x [c&63])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 64) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(c & 63)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh64x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64x32 x y)
+ // result: (SRAD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x64 x (MOVDconst [c]))
+ // cond: uint64(c) >= 64
+ // result: (SRADconst x [63])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(63)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh64x64 x (MOVDconst [c]))
+ // cond: uint64(c) < 64
+ // result: (SRADconst x [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 64) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh64x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64x64 x (AND y (MOVDconst [63])))
+ // result: (SRAD x (ANDconst <typ.Int64> [63] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64AND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ y := v_1_0
+ if v_1_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1.AuxInt) != 63 {
+ continue
+ }
+ v.reset(OpPPC64SRAD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(63)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh64x64 x (ANDconst <typ.UInt> [63] y))
+ // result: (SRAD x (ANDconst <typ.UInt> [63] y))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64ANDconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 63 {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpPPC64SRAD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(63)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x64 x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))
+ // result: (SRAD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUB || v_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != 64 {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64ANDconst || v_1_1.Type != typ.UInt || auxIntToInt64(v_1_1.AuxInt) != 63 {
+ break
+ }
+ y := v_1_1.Args[0]
+ v.reset(OpPPC64SRAD)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUB, typ.UInt)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(64)
+ v2 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v2.AuxInt = int64ToAuxInt(63)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x64 x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))
+ // result: (SRAD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUBFCconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 64 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64ANDconst || v_1_0.Type != typ.UInt || auxIntToInt64(v_1_0.AuxInt) != 63 {
+ break
+ }
+ y := v_1_0.Args[0]
+ v.reset(OpPPC64SRAD)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUBFCconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(64)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v1.AuxInt = int64ToAuxInt(63)
+ v1.AddArg(y)
+ v0.AddArg(v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x64 x (SUB <typ.UInt> (MOVDconst [64]) (AND <typ.UInt> y (MOVDconst [63]))))
+ // result: (SRAD x (SUB <typ.UInt> (MOVDconst [64]) (ANDconst <typ.UInt> [63] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUB || v_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != 64 {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpPPC64AND || v_1_1.Type != typ.UInt {
+ break
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ v_1_1_1 := v_1_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_1_0, v_1_1_1 = _i0+1, v_1_1_1, v_1_1_0 {
+ y := v_1_1_0
+ if v_1_1_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_1_1.AuxInt) != 63 {
+ continue
+ }
+ v.reset(OpPPC64SRAD)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUB, typ.UInt)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(64)
+ v2 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v2.AuxInt = int64ToAuxInt(63)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh64x64 x (SUBFCconst <typ.UInt> [64] (AND <typ.UInt> y (MOVDconst [63]))))
+ // result: (SRAD x (SUBFCconst <typ.UInt> [64] (ANDconst <typ.UInt> [63] y)))
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64SUBFCconst || v_1.Type != typ.UInt || auxIntToInt64(v_1.AuxInt) != 64 {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpPPC64AND || v_1_0.Type != typ.UInt {
+ break
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ v_1_0_1 := v_1_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0_0, v_1_0_1 = _i0+1, v_1_0_1, v_1_0_0 {
+ y := v_1_0_0
+ if v_1_0_1.Op != OpPPC64MOVDconst || auxIntToInt64(v_1_0_1.AuxInt) != 63 {
+ continue
+ }
+ v.reset(OpPPC64SRAD)
+ v0 := b.NewValue0(v.Pos, OpPPC64SUBFCconst, typ.UInt)
+ v0.AuxInt = int64ToAuxInt(64)
+ v1 := b.NewValue0(v.Pos, OpPPC64ANDconst, typ.UInt)
+ v1.AuxInt = int64ToAuxInt(63)
+ v1.AddArg(y)
+ v0.AddArg(v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (Rsh64x64 x y)
+ // result: (SRAD x (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64x8 x y)
+ // result: (SRAD x (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAD)
+ v0 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(v3, v4)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8Ux16 x y)
+ // result: (SRW (ZeroExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v5.AuxInt = int64ToAuxInt(8)
+ v3.AddArg2(v4, v5)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux32 x (MOVDconst [c]))
+ // cond: uint32(c) < 8
+ // result: (SRWconst (ZeroExt8to32 x) [c&7])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 8) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c & 7)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh8Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8Ux32 x y)
+ // result: (SRW (ZeroExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(8)
+ v3.AddArg2(y, v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux64 _ (MOVDconst [c]))
+ // cond: uint64(c) >= 8
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh8Ux64 x (MOVDconst [c]))
+ // cond: uint64(c) < 8
+ // result: (SRWconst (ZeroExt8to32 x) [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 8) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh8Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8Ux64 x y)
+ // result: (SRW (ZeroExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(8)
+ v3.AddArg2(y, v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8Ux8 x y)
+ // result: (SRW (ZeroExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v5.AuxInt = int64ToAuxInt(8)
+ v3.AddArg2(v4, v5)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8x16 x y)
+ // result: (SRAW (SignExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt16to64 y) (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v5.AuxInt = int64ToAuxInt(8)
+ v3.AddArg2(v4, v5)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x32 x (MOVDconst [c]))
+ // cond: uint32(c) < 8
+ // result: (SRAWconst (SignExt8to32 x) [c&7])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint32(c) < 8) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c & 7)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh8x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8x32 x y)
+ // result: (SRAW (SignExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(8)
+ v3.AddArg2(y, v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x64 x (MOVDconst [c]))
+ // cond: uint64(c) >= 8
+ // result: (SRAWconst (SignExt8to32 x) [63])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(63)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh8x64 x (MOVDconst [c]))
+ // cond: uint64(c) < 8
+ // result: (SRAWconst (SignExt8to32 x) [c])
+ for {
+ x := v_0
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 8) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh8x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8x64 x y)
+ // result: (SRAW (SignExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU y (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v4.AuxInt = int64ToAuxInt(8)
+ v3.AddArg2(y, v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8x8 x y)
+ // result: (SRAW (SignExt8to32 x) (ISEL [0] y (MOVDconst [-1]) (CMPU (ZeroExt8to64 y) (MOVDconst [8]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpPPC64ISEL, typ.Int32)
+ v1.AuxInt = int32ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpPPC64CMPU, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v5 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64)
+ v5.AuxInt = int64ToAuxInt(8)
+ v3.AddArg2(v4, v5)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuePPC64_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Slicemask <t> x)
+ // result: (SRADconst (NEG <t> x) [63])
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = int64ToAuxInt(63)
+ v0 := b.NewValue0(v.Pos, OpPPC64NEG, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuePPC64_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && is64BitFloat(val.Type)
+ // result: (FMOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpPPC64FMOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && is32BitFloat(val.Type)
+ // result: (FMOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpPPC64FMOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && is32BitFloat(val.Type)
+ // result: (FMOVSstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpPPC64FMOVSstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && (is64BitInt(val.Type) || isPtr(val.Type))
+ // result: (MOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && (is64BitInt(val.Type) || isPtr(val.Type))) {
+ break
+ }
+ v.reset(OpPPC64MOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && is32BitInt(val.Type)
+ // result: (MOVWstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && is32BitInt(val.Type)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 2
+ // result: (MOVHstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 2) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 1
+ // result: (MOVBstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpTrunc16to8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc16to8 <t> x)
+ // cond: isSigned(t)
+ // result: (MOVBreg x)
+ for {
+ t := v.Type
+ x := v_0
+ if !(isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc16to8 x)
+ // result: (MOVBZreg x)
+ for {
+ x := v_0
+ v.reset(OpPPC64MOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpTrunc32to16(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc32to16 <t> x)
+ // cond: isSigned(t)
+ // result: (MOVHreg x)
+ for {
+ t := v.Type
+ x := v_0
+ if !(isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc32to16 x)
+ // result: (MOVHZreg x)
+ for {
+ x := v_0
+ v.reset(OpPPC64MOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpTrunc32to8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc32to8 <t> x)
+ // cond: isSigned(t)
+ // result: (MOVBreg x)
+ for {
+ t := v.Type
+ x := v_0
+ if !(isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc32to8 x)
+ // result: (MOVBZreg x)
+ for {
+ x := v_0
+ v.reset(OpPPC64MOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpTrunc64to16(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc64to16 <t> x)
+ // cond: isSigned(t)
+ // result: (MOVHreg x)
+ for {
+ t := v.Type
+ x := v_0
+ if !(isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc64to16 x)
+ // result: (MOVHZreg x)
+ for {
+ x := v_0
+ v.reset(OpPPC64MOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpTrunc64to32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc64to32 <t> x)
+ // cond: isSigned(t)
+ // result: (MOVWreg x)
+ for {
+ t := v.Type
+ x := v_0
+ if !(isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc64to32 x)
+ // result: (MOVWZreg x)
+ for {
+ x := v_0
+ v.reset(OpPPC64MOVWZreg)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpTrunc64to8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc64to8 <t> x)
+ // cond: isSigned(t)
+ // result: (MOVBreg x)
+ for {
+ t := v.Type
+ x := v_0
+ if !(isSigned(t)) {
+ break
+ }
+ v.reset(OpPPC64MOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc64to8 x)
+ // result: (MOVBZreg x)
+ for {
+ x := v_0
+ v.reset(OpPPC64MOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValuePPC64_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Zero [0] _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_1
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero [1] destptr mem)
+ // result: (MOVBstorezero destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpPPC64MOVBstorezero)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [2] destptr mem)
+ // result: (MOVHstorezero destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpPPC64MOVHstorezero)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [3] destptr mem)
+ // result: (MOVBstorezero [2] destptr (MOVHstorezero destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpPPC64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHstorezero, types.TypeMem)
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [4] destptr mem)
+ // result: (MOVWstorezero destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpPPC64MOVWstorezero)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [5] destptr mem)
+ // result: (MOVBstorezero [4] destptr (MOVWstorezero destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpPPC64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWstorezero, types.TypeMem)
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [6] destptr mem)
+ // result: (MOVHstorezero [4] destptr (MOVWstorezero destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpPPC64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWstorezero, types.TypeMem)
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [7] destptr mem)
+ // result: (MOVBstorezero [6] destptr (MOVHstorezero [4] destptr (MOVWstorezero destptr mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpPPC64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHstorezero, types.TypeMem)
+ v0.AuxInt = int32ToAuxInt(4)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVWstorezero, types.TypeMem)
+ v1.AddArg2(destptr, mem)
+ v0.AddArg2(destptr, v1)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [8] {t} destptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVDstorezero destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ destptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstorezero)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [8] destptr mem)
+ // result: (MOVWstorezero [4] destptr (MOVWstorezero [0] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpPPC64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWstorezero, types.TypeMem)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [12] {t} destptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstorezero [8] destptr (MOVDstorezero [0] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ t := auxToType(v.Aux)
+ destptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDstorezero, types.TypeMem)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [16] {t} destptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVDstorezero [8] destptr (MOVDstorezero [0] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ t := auxToType(v.Aux)
+ destptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDstorezero, types.TypeMem)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [24] {t} destptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVDstorezero [16] destptr (MOVDstorezero [8] destptr (MOVDstorezero [0] destptr mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ t := auxToType(v.Aux)
+ destptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDstorezero, types.TypeMem)
+ v0.AuxInt = int32ToAuxInt(8)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDstorezero, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(0)
+ v1.AddArg2(destptr, mem)
+ v0.AddArg2(destptr, v1)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [32] {t} destptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVDstorezero [24] destptr (MOVDstorezero [16] destptr (MOVDstorezero [8] destptr (MOVDstorezero [0] destptr mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 32 {
+ break
+ }
+ t := auxToType(v.Aux)
+ destptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpPPC64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(24)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVDstorezero, types.TypeMem)
+ v0.AuxInt = int32ToAuxInt(16)
+ v1 := b.NewValue0(v.Pos, OpPPC64MOVDstorezero, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpPPC64MOVDstorezero, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg2(destptr, mem)
+ v1.AddArg2(destptr, v2)
+ v0.AddArg2(destptr, v1)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [s] ptr mem)
+ // cond: objabi.GOPPC64 <= 8 && s < 64
+ // result: (LoweredZeroShort [s] ptr mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ mem := v_1
+ if !(objabi.GOPPC64 <= 8 && s < 64) {
+ break
+ }
+ v.reset(OpPPC64LoweredZeroShort)
+ v.AuxInt = int64ToAuxInt(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Zero [s] ptr mem)
+ // cond: objabi.GOPPC64 <= 8
+ // result: (LoweredZero [s] ptr mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ mem := v_1
+ if !(objabi.GOPPC64 <= 8) {
+ break
+ }
+ v.reset(OpPPC64LoweredZero)
+ v.AuxInt = int64ToAuxInt(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Zero [s] ptr mem)
+ // cond: s < 128 && objabi.GOPPC64 >= 9
+ // result: (LoweredQuadZeroShort [s] ptr mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ mem := v_1
+ if !(s < 128 && objabi.GOPPC64 >= 9) {
+ break
+ }
+ v.reset(OpPPC64LoweredQuadZeroShort)
+ v.AuxInt = int64ToAuxInt(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Zero [s] ptr mem)
+ // cond: objabi.GOPPC64 >= 9
+ // result: (LoweredQuadZero [s] ptr mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ mem := v_1
+ if !(objabi.GOPPC64 >= 9) {
+ break
+ }
+ v.reset(OpPPC64LoweredQuadZero)
+ v.AuxInt = int64ToAuxInt(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteBlockPPC64(b *Block) bool {
+ switch b.Kind {
+ case BlockPPC64EQ:
+ // match: (EQ (CMPconst [0] (ANDconst [c] x)) yes no)
+ // result: (EQ (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPWconst [0] (ANDconst [c] x)) yes no)
+ // result: (EQ (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64EQ, v0)
+ return true
+ }
+ // match: (EQ (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpPPC64FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (EQ (FlagLT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpPPC64FlagLT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (EQ (FlagGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpPPC64FlagGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (EQ (InvertFlags cmp) yes no)
+ // result: (EQ cmp yes no)
+ for b.Controls[0].Op == OpPPC64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockPPC64EQ, cmp)
+ return true
+ }
+ // match: (EQ (CMPconst [0] (ANDconst [c] x)) yes no)
+ // result: (EQ (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPWconst [0] (ANDconst [c] x)) yes no)
+ // result: (EQ (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (ANDCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64EQ, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (CMPconst [0] z:(OR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (ORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64OR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64EQ, v0)
+ return true
+ }
+ break
+ }
+ // match: (EQ (CMPconst [0] z:(XOR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (XORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64XOR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64XORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64EQ, v0)
+ return true
+ }
+ break
+ }
+ case BlockPPC64GE:
+ // match: (GE (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpPPC64FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GE (FlagLT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpPPC64FlagLT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GE (FlagGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpPPC64FlagGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GE (InvertFlags cmp) yes no)
+ // result: (LE cmp yes no)
+ for b.Controls[0].Op == OpPPC64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockPPC64LE, cmp)
+ return true
+ }
+ // match: (GE (CMPconst [0] (ANDconst [c] x)) yes no)
+ // result: (GE (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64GE, v0)
+ return true
+ }
+ // match: (GE (CMPWconst [0] (ANDconst [c] x)) yes no)
+ // result: (GE (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64GE, v0)
+ return true
+ }
+ // match: (GE (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (ANDCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64GE, v0)
+ return true
+ }
+ break
+ }
+ // match: (GE (CMPconst [0] z:(OR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (ORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64OR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64GE, v0)
+ return true
+ }
+ break
+ }
+ // match: (GE (CMPconst [0] z:(XOR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (XORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64XOR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64XORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64GE, v0)
+ return true
+ }
+ break
+ }
+ case BlockPPC64GT:
+ // match: (GT (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpPPC64FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GT (FlagLT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpPPC64FlagLT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (GT (FlagGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpPPC64FlagGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (GT (InvertFlags cmp) yes no)
+ // result: (LT cmp yes no)
+ for b.Controls[0].Op == OpPPC64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockPPC64LT, cmp)
+ return true
+ }
+ // match: (GT (CMPconst [0] (ANDconst [c] x)) yes no)
+ // result: (GT (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64GT, v0)
+ return true
+ }
+ // match: (GT (CMPWconst [0] (ANDconst [c] x)) yes no)
+ // result: (GT (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64GT, v0)
+ return true
+ }
+ // match: (GT (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (ANDCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64GT, v0)
+ return true
+ }
+ break
+ }
+ // match: (GT (CMPconst [0] z:(OR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (ORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64OR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64GT, v0)
+ return true
+ }
+ break
+ }
+ // match: (GT (CMPconst [0] z:(XOR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (XORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64XOR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64XORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64GT, v0)
+ return true
+ }
+ break
+ }
+ case BlockIf:
+ // match: (If (Equal cc) yes no)
+ // result: (EQ cc yes no)
+ for b.Controls[0].Op == OpPPC64Equal {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockPPC64EQ, cc)
+ return true
+ }
+ // match: (If (NotEqual cc) yes no)
+ // result: (NE cc yes no)
+ for b.Controls[0].Op == OpPPC64NotEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockPPC64NE, cc)
+ return true
+ }
+ // match: (If (LessThan cc) yes no)
+ // result: (LT cc yes no)
+ for b.Controls[0].Op == OpPPC64LessThan {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockPPC64LT, cc)
+ return true
+ }
+ // match: (If (LessEqual cc) yes no)
+ // result: (LE cc yes no)
+ for b.Controls[0].Op == OpPPC64LessEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockPPC64LE, cc)
+ return true
+ }
+ // match: (If (GreaterThan cc) yes no)
+ // result: (GT cc yes no)
+ for b.Controls[0].Op == OpPPC64GreaterThan {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockPPC64GT, cc)
+ return true
+ }
+ // match: (If (GreaterEqual cc) yes no)
+ // result: (GE cc yes no)
+ for b.Controls[0].Op == OpPPC64GreaterEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockPPC64GE, cc)
+ return true
+ }
+ // match: (If (FLessThan cc) yes no)
+ // result: (FLT cc yes no)
+ for b.Controls[0].Op == OpPPC64FLessThan {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockPPC64FLT, cc)
+ return true
+ }
+ // match: (If (FLessEqual cc) yes no)
+ // result: (FLE cc yes no)
+ for b.Controls[0].Op == OpPPC64FLessEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockPPC64FLE, cc)
+ return true
+ }
+ // match: (If (FGreaterThan cc) yes no)
+ // result: (FGT cc yes no)
+ for b.Controls[0].Op == OpPPC64FGreaterThan {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockPPC64FGT, cc)
+ return true
+ }
+ // match: (If (FGreaterEqual cc) yes no)
+ // result: (FGE cc yes no)
+ for b.Controls[0].Op == OpPPC64FGreaterEqual {
+ v_0 := b.Controls[0]
+ cc := v_0.Args[0]
+ b.resetWithControl(BlockPPC64FGE, cc)
+ return true
+ }
+ // match: (If cond yes no)
+ // result: (NE (CMPWconst [0] cond) yes no)
+ for {
+ cond := b.Controls[0]
+ v0 := b.NewValue0(cond.Pos, OpPPC64CMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(0)
+ v0.AddArg(cond)
+ b.resetWithControl(BlockPPC64NE, v0)
+ return true
+ }
+ case BlockPPC64LE:
+ // match: (LE (FlagEQ) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpPPC64FlagEQ {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LE (FlagLT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpPPC64FlagLT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LE (FlagGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpPPC64FlagGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LE (InvertFlags cmp) yes no)
+ // result: (GE cmp yes no)
+ for b.Controls[0].Op == OpPPC64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockPPC64GE, cmp)
+ return true
+ }
+ // match: (LE (CMPconst [0] (ANDconst [c] x)) yes no)
+ // result: (LE (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64LE, v0)
+ return true
+ }
+ // match: (LE (CMPWconst [0] (ANDconst [c] x)) yes no)
+ // result: (LE (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64LE, v0)
+ return true
+ }
+ // match: (LE (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (ANDCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64LE, v0)
+ return true
+ }
+ break
+ }
+ // match: (LE (CMPconst [0] z:(OR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (ORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64OR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64LE, v0)
+ return true
+ }
+ break
+ }
+ // match: (LE (CMPconst [0] z:(XOR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (XORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64XOR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64XORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64LE, v0)
+ return true
+ }
+ break
+ }
+ case BlockPPC64LT:
+ // match: (LT (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpPPC64FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LT (FlagLT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpPPC64FlagLT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (LT (FlagGT) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpPPC64FlagGT {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (LT (InvertFlags cmp) yes no)
+ // result: (GT cmp yes no)
+ for b.Controls[0].Op == OpPPC64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockPPC64GT, cmp)
+ return true
+ }
+ // match: (LT (CMPconst [0] (ANDconst [c] x)) yes no)
+ // result: (LT (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64LT, v0)
+ return true
+ }
+ // match: (LT (CMPWconst [0] (ANDconst [c] x)) yes no)
+ // result: (LT (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64LT, v0)
+ return true
+ }
+ // match: (LT (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (ANDCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64LT, v0)
+ return true
+ }
+ break
+ }
+ // match: (LT (CMPconst [0] z:(OR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (ORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64OR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64LT, v0)
+ return true
+ }
+ break
+ }
+ // match: (LT (CMPconst [0] z:(XOR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (XORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64XOR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64XORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64LT, v0)
+ return true
+ }
+ break
+ }
+ case BlockPPC64NE:
+ // match: (NE (CMPWconst [0] (Equal cc)) yes no)
+ // result: (EQ cc yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64Equal {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockPPC64EQ, cc)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (NotEqual cc)) yes no)
+ // result: (NE cc yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64NotEqual {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockPPC64NE, cc)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (LessThan cc)) yes no)
+ // result: (LT cc yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64LessThan {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockPPC64LT, cc)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (LessEqual cc)) yes no)
+ // result: (LE cc yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64LessEqual {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockPPC64LE, cc)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (GreaterThan cc)) yes no)
+ // result: (GT cc yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64GreaterThan {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockPPC64GT, cc)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (GreaterEqual cc)) yes no)
+ // result: (GE cc yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64GreaterEqual {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockPPC64GE, cc)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (FLessThan cc)) yes no)
+ // result: (FLT cc yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64FLessThan {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockPPC64FLT, cc)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (FLessEqual cc)) yes no)
+ // result: (FLE cc yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64FLessEqual {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockPPC64FLE, cc)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (FGreaterThan cc)) yes no)
+ // result: (FGT cc yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64FGreaterThan {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockPPC64FGT, cc)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (FGreaterEqual cc)) yes no)
+ // result: (FGE cc yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64FGreaterEqual {
+ break
+ }
+ cc := v_0_0.Args[0]
+ b.resetWithControl(BlockPPC64FGE, cc)
+ return true
+ }
+ // match: (NE (CMPconst [0] (ANDconst [c] x)) yes no)
+ // result: (NE (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64NE, v0)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (ANDconst [c] x)) yes no)
+ // result: (NE (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64NE, v0)
+ return true
+ }
+ // match: (NE (FlagEQ) yes no)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpPPC64FlagEQ {
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (NE (FlagLT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpPPC64FlagLT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (NE (FlagGT) yes no)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpPPC64FlagGT {
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (NE (InvertFlags cmp) yes no)
+ // result: (NE cmp yes no)
+ for b.Controls[0].Op == OpPPC64InvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ b.resetWithControl(BlockPPC64NE, cmp)
+ return true
+ }
+ // match: (NE (CMPconst [0] (ANDconst [c] x)) yes no)
+ // result: (NE (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64NE, v0)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (ANDconst [c] x)) yes no)
+ // result: (NE (ANDCCconst [c] x) yes no)
+ for b.Controls[0].Op == OpPPC64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64ANDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(x)
+ b.resetWithControl(BlockPPC64NE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (ANDCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64AND {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ANDCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64NE, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (CMPconst [0] z:(OR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (ORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64OR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64ORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64NE, v0)
+ return true
+ }
+ break
+ }
+ // match: (NE (CMPconst [0] z:(XOR x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (XORCC x y) yes no)
+ for b.Controls[0].Op == OpPPC64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ z := v_0.Args[0]
+ if z.Op != OpPPC64XOR {
+ break
+ }
+ _ = z.Args[1]
+ z_0 := z.Args[0]
+ z_1 := z.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 {
+ x := z_0
+ y := z_1
+ if !(z.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpPPC64XORCC, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockPPC64NE, v0)
+ return true
+ }
+ break
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go
new file mode 100644
index 0000000..fb507b6
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go
@@ -0,0 +1,6604 @@
+// Code generated from gen/RISCV64.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "math"
+import "cmd/compile/internal/types"
+
+func rewriteValueRISCV64(v *Value) bool {
+ switch v.Op {
+ case OpAdd16:
+ v.Op = OpRISCV64ADD
+ return true
+ case OpAdd32:
+ v.Op = OpRISCV64ADD
+ return true
+ case OpAdd32F:
+ v.Op = OpRISCV64FADDS
+ return true
+ case OpAdd64:
+ v.Op = OpRISCV64ADD
+ return true
+ case OpAdd64F:
+ v.Op = OpRISCV64FADDD
+ return true
+ case OpAdd8:
+ v.Op = OpRISCV64ADD
+ return true
+ case OpAddPtr:
+ v.Op = OpRISCV64ADD
+ return true
+ case OpAddr:
+ return rewriteValueRISCV64_OpAddr(v)
+ case OpAnd16:
+ v.Op = OpRISCV64AND
+ return true
+ case OpAnd32:
+ v.Op = OpRISCV64AND
+ return true
+ case OpAnd64:
+ v.Op = OpRISCV64AND
+ return true
+ case OpAnd8:
+ v.Op = OpRISCV64AND
+ return true
+ case OpAndB:
+ v.Op = OpRISCV64AND
+ return true
+ case OpAtomicAdd32:
+ v.Op = OpRISCV64LoweredAtomicAdd32
+ return true
+ case OpAtomicAdd64:
+ v.Op = OpRISCV64LoweredAtomicAdd64
+ return true
+ case OpAtomicCompareAndSwap32:
+ v.Op = OpRISCV64LoweredAtomicCas32
+ return true
+ case OpAtomicCompareAndSwap64:
+ v.Op = OpRISCV64LoweredAtomicCas64
+ return true
+ case OpAtomicExchange32:
+ v.Op = OpRISCV64LoweredAtomicExchange32
+ return true
+ case OpAtomicExchange64:
+ v.Op = OpRISCV64LoweredAtomicExchange64
+ return true
+ case OpAtomicLoad32:
+ v.Op = OpRISCV64LoweredAtomicLoad32
+ return true
+ case OpAtomicLoad64:
+ v.Op = OpRISCV64LoweredAtomicLoad64
+ return true
+ case OpAtomicLoad8:
+ v.Op = OpRISCV64LoweredAtomicLoad8
+ return true
+ case OpAtomicLoadPtr:
+ v.Op = OpRISCV64LoweredAtomicLoad64
+ return true
+ case OpAtomicStore32:
+ v.Op = OpRISCV64LoweredAtomicStore32
+ return true
+ case OpAtomicStore64:
+ v.Op = OpRISCV64LoweredAtomicStore64
+ return true
+ case OpAtomicStore8:
+ v.Op = OpRISCV64LoweredAtomicStore8
+ return true
+ case OpAtomicStorePtrNoWB:
+ v.Op = OpRISCV64LoweredAtomicStore64
+ return true
+ case OpAvg64u:
+ return rewriteValueRISCV64_OpAvg64u(v)
+ case OpClosureCall:
+ v.Op = OpRISCV64CALLclosure
+ return true
+ case OpCom16:
+ v.Op = OpRISCV64NOT
+ return true
+ case OpCom32:
+ v.Op = OpRISCV64NOT
+ return true
+ case OpCom64:
+ v.Op = OpRISCV64NOT
+ return true
+ case OpCom8:
+ v.Op = OpRISCV64NOT
+ return true
+ case OpConst16:
+ v.Op = OpRISCV64MOVHconst
+ return true
+ case OpConst32:
+ v.Op = OpRISCV64MOVWconst
+ return true
+ case OpConst32F:
+ return rewriteValueRISCV64_OpConst32F(v)
+ case OpConst64:
+ v.Op = OpRISCV64MOVDconst
+ return true
+ case OpConst64F:
+ return rewriteValueRISCV64_OpConst64F(v)
+ case OpConst8:
+ v.Op = OpRISCV64MOVBconst
+ return true
+ case OpConstBool:
+ return rewriteValueRISCV64_OpConstBool(v)
+ case OpConstNil:
+ return rewriteValueRISCV64_OpConstNil(v)
+ case OpConvert:
+ v.Op = OpRISCV64MOVconvert
+ return true
+ case OpCvt32Fto32:
+ v.Op = OpRISCV64FCVTWS
+ return true
+ case OpCvt32Fto64:
+ v.Op = OpRISCV64FCVTLS
+ return true
+ case OpCvt32Fto64F:
+ v.Op = OpRISCV64FCVTDS
+ return true
+ case OpCvt32to32F:
+ v.Op = OpRISCV64FCVTSW
+ return true
+ case OpCvt32to64F:
+ v.Op = OpRISCV64FCVTDW
+ return true
+ case OpCvt64Fto32:
+ v.Op = OpRISCV64FCVTWD
+ return true
+ case OpCvt64Fto32F:
+ v.Op = OpRISCV64FCVTSD
+ return true
+ case OpCvt64Fto64:
+ v.Op = OpRISCV64FCVTLD
+ return true
+ case OpCvt64to32F:
+ v.Op = OpRISCV64FCVTSL
+ return true
+ case OpCvt64to64F:
+ v.Op = OpRISCV64FCVTDL
+ return true
+ case OpCvtBoolToUint8:
+ v.Op = OpCopy
+ return true
+ case OpDiv16:
+ return rewriteValueRISCV64_OpDiv16(v)
+ case OpDiv16u:
+ return rewriteValueRISCV64_OpDiv16u(v)
+ case OpDiv32:
+ return rewriteValueRISCV64_OpDiv32(v)
+ case OpDiv32F:
+ v.Op = OpRISCV64FDIVS
+ return true
+ case OpDiv32u:
+ v.Op = OpRISCV64DIVUW
+ return true
+ case OpDiv64:
+ return rewriteValueRISCV64_OpDiv64(v)
+ case OpDiv64F:
+ v.Op = OpRISCV64FDIVD
+ return true
+ case OpDiv64u:
+ v.Op = OpRISCV64DIVU
+ return true
+ case OpDiv8:
+ return rewriteValueRISCV64_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValueRISCV64_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValueRISCV64_OpEq16(v)
+ case OpEq32:
+ return rewriteValueRISCV64_OpEq32(v)
+ case OpEq32F:
+ v.Op = OpRISCV64FEQS
+ return true
+ case OpEq64:
+ return rewriteValueRISCV64_OpEq64(v)
+ case OpEq64F:
+ v.Op = OpRISCV64FEQD
+ return true
+ case OpEq8:
+ return rewriteValueRISCV64_OpEq8(v)
+ case OpEqB:
+ return rewriteValueRISCV64_OpEqB(v)
+ case OpEqPtr:
+ return rewriteValueRISCV64_OpEqPtr(v)
+ case OpGetCallerPC:
+ v.Op = OpRISCV64LoweredGetCallerPC
+ return true
+ case OpGetCallerSP:
+ v.Op = OpRISCV64LoweredGetCallerSP
+ return true
+ case OpGetClosurePtr:
+ v.Op = OpRISCV64LoweredGetClosurePtr
+ return true
+ case OpHmul32:
+ return rewriteValueRISCV64_OpHmul32(v)
+ case OpHmul32u:
+ return rewriteValueRISCV64_OpHmul32u(v)
+ case OpHmul64:
+ v.Op = OpRISCV64MULH
+ return true
+ case OpHmul64u:
+ v.Op = OpRISCV64MULHU
+ return true
+ case OpInterCall:
+ v.Op = OpRISCV64CALLinter
+ return true
+ case OpIsInBounds:
+ v.Op = OpLess64U
+ return true
+ case OpIsNonNil:
+ return rewriteValueRISCV64_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ v.Op = OpLeq64U
+ return true
+ case OpLeq16:
+ return rewriteValueRISCV64_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValueRISCV64_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValueRISCV64_OpLeq32(v)
+ case OpLeq32F:
+ v.Op = OpRISCV64FLES
+ return true
+ case OpLeq32U:
+ return rewriteValueRISCV64_OpLeq32U(v)
+ case OpLeq64:
+ return rewriteValueRISCV64_OpLeq64(v)
+ case OpLeq64F:
+ v.Op = OpRISCV64FLED
+ return true
+ case OpLeq64U:
+ return rewriteValueRISCV64_OpLeq64U(v)
+ case OpLeq8:
+ return rewriteValueRISCV64_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValueRISCV64_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValueRISCV64_OpLess16(v)
+ case OpLess16U:
+ return rewriteValueRISCV64_OpLess16U(v)
+ case OpLess32:
+ return rewriteValueRISCV64_OpLess32(v)
+ case OpLess32F:
+ v.Op = OpRISCV64FLTS
+ return true
+ case OpLess32U:
+ return rewriteValueRISCV64_OpLess32U(v)
+ case OpLess64:
+ v.Op = OpRISCV64SLT
+ return true
+ case OpLess64F:
+ v.Op = OpRISCV64FLTD
+ return true
+ case OpLess64U:
+ v.Op = OpRISCV64SLTU
+ return true
+ case OpLess8:
+ return rewriteValueRISCV64_OpLess8(v)
+ case OpLess8U:
+ return rewriteValueRISCV64_OpLess8U(v)
+ case OpLoad:
+ return rewriteValueRISCV64_OpLoad(v)
+ case OpLocalAddr:
+ return rewriteValueRISCV64_OpLocalAddr(v)
+ case OpLsh16x16:
+ return rewriteValueRISCV64_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValueRISCV64_OpLsh16x32(v)
+ case OpLsh16x64:
+ return rewriteValueRISCV64_OpLsh16x64(v)
+ case OpLsh16x8:
+ return rewriteValueRISCV64_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValueRISCV64_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValueRISCV64_OpLsh32x32(v)
+ case OpLsh32x64:
+ return rewriteValueRISCV64_OpLsh32x64(v)
+ case OpLsh32x8:
+ return rewriteValueRISCV64_OpLsh32x8(v)
+ case OpLsh64x16:
+ return rewriteValueRISCV64_OpLsh64x16(v)
+ case OpLsh64x32:
+ return rewriteValueRISCV64_OpLsh64x32(v)
+ case OpLsh64x64:
+ return rewriteValueRISCV64_OpLsh64x64(v)
+ case OpLsh64x8:
+ return rewriteValueRISCV64_OpLsh64x8(v)
+ case OpLsh8x16:
+ return rewriteValueRISCV64_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValueRISCV64_OpLsh8x32(v)
+ case OpLsh8x64:
+ return rewriteValueRISCV64_OpLsh8x64(v)
+ case OpLsh8x8:
+ return rewriteValueRISCV64_OpLsh8x8(v)
+ case OpMod16:
+ return rewriteValueRISCV64_OpMod16(v)
+ case OpMod16u:
+ return rewriteValueRISCV64_OpMod16u(v)
+ case OpMod32:
+ return rewriteValueRISCV64_OpMod32(v)
+ case OpMod32u:
+ v.Op = OpRISCV64REMUW
+ return true
+ case OpMod64:
+ return rewriteValueRISCV64_OpMod64(v)
+ case OpMod64u:
+ v.Op = OpRISCV64REMU
+ return true
+ case OpMod8:
+ return rewriteValueRISCV64_OpMod8(v)
+ case OpMod8u:
+ return rewriteValueRISCV64_OpMod8u(v)
+ case OpMove:
+ return rewriteValueRISCV64_OpMove(v)
+ case OpMul16:
+ return rewriteValueRISCV64_OpMul16(v)
+ case OpMul32:
+ v.Op = OpRISCV64MULW
+ return true
+ case OpMul32F:
+ v.Op = OpRISCV64FMULS
+ return true
+ case OpMul64:
+ v.Op = OpRISCV64MUL
+ return true
+ case OpMul64F:
+ v.Op = OpRISCV64FMULD
+ return true
+ case OpMul8:
+ return rewriteValueRISCV64_OpMul8(v)
+ case OpNeg16:
+ v.Op = OpRISCV64NEG
+ return true
+ case OpNeg32:
+ v.Op = OpRISCV64NEG
+ return true
+ case OpNeg32F:
+ v.Op = OpRISCV64FNEGS
+ return true
+ case OpNeg64:
+ v.Op = OpRISCV64NEG
+ return true
+ case OpNeg64F:
+ v.Op = OpRISCV64FNEGD
+ return true
+ case OpNeg8:
+ v.Op = OpRISCV64NEG
+ return true
+ case OpNeq16:
+ return rewriteValueRISCV64_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValueRISCV64_OpNeq32(v)
+ case OpNeq32F:
+ v.Op = OpRISCV64FNES
+ return true
+ case OpNeq64:
+ return rewriteValueRISCV64_OpNeq64(v)
+ case OpNeq64F:
+ v.Op = OpRISCV64FNED
+ return true
+ case OpNeq8:
+ return rewriteValueRISCV64_OpNeq8(v)
+ case OpNeqB:
+ v.Op = OpRISCV64XOR
+ return true
+ case OpNeqPtr:
+ return rewriteValueRISCV64_OpNeqPtr(v)
+ case OpNilCheck:
+ v.Op = OpRISCV64LoweredNilCheck
+ return true
+ case OpNot:
+ v.Op = OpRISCV64SEQZ
+ return true
+ case OpOffPtr:
+ return rewriteValueRISCV64_OpOffPtr(v)
+ case OpOr16:
+ v.Op = OpRISCV64OR
+ return true
+ case OpOr32:
+ v.Op = OpRISCV64OR
+ return true
+ case OpOr64:
+ v.Op = OpRISCV64OR
+ return true
+ case OpOr8:
+ v.Op = OpRISCV64OR
+ return true
+ case OpOrB:
+ v.Op = OpRISCV64OR
+ return true
+ case OpPanicBounds:
+ return rewriteValueRISCV64_OpPanicBounds(v)
+ case OpRISCV64ADD:
+ return rewriteValueRISCV64_OpRISCV64ADD(v)
+ case OpRISCV64ADDI:
+ return rewriteValueRISCV64_OpRISCV64ADDI(v)
+ case OpRISCV64AND:
+ return rewriteValueRISCV64_OpRISCV64AND(v)
+ case OpRISCV64MOVBUload:
+ return rewriteValueRISCV64_OpRISCV64MOVBUload(v)
+ case OpRISCV64MOVBUreg:
+ return rewriteValueRISCV64_OpRISCV64MOVBUreg(v)
+ case OpRISCV64MOVBload:
+ return rewriteValueRISCV64_OpRISCV64MOVBload(v)
+ case OpRISCV64MOVBreg:
+ return rewriteValueRISCV64_OpRISCV64MOVBreg(v)
+ case OpRISCV64MOVBstore:
+ return rewriteValueRISCV64_OpRISCV64MOVBstore(v)
+ case OpRISCV64MOVBstorezero:
+ return rewriteValueRISCV64_OpRISCV64MOVBstorezero(v)
+ case OpRISCV64MOVDconst:
+ return rewriteValueRISCV64_OpRISCV64MOVDconst(v)
+ case OpRISCV64MOVDload:
+ return rewriteValueRISCV64_OpRISCV64MOVDload(v)
+ case OpRISCV64MOVDreg:
+ return rewriteValueRISCV64_OpRISCV64MOVDreg(v)
+ case OpRISCV64MOVDstore:
+ return rewriteValueRISCV64_OpRISCV64MOVDstore(v)
+ case OpRISCV64MOVDstorezero:
+ return rewriteValueRISCV64_OpRISCV64MOVDstorezero(v)
+ case OpRISCV64MOVHUload:
+ return rewriteValueRISCV64_OpRISCV64MOVHUload(v)
+ case OpRISCV64MOVHUreg:
+ return rewriteValueRISCV64_OpRISCV64MOVHUreg(v)
+ case OpRISCV64MOVHload:
+ return rewriteValueRISCV64_OpRISCV64MOVHload(v)
+ case OpRISCV64MOVHreg:
+ return rewriteValueRISCV64_OpRISCV64MOVHreg(v)
+ case OpRISCV64MOVHstore:
+ return rewriteValueRISCV64_OpRISCV64MOVHstore(v)
+ case OpRISCV64MOVHstorezero:
+ return rewriteValueRISCV64_OpRISCV64MOVHstorezero(v)
+ case OpRISCV64MOVWUload:
+ return rewriteValueRISCV64_OpRISCV64MOVWUload(v)
+ case OpRISCV64MOVWUreg:
+ return rewriteValueRISCV64_OpRISCV64MOVWUreg(v)
+ case OpRISCV64MOVWload:
+ return rewriteValueRISCV64_OpRISCV64MOVWload(v)
+ case OpRISCV64MOVWreg:
+ return rewriteValueRISCV64_OpRISCV64MOVWreg(v)
+ case OpRISCV64MOVWstore:
+ return rewriteValueRISCV64_OpRISCV64MOVWstore(v)
+ case OpRISCV64MOVWstorezero:
+ return rewriteValueRISCV64_OpRISCV64MOVWstorezero(v)
+ case OpRISCV64OR:
+ return rewriteValueRISCV64_OpRISCV64OR(v)
+ case OpRISCV64SLL:
+ return rewriteValueRISCV64_OpRISCV64SLL(v)
+ case OpRISCV64SRA:
+ return rewriteValueRISCV64_OpRISCV64SRA(v)
+ case OpRISCV64SRL:
+ return rewriteValueRISCV64_OpRISCV64SRL(v)
+ case OpRISCV64SUB:
+ return rewriteValueRISCV64_OpRISCV64SUB(v)
+ case OpRISCV64SUBW:
+ return rewriteValueRISCV64_OpRISCV64SUBW(v)
+ case OpRISCV64XOR:
+ return rewriteValueRISCV64_OpRISCV64XOR(v)
+ case OpRotateLeft16:
+ return rewriteValueRISCV64_OpRotateLeft16(v)
+ case OpRotateLeft32:
+ return rewriteValueRISCV64_OpRotateLeft32(v)
+ case OpRotateLeft64:
+ return rewriteValueRISCV64_OpRotateLeft64(v)
+ case OpRotateLeft8:
+ return rewriteValueRISCV64_OpRotateLeft8(v)
+ case OpRound32F:
+ v.Op = OpCopy
+ return true
+ case OpRound64F:
+ v.Op = OpCopy
+ return true
+ case OpRsh16Ux16:
+ return rewriteValueRISCV64_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValueRISCV64_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValueRISCV64_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValueRISCV64_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValueRISCV64_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValueRISCV64_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValueRISCV64_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValueRISCV64_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValueRISCV64_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValueRISCV64_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValueRISCV64_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValueRISCV64_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValueRISCV64_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValueRISCV64_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValueRISCV64_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValueRISCV64_OpRsh32x8(v)
+ case OpRsh64Ux16:
+ return rewriteValueRISCV64_OpRsh64Ux16(v)
+ case OpRsh64Ux32:
+ return rewriteValueRISCV64_OpRsh64Ux32(v)
+ case OpRsh64Ux64:
+ return rewriteValueRISCV64_OpRsh64Ux64(v)
+ case OpRsh64Ux8:
+ return rewriteValueRISCV64_OpRsh64Ux8(v)
+ case OpRsh64x16:
+ return rewriteValueRISCV64_OpRsh64x16(v)
+ case OpRsh64x32:
+ return rewriteValueRISCV64_OpRsh64x32(v)
+ case OpRsh64x64:
+ return rewriteValueRISCV64_OpRsh64x64(v)
+ case OpRsh64x8:
+ return rewriteValueRISCV64_OpRsh64x8(v)
+ case OpRsh8Ux16:
+ return rewriteValueRISCV64_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValueRISCV64_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValueRISCV64_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValueRISCV64_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValueRISCV64_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValueRISCV64_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValueRISCV64_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValueRISCV64_OpRsh8x8(v)
+ case OpSignExt16to32:
+ v.Op = OpRISCV64MOVHreg
+ return true
+ case OpSignExt16to64:
+ v.Op = OpRISCV64MOVHreg
+ return true
+ case OpSignExt32to64:
+ v.Op = OpRISCV64MOVWreg
+ return true
+ case OpSignExt8to16:
+ v.Op = OpRISCV64MOVBreg
+ return true
+ case OpSignExt8to32:
+ v.Op = OpRISCV64MOVBreg
+ return true
+ case OpSignExt8to64:
+ v.Op = OpRISCV64MOVBreg
+ return true
+ case OpSlicemask:
+ return rewriteValueRISCV64_OpSlicemask(v)
+ case OpSqrt:
+ v.Op = OpRISCV64FSQRTD
+ return true
+ case OpStaticCall:
+ v.Op = OpRISCV64CALLstatic
+ return true
+ case OpStore:
+ return rewriteValueRISCV64_OpStore(v)
+ case OpSub16:
+ v.Op = OpRISCV64SUB
+ return true
+ case OpSub32:
+ v.Op = OpRISCV64SUB
+ return true
+ case OpSub32F:
+ v.Op = OpRISCV64FSUBS
+ return true
+ case OpSub64:
+ v.Op = OpRISCV64SUB
+ return true
+ case OpSub64F:
+ v.Op = OpRISCV64FSUBD
+ return true
+ case OpSub8:
+ v.Op = OpRISCV64SUB
+ return true
+ case OpSubPtr:
+ v.Op = OpRISCV64SUB
+ return true
+ case OpTrunc16to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to32:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to8:
+ v.Op = OpCopy
+ return true
+ case OpWB:
+ v.Op = OpRISCV64LoweredWB
+ return true
+ case OpXor16:
+ v.Op = OpRISCV64XOR
+ return true
+ case OpXor32:
+ v.Op = OpRISCV64XOR
+ return true
+ case OpXor64:
+ v.Op = OpRISCV64XOR
+ return true
+ case OpXor8:
+ v.Op = OpRISCV64XOR
+ return true
+ case OpZero:
+ return rewriteValueRISCV64_OpZero(v)
+ case OpZeroExt16to32:
+ v.Op = OpRISCV64MOVHUreg
+ return true
+ case OpZeroExt16to64:
+ v.Op = OpRISCV64MOVHUreg
+ return true
+ case OpZeroExt32to64:
+ v.Op = OpRISCV64MOVWUreg
+ return true
+ case OpZeroExt8to16:
+ v.Op = OpRISCV64MOVBUreg
+ return true
+ case OpZeroExt8to32:
+ v.Op = OpRISCV64MOVBUreg
+ return true
+ case OpZeroExt8to64:
+ v.Op = OpRISCV64MOVBUreg
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Addr {sym} base)
+ // result: (MOVaddr {sym} [0] base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpRISCV64MOVaddr)
+ v.AuxInt = int32ToAuxInt(0)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpAvg64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Avg64u <t> x y)
+ // result: (ADD (ADD <t> (SRLI <t> [1] x) (SRLI <t> [1] y)) (ANDI <t> [1] (AND <t> x y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64ADD)
+ v0 := b.NewValue0(v.Pos, OpRISCV64ADD, t)
+ v1 := b.NewValue0(v.Pos, OpRISCV64SRLI, t)
+ v1.AuxInt = int64ToAuxInt(1)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SRLI, t)
+ v2.AuxInt = int64ToAuxInt(1)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpRISCV64ANDI, t)
+ v3.AuxInt = int64ToAuxInt(1)
+ v4 := b.NewValue0(v.Pos, OpRISCV64AND, t)
+ v4.AddArg2(x, y)
+ v3.AddArg(v4)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpConst32F(v *Value) bool {
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Const32F [val])
+ // result: (FMVSX (MOVWconst [int32(math.Float32bits(val))]))
+ for {
+ val := auxIntToFloat32(v.AuxInt)
+ v.reset(OpRISCV64FMVSX)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(math.Float32bits(val)))
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpConst64F(v *Value) bool {
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Const64F [val])
+ // result: (FMVDX (MOVDconst [int64(math.Float64bits(val))]))
+ for {
+ val := auxIntToFloat64(v.AuxInt)
+ v.reset(OpRISCV64FMVDX)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(int64(math.Float64bits(val)))
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpConstBool(v *Value) bool {
+ // match: (ConstBool [val])
+ // result: (MOVBconst [int8(b2i(val))])
+ for {
+ val := auxIntToBool(v.AuxInt)
+ v.reset(OpRISCV64MOVBconst)
+ v.AuxInt = int8ToAuxInt(int8(b2i(val)))
+ return true
+ }
+}
+func rewriteValueRISCV64_OpConstNil(v *Value) bool {
+ // match: (ConstNil)
+ // result: (MOVDconst [0])
+ for {
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpDiv16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16 x y [false])
+ // result: (DIVW (SignExt16to32 x) (SignExt16to32 y))
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64DIVW)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpDiv16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16u x y)
+ // result: (DIVUW (ZeroExt16to32 x) (ZeroExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64DIVUW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpDiv32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Div32 x y [false])
+ // result: (DIVW x y)
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64DIVW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpDiv64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Div64 x y [false])
+ // result: (DIV x y)
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64DIV)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 x y)
+ // result: (DIVW (SignExt8to32 x) (SignExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64DIVW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u x y)
+ // result: (DIVUW (ZeroExt8to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64DIVUW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq16 x y)
+ // result: (SEQZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SEQZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq32 x y)
+ // result: (SEQZ (SUBW <x.Type> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SEQZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUBW, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpEq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Eq64 x y)
+ // result: (SEQZ (SUB <x.Type> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SEQZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq8 x y)
+ // result: (SEQZ (SUB <x.Type> (ZeroExt8to64 x) (ZeroExt8to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SEQZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpEqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqB x y)
+ // result: (SEQZ (XOR <typ.Bool> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SEQZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64XOR, typ.Bool)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpEqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (EqPtr x y)
+ // result: (SEQZ (SUB <x.Type> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SEQZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpHmul32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul32 x y)
+ // result: (SRAI [32] (MUL (SignExt32to64 x) (SignExt32to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRAI)
+ v.AuxInt = int64ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MUL, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpHmul32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul32u x y)
+ // result: (SRLI [32] (MUL (ZeroExt32to64 x) (ZeroExt32to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRLI)
+ v.AuxInt = int64ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MUL, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (IsNonNil p)
+ // result: (NeqPtr (MOVDconst [0]) p)
+ for {
+ p := v_0
+ v.reset(OpNeqPtr)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, p)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16 x y)
+ // result: (Not (Less16 y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpLess16, typ.Bool)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16U x y)
+ // result: (Not (Less16U y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpLess16U, typ.Bool)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32 x y)
+ // result: (Not (Less32 y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpLess32, typ.Bool)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32U x y)
+ // result: (Not (Less32U y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpLess32U, typ.Bool)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq64 x y)
+ // result: (Not (Less64 y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpLess64, typ.Bool)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLeq64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq64U x y)
+ // result: (Not (Less64U y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpLess64U, typ.Bool)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8 x y)
+ // result: (Not (Less8 y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpLess8, typ.Bool)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8U x y)
+ // result: (Not (Less8U y x))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpLess8U, typ.Bool)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16 x y)
+ // result: (SLT (SignExt16to64 x) (SignExt16to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SLT)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16U x y)
+ // result: (SLTU (ZeroExt16to64 x) (ZeroExt16to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SLTU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less32 x y)
+ // result: (SLT (SignExt32to64 x) (SignExt32to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SLT)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less32U x y)
+ // result: (SLTU (ZeroExt32to64 x) (ZeroExt32to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SLTU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8 x y)
+ // result: (SLT (SignExt8to64 x) (SignExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SLT)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8U x y)
+ // result: (SLTU (ZeroExt8to64 x) (ZeroExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SLTU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Load <t> ptr mem)
+ // cond: t.IsBoolean()
+ // result: (MOVBUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsBoolean()) {
+ break
+ }
+ v.reset(OpRISCV64MOVBUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: ( is8BitInt(t) && isSigned(t))
+ // result: (MOVBload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpRISCV64MOVBload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: ( is8BitInt(t) && !isSigned(t))
+ // result: (MOVBUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpRISCV64MOVBUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is16BitInt(t) && isSigned(t))
+ // result: (MOVHload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpRISCV64MOVHload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is16BitInt(t) && !isSigned(t))
+ // result: (MOVHUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpRISCV64MOVHUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is32BitInt(t) && isSigned(t))
+ // result: (MOVWload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpRISCV64MOVWload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is32BitInt(t) && !isSigned(t))
+ // result: (MOVWUload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpRISCV64MOVWUload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (MOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpRISCV64MOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitFloat(t)
+ // result: (FMOVWload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(OpRISCV64FMOVWload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitFloat(t)
+ // result: (FMOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(OpRISCV64FMOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpLocalAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LocalAddr {sym} base _)
+ // result: (MOVaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpRISCV64MOVaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x16 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg16, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x32 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg16, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x64 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg16, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x8 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg16, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x16 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg32, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x32 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg32, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x64 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg32, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x8 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg32, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x16 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg64, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x32 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg64, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh64x64 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg64, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x8 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg64, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x16 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg8, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x32 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg8, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x64 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg8, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x8 <t> x y)
+ // result: (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg8, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpMod16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16 x y [false])
+ // result: (REMW (SignExt16to32 x) (SignExt16to32 y))
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64REMW)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpMod16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16u x y)
+ // result: (REMUW (ZeroExt16to32 x) (ZeroExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64REMUW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpMod32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Mod32 x y [false])
+ // result: (REMW x y)
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64REMW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpMod64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Mod64 x y [false])
+ // result: (REM x y)
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64REM)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8 x y)
+ // result: (REMW (SignExt8to32 x) (SignExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64REMW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8u x y)
+ // result: (REMUW (ZeroExt8to32 x) (ZeroExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64REMUW)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Move [0] _ _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Move [1] dst src mem)
+ // result: (MOVBstore dst (MOVBload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpRISCV64MOVBstore)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore dst (MOVHload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] dst src mem)
+ // result: (MOVBstore [1] dst (MOVBload [1] src mem) (MOVBstore dst (MOVBload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8)
+ v0.AuxInt = int32ToAuxInt(1)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [4] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore dst (MOVWload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstore)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [4] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [4] dst src mem)
+ // result: (MOVBstore [3] dst (MOVBload [3] src mem) (MOVBstore [2] dst (MOVBload [2] src mem) (MOVBstore [1] dst (MOVBload [1] src mem) (MOVBstore dst (MOVBload src mem) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8)
+ v0.AuxInt = int32ToAuxInt(3)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8)
+ v2.AuxInt = int32ToAuxInt(2)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(1)
+ v4 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8)
+ v4.AuxInt = int32ToAuxInt(1)
+ v4.AddArg2(src, mem)
+ v5 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v6 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8)
+ v6.AddArg2(src, mem)
+ v5.AddArg3(dst, v6, mem)
+ v3.AddArg3(dst, v4, v5)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [8] {t} dst src mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVDstore dst (MOVDload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [8] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [4] dst (MOVWload [4] src mem) (MOVWstore dst (MOVWload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [8] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [6] dst (MOVHload [6] src mem) (MOVHstore [4] dst (MOVHload [4] src mem) (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16)
+ v0.AuxInt = int32ToAuxInt(6)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16)
+ v2.AuxInt = int32ToAuxInt(4)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(2)
+ v4 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16)
+ v4.AuxInt = int32ToAuxInt(2)
+ v4.AddArg2(src, mem)
+ v5 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v6 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16)
+ v6.AddArg2(src, mem)
+ v5.AddArg3(dst, v6, mem)
+ v3.AddArg3(dst, v4, v5)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [3] dst src mem)
+ // result: (MOVBstore [2] dst (MOVBload [2] src mem) (MOVBstore [1] dst (MOVBload [1] src mem) (MOVBstore dst (MOVBload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8)
+ v2.AuxInt = int32ToAuxInt(1)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [6] {t} dst src mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [4] dst (MOVHload [4] src mem) (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16)
+ v2.AuxInt = int32ToAuxInt(2)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [12] {t} dst src mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [8] dst (MOVWload [8] src mem) (MOVWstore [4] dst (MOVWload [4] src mem) (MOVWstore dst (MOVWload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32)
+ v2.AuxInt = int32ToAuxInt(4)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [16] {t} dst src mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVDstore [8] dst (MOVDload [8] src mem) (MOVDstore dst (MOVDload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [24] {t} dst src mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVDstore [16] dst (MOVDload [16] src mem) (MOVDstore [8] dst (MOVDload [8] src mem) (MOVDstore dst (MOVDload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v.AuxInt = int32ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64)
+ v0.AuxInt = int32ToAuxInt(16)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64)
+ v2.AuxInt = int32ToAuxInt(8)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [32] {t} dst src mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVDstore [24] dst (MOVDload [24] src mem) (MOVDstore [16] dst (MOVDload [16] src mem) (MOVDstore [8] dst (MOVDload [8] src mem) (MOVDstore dst (MOVDload src mem) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 32 {
+ break
+ }
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v.AuxInt = int32ToAuxInt(24)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64)
+ v0.AuxInt = int32ToAuxInt(24)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(16)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64)
+ v2.AuxInt = int32ToAuxInt(16)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v3.AuxInt = int32ToAuxInt(8)
+ v4 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64)
+ v4.AuxInt = int32ToAuxInt(8)
+ v4.AddArg2(src, mem)
+ v5 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v6 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64)
+ v6.AddArg2(src, mem)
+ v5.AddArg3(dst, v6, mem)
+ v3.AddArg3(dst, v4, v5)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] {t} dst src mem)
+ // cond: s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
+ // result: (DUFFCOPY [16 * (128 - s/8)] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpRISCV64DUFFCOPY)
+ v.AuxInt = int64ToAuxInt(16 * (128 - s/8))
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (Move [s] {t} dst src mem)
+ // cond: (s <= 16 || logLargeCopy(v, s))
+ // result: (LoweredMove [t.Alignment()] dst src (ADDI <src.Type> [s-moveSize(t.Alignment(), config)] src) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s <= 16 || logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpRISCV64LoweredMove)
+ v.AuxInt = int64ToAuxInt(t.Alignment())
+ v0 := b.NewValue0(v.Pos, OpRISCV64ADDI, src.Type)
+ v0.AuxInt = int64ToAuxInt(s - moveSize(t.Alignment(), config))
+ v0.AddArg(src)
+ v.AddArg4(dst, src, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpMul16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul16 x y)
+ // result: (MULW (SignExt16to32 x) (SignExt16to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64MULW)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpMul8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul8 x y)
+ // result: (MULW (SignExt8to32 x) (SignExt8to32 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64MULW)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq16 x y)
+ // result: (SNEZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SNEZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq32 x y)
+ // result: (SNEZ (SUBW <x.Type> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SNEZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUBW, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpNeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neq64 x y)
+ // result: (SNEZ (SUB <x.Type> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SNEZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq8 x y)
+ // result: (SNEZ (SUB <x.Type> (ZeroExt8to64 x) (ZeroExt8to64 y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SNEZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpNeqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (NeqPtr x y)
+ // result: (SNEZ (SUB <x.Type> x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SNEZ)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpOffPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (OffPtr [off] ptr:(SP))
+ // cond: is32Bit(off)
+ // result: (MOVaddr [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ if ptr.Op != OpSP || !(is32Bit(off)) {
+ break
+ }
+ v.reset(OpRISCV64MOVaddr)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (OffPtr [off] ptr)
+ // cond: is32Bit(off)
+ // result: (ADDI [off] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ if !(is32Bit(off)) {
+ break
+ }
+ v.reset(OpRISCV64ADDI)
+ v.AuxInt = int64ToAuxInt(off)
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (OffPtr [off] ptr)
+ // result: (ADD (MOVDconst [off]) ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ v.reset(OpRISCV64ADD)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(off)
+ v.AddArg2(v0, ptr)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpPanicBounds(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicBoundsA [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(OpRISCV64LoweredPanicBoundsA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicBoundsB [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(OpRISCV64LoweredPanicBoundsB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicBoundsC [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(OpRISCV64LoweredPanicBoundsC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64ADD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADD (MOVBconst [val]) x)
+ // result: (ADDI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVBconst {
+ continue
+ }
+ val := auxIntToInt8(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64ADDI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADD (MOVHconst [val]) x)
+ // result: (ADDI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVHconst {
+ continue
+ }
+ val := auxIntToInt16(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64ADDI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADD (MOVWconst [val]) x)
+ // result: (ADDI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVWconst {
+ continue
+ }
+ val := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64ADDI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADD (MOVDconst [val]) x)
+ // cond: is32Bit(val)
+ // result: (ADDI [val] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVDconst {
+ continue
+ }
+ val := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(val)) {
+ continue
+ }
+ v.reset(OpRISCV64ADDI)
+ v.AuxInt = int64ToAuxInt(val)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64ADDI(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDI [c] (MOVaddr [d] {s} x))
+ // cond: is32Bit(c+int64(d))
+ // result: (MOVaddr [int32(c)+d] {s} x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ if !(is32Bit(c + int64(d))) {
+ break
+ }
+ v.reset(OpRISCV64MOVaddr)
+ v.AuxInt = int32ToAuxInt(int32(c) + d)
+ v.Aux = symToAux(s)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDI [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64AND(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AND (MOVBconst [val]) x)
+ // result: (ANDI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVBconst {
+ continue
+ }
+ val := auxIntToInt8(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64ANDI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVHconst [val]) x)
+ // result: (ANDI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVHconst {
+ continue
+ }
+ val := auxIntToInt16(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64ANDI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVWconst [val]) x)
+ // result: (ANDI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVWconst {
+ continue
+ }
+ val := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64ANDI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVDconst [val]) x)
+ // cond: is32Bit(val)
+ // result: (ANDI [val] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVDconst {
+ continue
+ }
+ val := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(val)) {
+ continue
+ }
+ v.reset(OpRISCV64ANDI)
+ v.AuxInt = int64ToAuxInt(val)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVBUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVBUload [off1] {sym} (ADDI [off2] base) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVBUload [off1+int32(off2)] {sym} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVBUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVBUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVBUreg (MOVBconst [c]))
+ // result: (MOVDconst [int64(uint8(c))])
+ for {
+ if v_0.Op != OpRISCV64MOVBconst {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ return true
+ }
+ // match: (MOVBUreg x:(MOVBUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBUload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg x:(MOVBUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBUreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBUreg <t> x:(MOVBload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBUload <t> [off] {sym} ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpRISCV64MOVBload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpRISCV64MOVBUload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVBload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym} (ADDI [off2] base) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVBload [off1+int32(off2)] {sym} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVBreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVBreg (MOVBconst [c]))
+ // result: (MOVDconst [int64(c)])
+ for {
+ if v_0.Op != OpRISCV64MOVBconst {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ // match: (MOVBreg x:(MOVBload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg x:(MOVBreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg <t> x:(MOVBUload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBload <t> [off] {sym} ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpRISCV64MOVBUload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpRISCV64MOVBload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVBstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym} (ADDI [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVBstore [off1+int32(off2)] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBconst [0]) mem)
+ // result: (MOVBstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVBconst || auxIntToInt8(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpRISCV64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVBreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVBUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVHUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVHUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVWUreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVWUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVBstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpRISCV64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstorezero [off1] {sym} (ADDI [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVBstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVBstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVDconst(v *Value) bool {
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVDconst <t> [c])
+ // cond: !is32Bit(c) && int32(c) < 0
+ // result: (ADD (SLLI <t> [32] (MOVDconst [c>>32+1])) (MOVDconst [int64(int32(c))]))
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if !(!is32Bit(c) && int32(c) < 0) {
+ break
+ }
+ v.reset(OpRISCV64ADD)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLLI, t)
+ v0.AuxInt = int64ToAuxInt(32)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c>>32 + 1)
+ v0.AddArg(v1)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(int32(c)))
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (MOVDconst <t> [c])
+ // cond: !is32Bit(c) && int32(c) >= 0
+ // result: (ADD (SLLI <t> [32] (MOVDconst [c>>32+0])) (MOVDconst [int64(int32(c))]))
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if !(!is32Bit(c) && int32(c) >= 0) {
+ break
+ }
+ v.reset(OpRISCV64ADD)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SLLI, t)
+ v0.AuxInt = int64ToAuxInt(32)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c>>32 + 0)
+ v0.AddArg(v1)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(int32(c)))
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVDload [off1] {sym} (ADDI [off2] base) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVDload [off1+int32(off2)] {sym} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVDreg(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (MOVDreg x)
+ // cond: x.Uses == 1
+ // result: (MOVDnop x)
+ for {
+ x := v_0
+ if !(x.Uses == 1) {
+ break
+ }
+ v.reset(OpRISCV64MOVDnop)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off1] {sym} (ADDI [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVDstore [off1+int32(off2)] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // result: (MOVDstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpRISCV64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVDstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDstorezero [off1] {sym} (ADDI [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVDstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVHUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVHUload [off1] {sym} (ADDI [off2] base) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVHUload [off1+int32(off2)] {sym} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVHUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVHUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVHUreg (MOVBconst [c]))
+ // result: (MOVDconst [int64(uint16(c))])
+ for {
+ if v_0.Op != OpRISCV64MOVBconst {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ return true
+ }
+ // match: (MOVHUreg (MOVHconst [c]))
+ // result: (MOVDconst [int64(uint16(c))])
+ for {
+ if v_0.Op != OpRISCV64MOVHconst {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ return true
+ }
+ // match: (MOVHUreg x:(MOVBUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBUload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVHUload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVBUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBUreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg x:(MOVHUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVHUreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHUreg <t> x:(MOVHload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVHUload <t> [off] {sym} ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpRISCV64MOVHload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpRISCV64MOVHUload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVHload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVHload [off1] {sym} (ADDI [off2] base) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVHload [off1+int32(off2)] {sym} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVHreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVHreg (MOVBconst [c]))
+ // result: (MOVDconst [int64(c)])
+ for {
+ if v_0.Op != OpRISCV64MOVBconst {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ // match: (MOVHreg (MOVHconst [c]))
+ // result: (MOVDconst [int64(c)])
+ for {
+ if v_0.Op != OpRISCV64MOVHconst {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ // match: (MOVHreg x:(MOVBload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBUload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVHload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBUreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVHreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg <t> x:(MOVHUload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVHload <t> [off] {sym} ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpRISCV64MOVHUload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpRISCV64MOVHload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVHstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off1] {sym} (ADDI [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVHstore [off1+int32(off2)] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHconst [0]) mem)
+ // result: (MOVHstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVHconst || auxIntToInt16(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpRISCV64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHUreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVHUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVWUreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVWUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVHstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstorezero [off1] {sym} (ADDI [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVHstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVWUload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVWUload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVWUload [off1] {sym} (ADDI [off2] base) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVWUload [off1+int32(off2)] {sym} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVWUload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVWUreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVWUreg (MOVBconst [c]))
+ // result: (MOVDconst [int64(uint32(c))])
+ for {
+ if v_0.Op != OpRISCV64MOVBconst {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ return true
+ }
+ // match: (MOVWUreg (MOVHconst [c]))
+ // result: (MOVDconst [int64(uint32(c))])
+ for {
+ if v_0.Op != OpRISCV64MOVHconst {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ return true
+ }
+ // match: (MOVWUreg (MOVWconst [c]))
+ // result: (MOVDconst [int64(uint32(c))])
+ for {
+ if v_0.Op != OpRISCV64MOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ return true
+ }
+ // match: (MOVWUreg x:(MOVBUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBUload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVHUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVHUload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVWUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVWUload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVBUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBUreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVHUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVHUreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg x:(MOVWUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVWUreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWUreg <t> x:(MOVWload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWUload <t> [off] {sym} ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpRISCV64MOVWload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpRISCV64MOVWUload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVWload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym} (ADDI [off2] base) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVWload [off1+int32(off2)] {sym} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVWreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVWreg (MOVBconst [c]))
+ // result: (MOVDconst [int64(c)])
+ for {
+ if v_0.Op != OpRISCV64MOVBconst {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ // match: (MOVWreg (MOVHconst [c]))
+ // result: (MOVDconst [int64(c)])
+ for {
+ if v_0.Op != OpRISCV64MOVHconst {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ // match: (MOVWreg (MOVWconst [c]))
+ // result: (MOVDconst [int64(c)])
+ for {
+ if v_0.Op != OpRISCV64MOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpRISCV64MOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ // match: (MOVWreg x:(MOVBload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBUload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVHload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHUload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVHUload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWload _ _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVWload {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBUreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVBUreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVHreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWreg _))
+ // result: (MOVDreg x)
+ for {
+ x := v_0
+ if x.Op != OpRISCV64MOVWreg {
+ break
+ }
+ v.reset(OpRISCV64MOVDreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg <t> x:(MOVWUload [off] {sym} ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWload <t> [off] {sym} ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpRISCV64MOVWUload {
+ break
+ }
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpRISCV64MOVWload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(sym)
+ v0.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVWstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym} (ADDI [off2] base) val mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVWstore [off1+int32(off2)] {sym} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWconst [0]) mem)
+ // result: (MOVWstorezero [off] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.reset(OpRISCV64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWUreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpRISCV64MOVWUreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpRISCV64MOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64MOVWstorezero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem)
+ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2))
+ // result: (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64MOVaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstorezero [off1] {sym} (ADDI [off2] ptr) mem)
+ // cond: is32Bit(int64(off1)+off2)
+ // result: (MOVWstorezero [off1+int32(off2)] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpRISCV64ADDI {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1) + off2)) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstorezero)
+ v.AuxInt = int32ToAuxInt(off1 + int32(off2))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64OR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (OR (MOVBconst [val]) x)
+ // result: (ORI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVBconst {
+ continue
+ }
+ val := auxIntToInt8(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64ORI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (OR (MOVHconst [val]) x)
+ // result: (ORI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVHconst {
+ continue
+ }
+ val := auxIntToInt16(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64ORI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (OR (MOVWconst [val]) x)
+ // result: (ORI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVWconst {
+ continue
+ }
+ val := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64ORI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (OR (MOVDconst [val]) x)
+ // cond: is32Bit(val)
+ // result: (ORI [val] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVDconst {
+ continue
+ }
+ val := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(val)) {
+ continue
+ }
+ v.reset(OpRISCV64ORI)
+ v.AuxInt = int64ToAuxInt(val)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64SLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SLL x (MOVBconst [val]))
+ // result: (SLLI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVBconst {
+ break
+ }
+ val := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRISCV64SLLI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLL x (MOVHconst [val]))
+ // result: (SLLI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVHconst {
+ break
+ }
+ val := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRISCV64SLLI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLL x (MOVWconst [val]))
+ // result: (SLLI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVWconst {
+ break
+ }
+ val := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRISCV64SLLI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLL x (MOVDconst [val]))
+ // result: (SLLI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVDconst {
+ break
+ }
+ val := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpRISCV64SLLI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64SRA(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRA x (MOVBconst [val]))
+ // result: (SRAI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVBconst {
+ break
+ }
+ val := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRISCV64SRAI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRA x (MOVHconst [val]))
+ // result: (SRAI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVHconst {
+ break
+ }
+ val := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRISCV64SRAI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRA x (MOVWconst [val]))
+ // result: (SRAI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVWconst {
+ break
+ }
+ val := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRISCV64SRAI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRA x (MOVDconst [val]))
+ // result: (SRAI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVDconst {
+ break
+ }
+ val := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpRISCV64SRAI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64SRL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SRL x (MOVBconst [val]))
+ // result: (SRLI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVBconst {
+ break
+ }
+ val := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRISCV64SRLI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRL x (MOVHconst [val]))
+ // result: (SRLI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVHconst {
+ break
+ }
+ val := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRISCV64SRLI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRL x (MOVWconst [val]))
+ // result: (SRLI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVWconst {
+ break
+ }
+ val := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRISCV64SRLI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRL x (MOVDconst [val]))
+ // result: (SRLI [int64(val&63)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVDconst {
+ break
+ }
+ val := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpRISCV64SRLI)
+ v.AuxInt = int64ToAuxInt(int64(val & 63))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64SUB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUB x (MOVBconst [val]))
+ // result: (ADDI [-int64(val)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVBconst {
+ break
+ }
+ val := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRISCV64ADDI)
+ v.AuxInt = int64ToAuxInt(-int64(val))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB x (MOVHconst [val]))
+ // result: (ADDI [-int64(val)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVHconst {
+ break
+ }
+ val := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRISCV64ADDI)
+ v.AuxInt = int64ToAuxInt(-int64(val))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB x (MOVWconst [val]))
+ // cond: is32Bit(-int64(val))
+ // result: (ADDI [-int64(val)] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVWconst {
+ break
+ }
+ val := auxIntToInt32(v_1.AuxInt)
+ if !(is32Bit(-int64(val))) {
+ break
+ }
+ v.reset(OpRISCV64ADDI)
+ v.AuxInt = int64ToAuxInt(-int64(val))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB x (MOVDconst [val]))
+ // cond: is32Bit(-val)
+ // result: (ADDI [-val] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVDconst {
+ break
+ }
+ val := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(-val)) {
+ break
+ }
+ v.reset(OpRISCV64ADDI)
+ v.AuxInt = int64ToAuxInt(-val)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB x (MOVBconst [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVBconst || auxIntToInt8(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUB x (MOVHconst [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVHconst || auxIntToInt16(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUB x (MOVWconst [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUB x (MOVDconst [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUB (MOVBconst [0]) x)
+ // result: (NEG x)
+ for {
+ if v_0.Op != OpRISCV64MOVBconst || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpRISCV64NEG)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB (MOVHconst [0]) x)
+ // result: (NEG x)
+ for {
+ if v_0.Op != OpRISCV64MOVHconst || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpRISCV64NEG)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB (MOVWconst [0]) x)
+ // result: (NEG x)
+ for {
+ if v_0.Op != OpRISCV64MOVWconst || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpRISCV64NEG)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB (MOVDconst [0]) x)
+ // result: (NEG x)
+ for {
+ if v_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpRISCV64NEG)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64SUBW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBW x (MOVWconst [0]))
+ // result: (ADDIW [0] x)
+ for {
+ x := v_0
+ if v_1.Op != OpRISCV64MOVWconst || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpRISCV64ADDIW)
+ v.AuxInt = int64ToAuxInt(0)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBW (MOVDconst [0]) x)
+ // result: (NEGW x)
+ for {
+ if v_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpRISCV64NEGW)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRISCV64XOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XOR (MOVBconst [val]) x)
+ // result: (XORI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVBconst {
+ continue
+ }
+ val := auxIntToInt8(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64XORI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR (MOVHconst [val]) x)
+ // result: (XORI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVHconst {
+ continue
+ }
+ val := auxIntToInt16(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64XORI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR (MOVWconst [val]) x)
+ // result: (XORI [int64(val)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVWconst {
+ continue
+ }
+ val := auxIntToInt32(v_0.AuxInt)
+ x := v_1
+ v.reset(OpRISCV64XORI)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR (MOVDconst [val]) x)
+ // cond: is32Bit(val)
+ // result: (XORI [val] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpRISCV64MOVDconst {
+ continue
+ }
+ val := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(val)) {
+ continue
+ }
+ v.reset(OpRISCV64XORI)
+ v.AuxInt = int64ToAuxInt(val)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRotateLeft16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft16 <t> x (MOVHconst [c]))
+ // result: (Or16 (Lsh16x64 <t> x (MOVHconst [c&15])) (Rsh16Ux64 <t> x (MOVHconst [-c&15])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpRISCV64MOVHconst {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpLsh16x64, t)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16)
+ v1.AuxInt = int16ToAuxInt(c & 15)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh16Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16)
+ v3.AuxInt = int16ToAuxInt(-c & 15)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRotateLeft32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft32 <t> x (MOVWconst [c]))
+ // result: (Or32 (Lsh32x64 <t> x (MOVWconst [c&31])) (Rsh32Ux64 <t> x (MOVWconst [-c&31])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpRISCV64MOVWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpOr32)
+ v0 := b.NewValue0(v.Pos, OpLsh32x64, t)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(c & 31)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh32Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVWconst, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(-c & 31)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRotateLeft64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft64 <t> x (MOVDconst [c]))
+ // result: (Or64 (Lsh64x64 <t> x (MOVDconst [c&63])) (Rsh64Ux64 <t> x (MOVDconst [-c&63])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpRISCV64MOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr64)
+ v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c & 63)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh64Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(-c & 63)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRotateLeft8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft8 <t> x (MOVBconst [c]))
+ // result: (Or8 (Lsh8x64 <t> x (MOVBconst [c&7])) (Rsh8Ux64 <t> x (MOVBconst [-c&7])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpRISCV64MOVBconst {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpLsh8x64, t)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVBconst, typ.UInt8)
+ v1.AuxInt = int8ToAuxInt(c & 7)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh8Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVBconst, typ.UInt8)
+ v3.AuxInt = int8ToAuxInt(-c & 7)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux16 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg16, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux32 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg16, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux64 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg16, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux8 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg16, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x16 <t> x y)
+ // result: (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x32 <t> x y)
+ // result: (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x64 <t> x y)
+ // result: (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x8 <t> x y)
+ // result: (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux16 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg32, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux32 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg32, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux64 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg32, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux8 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg32, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x16 <t> x y)
+ // result: (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x32 <t> x y)
+ // result: (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x64 <t> x y)
+ // result: (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x8 <t> x y)
+ // result: (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh64Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux16 <t> x y)
+ // result: (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg64, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh64Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux32 <t> x y)
+ // result: (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg64, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh64Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64Ux64 <t> x y)
+ // result: (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg64, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh64Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux8 <t> x y)
+ // result: (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpNeg64, t)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x16 <t> x y)
+ // result: (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v1 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x32 <t> x y)
+ // result: (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v1 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x64 <t> x y)
+ // result: (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v1 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v2.AuxInt = int64ToAuxInt(64)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x8 <t> x y)
+ // result: (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v1 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v2 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v2.AuxInt = int64ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(y, v1)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux16 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg8, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux32 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg8, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux64 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] y)))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg8, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux8 <t> x y)
+ // result: (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64AND)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpNeg8, t)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, t)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x16 <t> x y)
+ // result: (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x32 <t> x y)
+ // result: (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x64 <t> x y)
+ // result: (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x8 <t> x y)
+ // result: (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpRISCV64SRA)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpRISCV64OR, y.Type)
+ v2 := b.NewValue0(v.Pos, OpRISCV64ADDI, y.Type)
+ v2.AuxInt = int64ToAuxInt(-1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64SLTIU, y.Type)
+ v3.AuxInt = int64ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v2.AddArg(v3)
+ v1.AddArg2(y, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Slicemask <t> x)
+ // result: (NOT (SRAI <t> [63] (ADDI <t> [-1] x)))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpRISCV64NOT)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SRAI, t)
+ v0.AuxInt = int64ToAuxInt(63)
+ v1 := b.NewValue0(v.Pos, OpRISCV64ADDI, t)
+ v1.AuxInt = int64ToAuxInt(-1)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueRISCV64_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 1
+ // result: (MOVBstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 1) {
+ break
+ }
+ v.reset(OpRISCV64MOVBstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 2
+ // result: (MOVHstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 2) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && !is32BitFloat(val.Type)
+ // result: (MOVWstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && !is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && !is64BitFloat(val.Type)
+ // result: (MOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && !is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && is32BitFloat(val.Type)
+ // result: (FMOVWstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpRISCV64FMOVWstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && is64BitFloat(val.Type)
+ // result: (FMOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpRISCV64FMOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Zero [0] _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_1
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero [1] ptr mem)
+ // result: (MOVBstore ptr (MOVBconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpRISCV64MOVBstore)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVBconst, typ.UInt8)
+ v0.AuxInt = int8ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [2] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore ptr (MOVHconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16)
+ v0.AuxInt = int16ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [2] ptr mem)
+ // result: (MOVBstore [1] ptr (MOVBconst [0]) (MOVBstore ptr (MOVBconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVBconst, typ.UInt8)
+ v0.AuxInt = int8ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [4] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore ptr (MOVWconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstore)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [4] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [2] ptr (MOVHconst [0]) (MOVHstore ptr (MOVHconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16)
+ v0.AuxInt = int16ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [4] ptr mem)
+ // result: (MOVBstore [3] ptr (MOVBconst [0]) (MOVBstore [2] ptr (MOVBconst [0]) (MOVBstore [1] ptr (MOVBconst [0]) (MOVBstore ptr (MOVBconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVBconst, typ.UInt8)
+ v0.AuxInt = int8ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(1)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v3.AddArg3(ptr, v0, mem)
+ v2.AddArg3(ptr, v0, v3)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [8] {t} ptr mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVDstore ptr (MOVDconst [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+ // match: (Zero [8] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [4] ptr (MOVWconst [0]) (MOVWstore ptr (MOVWconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [8] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [6] ptr (MOVHconst [0]) (MOVHstore [4] ptr (MOVHconst [0]) (MOVHstore [2] ptr (MOVHconst [0]) (MOVHstore ptr (MOVHconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16)
+ v0.AuxInt = int16ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(2)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v3.AddArg3(ptr, v0, mem)
+ v2.AddArg3(ptr, v0, v3)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [3] ptr mem)
+ // result: (MOVBstore [2] ptr (MOVBconst [0]) (MOVBstore [1] ptr (MOVBconst [0]) (MOVBstore ptr (MOVBconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ ptr := v_0
+ mem := v_1
+ v.reset(OpRISCV64MOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVBconst, typ.UInt8)
+ v0.AuxInt = int8ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [6] {t} ptr mem)
+ // cond: t.Alignment()%2 == 0
+ // result: (MOVHstore [4] ptr (MOVHconst [0]) (MOVHstore [2] ptr (MOVHconst [0]) (MOVHstore ptr (MOVHconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%2 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVHstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16)
+ v0.AuxInt = int16ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(2)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [12] {t} ptr mem)
+ // cond: t.Alignment()%4 == 0
+ // result: (MOVWstore [8] ptr (MOVWconst [0]) (MOVWstore [4] ptr (MOVWconst [0]) (MOVWstore ptr (MOVWconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 12 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%4 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVWstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [16] {t} ptr mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVDstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v1.AddArg3(ptr, v0, mem)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [24] {t} ptr mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVDstore [16] ptr (MOVDconst [0]) (MOVDstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v.AuxInt = int32ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v2.AddArg3(ptr, v0, mem)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [32] {t} ptr mem)
+ // cond: t.Alignment()%8 == 0
+ // result: (MOVDstore [24] ptr (MOVDconst [0]) (MOVDstore [16] ptr (MOVDconst [0]) (MOVDstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 32 {
+ break
+ }
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(t.Alignment()%8 == 0) {
+ break
+ }
+ v.reset(OpRISCV64MOVDstore)
+ v.AuxInt = int32ToAuxInt(24)
+ v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(16)
+ v2 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v2.AuxInt = int32ToAuxInt(8)
+ v3 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem)
+ v3.AddArg3(ptr, v0, mem)
+ v2.AddArg3(ptr, v0, v3)
+ v1.AddArg3(ptr, v0, v2)
+ v.AddArg3(ptr, v0, v1)
+ return true
+ }
+ // match: (Zero [s] {t} ptr mem)
+ // cond: s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice
+ // result: (DUFFZERO [8 * (128 - s/8)] ptr mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ if !(s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice) {
+ break
+ }
+ v.reset(OpRISCV64DUFFZERO)
+ v.AuxInt = int64ToAuxInt(8 * (128 - s/8))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Zero [s] {t} ptr mem)
+ // result: (LoweredZero [t.Alignment()] ptr (ADD <ptr.Type> ptr (MOVDconst [s-moveSize(t.Alignment(), config)])) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ ptr := v_0
+ mem := v_1
+ v.reset(OpRISCV64LoweredZero)
+ v.AuxInt = int64ToAuxInt(t.Alignment())
+ v0 := b.NewValue0(v.Pos, OpRISCV64ADD, ptr.Type)
+ v1 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(s - moveSize(t.Alignment(), config))
+ v0.AddArg2(ptr, v1)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+}
+func rewriteBlockRISCV64(b *Block) bool {
+ switch b.Kind {
+ case BlockRISCV64BEQ:
+ // match: (BEQ (MOVDconst [0]) cond yes no)
+ // result: (BEQZ cond yes no)
+ for b.Controls[0].Op == OpRISCV64MOVDconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ cond := b.Controls[1]
+ b.resetWithControl(BlockRISCV64BEQZ, cond)
+ return true
+ }
+ // match: (BEQ cond (MOVDconst [0]) yes no)
+ // result: (BEQZ cond yes no)
+ for b.Controls[1].Op == OpRISCV64MOVDconst {
+ cond := b.Controls[0]
+ v_1 := b.Controls[1]
+ if auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ b.resetWithControl(BlockRISCV64BEQZ, cond)
+ return true
+ }
+ case BlockRISCV64BEQZ:
+ // match: (BEQZ (SEQZ x) yes no)
+ // result: (BNEZ x yes no)
+ for b.Controls[0].Op == OpRISCV64SEQZ {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ b.resetWithControl(BlockRISCV64BNEZ, x)
+ return true
+ }
+ // match: (BEQZ (SNEZ x) yes no)
+ // result: (BEQZ x yes no)
+ for b.Controls[0].Op == OpRISCV64SNEZ {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ b.resetWithControl(BlockRISCV64BEQZ, x)
+ return true
+ }
+ // match: (BEQZ (SUB x y) yes no)
+ // result: (BEQ x y yes no)
+ for b.Controls[0].Op == OpRISCV64SUB {
+ v_0 := b.Controls[0]
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ b.resetWithControl2(BlockRISCV64BEQ, x, y)
+ return true
+ }
+ // match: (BEQZ (SLT x y) yes no)
+ // result: (BGE x y yes no)
+ for b.Controls[0].Op == OpRISCV64SLT {
+ v_0 := b.Controls[0]
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ b.resetWithControl2(BlockRISCV64BGE, x, y)
+ return true
+ }
+ // match: (BEQZ (SLTU x y) yes no)
+ // result: (BGEU x y yes no)
+ for b.Controls[0].Op == OpRISCV64SLTU {
+ v_0 := b.Controls[0]
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ b.resetWithControl2(BlockRISCV64BGEU, x, y)
+ return true
+ }
+ case BlockRISCV64BNE:
+ // match: (BNE (MOVDconst [0]) cond yes no)
+ // result: (BNEZ cond yes no)
+ for b.Controls[0].Op == OpRISCV64MOVDconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ cond := b.Controls[1]
+ b.resetWithControl(BlockRISCV64BNEZ, cond)
+ return true
+ }
+ // match: (BNE cond (MOVDconst [0]) yes no)
+ // result: (BNEZ cond yes no)
+ for b.Controls[1].Op == OpRISCV64MOVDconst {
+ cond := b.Controls[0]
+ v_1 := b.Controls[1]
+ if auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ b.resetWithControl(BlockRISCV64BNEZ, cond)
+ return true
+ }
+ case BlockRISCV64BNEZ:
+ // match: (BNEZ (SEQZ x) yes no)
+ // result: (BEQZ x yes no)
+ for b.Controls[0].Op == OpRISCV64SEQZ {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ b.resetWithControl(BlockRISCV64BEQZ, x)
+ return true
+ }
+ // match: (BNEZ (SNEZ x) yes no)
+ // result: (BNEZ x yes no)
+ for b.Controls[0].Op == OpRISCV64SNEZ {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ b.resetWithControl(BlockRISCV64BNEZ, x)
+ return true
+ }
+ // match: (BNEZ (SUB x y) yes no)
+ // result: (BNE x y yes no)
+ for b.Controls[0].Op == OpRISCV64SUB {
+ v_0 := b.Controls[0]
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ b.resetWithControl2(BlockRISCV64BNE, x, y)
+ return true
+ }
+ // match: (BNEZ (SLT x y) yes no)
+ // result: (BLT x y yes no)
+ for b.Controls[0].Op == OpRISCV64SLT {
+ v_0 := b.Controls[0]
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ b.resetWithControl2(BlockRISCV64BLT, x, y)
+ return true
+ }
+ // match: (BNEZ (SLTU x y) yes no)
+ // result: (BLTU x y yes no)
+ for b.Controls[0].Op == OpRISCV64SLTU {
+ v_0 := b.Controls[0]
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ b.resetWithControl2(BlockRISCV64BLTU, x, y)
+ return true
+ }
+ case BlockIf:
+ // match: (If cond yes no)
+ // result: (BNEZ cond yes no)
+ for {
+ cond := b.Controls[0]
+ b.resetWithControl(BlockRISCV64BNEZ, cond)
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteS390X.go b/src/cmd/compile/internal/ssa/rewriteS390X.go
new file mode 100644
index 0000000..a9722b8
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewriteS390X.go
@@ -0,0 +1,17859 @@
+// Code generated from gen/S390X.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "math"
+import "cmd/compile/internal/types"
+import "cmd/internal/obj/s390x"
+
+func rewriteValueS390X(v *Value) bool {
+ switch v.Op {
+ case OpAdd16:
+ v.Op = OpS390XADDW
+ return true
+ case OpAdd32:
+ v.Op = OpS390XADDW
+ return true
+ case OpAdd32F:
+ return rewriteValueS390X_OpAdd32F(v)
+ case OpAdd64:
+ v.Op = OpS390XADD
+ return true
+ case OpAdd64F:
+ return rewriteValueS390X_OpAdd64F(v)
+ case OpAdd8:
+ v.Op = OpS390XADDW
+ return true
+ case OpAddPtr:
+ v.Op = OpS390XADD
+ return true
+ case OpAddr:
+ return rewriteValueS390X_OpAddr(v)
+ case OpAnd16:
+ v.Op = OpS390XANDW
+ return true
+ case OpAnd32:
+ v.Op = OpS390XANDW
+ return true
+ case OpAnd64:
+ v.Op = OpS390XAND
+ return true
+ case OpAnd8:
+ v.Op = OpS390XANDW
+ return true
+ case OpAndB:
+ v.Op = OpS390XANDW
+ return true
+ case OpAtomicAdd32:
+ return rewriteValueS390X_OpAtomicAdd32(v)
+ case OpAtomicAdd64:
+ return rewriteValueS390X_OpAtomicAdd64(v)
+ case OpAtomicAnd32:
+ v.Op = OpS390XLAN
+ return true
+ case OpAtomicAnd8:
+ return rewriteValueS390X_OpAtomicAnd8(v)
+ case OpAtomicCompareAndSwap32:
+ return rewriteValueS390X_OpAtomicCompareAndSwap32(v)
+ case OpAtomicCompareAndSwap64:
+ return rewriteValueS390X_OpAtomicCompareAndSwap64(v)
+ case OpAtomicExchange32:
+ return rewriteValueS390X_OpAtomicExchange32(v)
+ case OpAtomicExchange64:
+ return rewriteValueS390X_OpAtomicExchange64(v)
+ case OpAtomicLoad32:
+ return rewriteValueS390X_OpAtomicLoad32(v)
+ case OpAtomicLoad64:
+ return rewriteValueS390X_OpAtomicLoad64(v)
+ case OpAtomicLoad8:
+ return rewriteValueS390X_OpAtomicLoad8(v)
+ case OpAtomicLoadAcq32:
+ return rewriteValueS390X_OpAtomicLoadAcq32(v)
+ case OpAtomicLoadPtr:
+ return rewriteValueS390X_OpAtomicLoadPtr(v)
+ case OpAtomicOr32:
+ v.Op = OpS390XLAO
+ return true
+ case OpAtomicOr8:
+ return rewriteValueS390X_OpAtomicOr8(v)
+ case OpAtomicStore32:
+ return rewriteValueS390X_OpAtomicStore32(v)
+ case OpAtomicStore64:
+ return rewriteValueS390X_OpAtomicStore64(v)
+ case OpAtomicStore8:
+ return rewriteValueS390X_OpAtomicStore8(v)
+ case OpAtomicStorePtrNoWB:
+ return rewriteValueS390X_OpAtomicStorePtrNoWB(v)
+ case OpAtomicStoreRel32:
+ return rewriteValueS390X_OpAtomicStoreRel32(v)
+ case OpAvg64u:
+ return rewriteValueS390X_OpAvg64u(v)
+ case OpBitLen64:
+ return rewriteValueS390X_OpBitLen64(v)
+ case OpBswap32:
+ v.Op = OpS390XMOVWBR
+ return true
+ case OpBswap64:
+ v.Op = OpS390XMOVDBR
+ return true
+ case OpCeil:
+ return rewriteValueS390X_OpCeil(v)
+ case OpClosureCall:
+ v.Op = OpS390XCALLclosure
+ return true
+ case OpCom16:
+ v.Op = OpS390XNOTW
+ return true
+ case OpCom32:
+ v.Op = OpS390XNOTW
+ return true
+ case OpCom64:
+ v.Op = OpS390XNOT
+ return true
+ case OpCom8:
+ v.Op = OpS390XNOTW
+ return true
+ case OpConst16:
+ return rewriteValueS390X_OpConst16(v)
+ case OpConst32:
+ return rewriteValueS390X_OpConst32(v)
+ case OpConst32F:
+ v.Op = OpS390XFMOVSconst
+ return true
+ case OpConst64:
+ return rewriteValueS390X_OpConst64(v)
+ case OpConst64F:
+ v.Op = OpS390XFMOVDconst
+ return true
+ case OpConst8:
+ return rewriteValueS390X_OpConst8(v)
+ case OpConstBool:
+ return rewriteValueS390X_OpConstBool(v)
+ case OpConstNil:
+ return rewriteValueS390X_OpConstNil(v)
+ case OpCtz32:
+ return rewriteValueS390X_OpCtz32(v)
+ case OpCtz32NonZero:
+ v.Op = OpCtz32
+ return true
+ case OpCtz64:
+ return rewriteValueS390X_OpCtz64(v)
+ case OpCtz64NonZero:
+ v.Op = OpCtz64
+ return true
+ case OpCvt32Fto32:
+ v.Op = OpS390XCFEBRA
+ return true
+ case OpCvt32Fto32U:
+ v.Op = OpS390XCLFEBR
+ return true
+ case OpCvt32Fto64:
+ v.Op = OpS390XCGEBRA
+ return true
+ case OpCvt32Fto64F:
+ v.Op = OpS390XLDEBR
+ return true
+ case OpCvt32Fto64U:
+ v.Op = OpS390XCLGEBR
+ return true
+ case OpCvt32Uto32F:
+ v.Op = OpS390XCELFBR
+ return true
+ case OpCvt32Uto64F:
+ v.Op = OpS390XCDLFBR
+ return true
+ case OpCvt32to32F:
+ v.Op = OpS390XCEFBRA
+ return true
+ case OpCvt32to64F:
+ v.Op = OpS390XCDFBRA
+ return true
+ case OpCvt64Fto32:
+ v.Op = OpS390XCFDBRA
+ return true
+ case OpCvt64Fto32F:
+ v.Op = OpS390XLEDBR
+ return true
+ case OpCvt64Fto32U:
+ v.Op = OpS390XCLFDBR
+ return true
+ case OpCvt64Fto64:
+ v.Op = OpS390XCGDBRA
+ return true
+ case OpCvt64Fto64U:
+ v.Op = OpS390XCLGDBR
+ return true
+ case OpCvt64Uto32F:
+ v.Op = OpS390XCELGBR
+ return true
+ case OpCvt64Uto64F:
+ v.Op = OpS390XCDLGBR
+ return true
+ case OpCvt64to32F:
+ v.Op = OpS390XCEGBRA
+ return true
+ case OpCvt64to64F:
+ v.Op = OpS390XCDGBRA
+ return true
+ case OpCvtBoolToUint8:
+ v.Op = OpCopy
+ return true
+ case OpDiv16:
+ return rewriteValueS390X_OpDiv16(v)
+ case OpDiv16u:
+ return rewriteValueS390X_OpDiv16u(v)
+ case OpDiv32:
+ return rewriteValueS390X_OpDiv32(v)
+ case OpDiv32F:
+ v.Op = OpS390XFDIVS
+ return true
+ case OpDiv32u:
+ return rewriteValueS390X_OpDiv32u(v)
+ case OpDiv64:
+ return rewriteValueS390X_OpDiv64(v)
+ case OpDiv64F:
+ v.Op = OpS390XFDIV
+ return true
+ case OpDiv64u:
+ v.Op = OpS390XDIVDU
+ return true
+ case OpDiv8:
+ return rewriteValueS390X_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValueS390X_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValueS390X_OpEq16(v)
+ case OpEq32:
+ return rewriteValueS390X_OpEq32(v)
+ case OpEq32F:
+ return rewriteValueS390X_OpEq32F(v)
+ case OpEq64:
+ return rewriteValueS390X_OpEq64(v)
+ case OpEq64F:
+ return rewriteValueS390X_OpEq64F(v)
+ case OpEq8:
+ return rewriteValueS390X_OpEq8(v)
+ case OpEqB:
+ return rewriteValueS390X_OpEqB(v)
+ case OpEqPtr:
+ return rewriteValueS390X_OpEqPtr(v)
+ case OpFMA:
+ return rewriteValueS390X_OpFMA(v)
+ case OpFloor:
+ return rewriteValueS390X_OpFloor(v)
+ case OpGetCallerPC:
+ v.Op = OpS390XLoweredGetCallerPC
+ return true
+ case OpGetCallerSP:
+ v.Op = OpS390XLoweredGetCallerSP
+ return true
+ case OpGetClosurePtr:
+ v.Op = OpS390XLoweredGetClosurePtr
+ return true
+ case OpGetG:
+ v.Op = OpS390XLoweredGetG
+ return true
+ case OpHmul32:
+ return rewriteValueS390X_OpHmul32(v)
+ case OpHmul32u:
+ return rewriteValueS390X_OpHmul32u(v)
+ case OpHmul64:
+ v.Op = OpS390XMULHD
+ return true
+ case OpHmul64u:
+ v.Op = OpS390XMULHDU
+ return true
+ case OpITab:
+ return rewriteValueS390X_OpITab(v)
+ case OpInterCall:
+ v.Op = OpS390XCALLinter
+ return true
+ case OpIsInBounds:
+ return rewriteValueS390X_OpIsInBounds(v)
+ case OpIsNonNil:
+ return rewriteValueS390X_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ return rewriteValueS390X_OpIsSliceInBounds(v)
+ case OpLeq16:
+ return rewriteValueS390X_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValueS390X_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValueS390X_OpLeq32(v)
+ case OpLeq32F:
+ return rewriteValueS390X_OpLeq32F(v)
+ case OpLeq32U:
+ return rewriteValueS390X_OpLeq32U(v)
+ case OpLeq64:
+ return rewriteValueS390X_OpLeq64(v)
+ case OpLeq64F:
+ return rewriteValueS390X_OpLeq64F(v)
+ case OpLeq64U:
+ return rewriteValueS390X_OpLeq64U(v)
+ case OpLeq8:
+ return rewriteValueS390X_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValueS390X_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValueS390X_OpLess16(v)
+ case OpLess16U:
+ return rewriteValueS390X_OpLess16U(v)
+ case OpLess32:
+ return rewriteValueS390X_OpLess32(v)
+ case OpLess32F:
+ return rewriteValueS390X_OpLess32F(v)
+ case OpLess32U:
+ return rewriteValueS390X_OpLess32U(v)
+ case OpLess64:
+ return rewriteValueS390X_OpLess64(v)
+ case OpLess64F:
+ return rewriteValueS390X_OpLess64F(v)
+ case OpLess64U:
+ return rewriteValueS390X_OpLess64U(v)
+ case OpLess8:
+ return rewriteValueS390X_OpLess8(v)
+ case OpLess8U:
+ return rewriteValueS390X_OpLess8U(v)
+ case OpLoad:
+ return rewriteValueS390X_OpLoad(v)
+ case OpLocalAddr:
+ return rewriteValueS390X_OpLocalAddr(v)
+ case OpLsh16x16:
+ return rewriteValueS390X_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValueS390X_OpLsh16x32(v)
+ case OpLsh16x64:
+ return rewriteValueS390X_OpLsh16x64(v)
+ case OpLsh16x8:
+ return rewriteValueS390X_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValueS390X_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValueS390X_OpLsh32x32(v)
+ case OpLsh32x64:
+ return rewriteValueS390X_OpLsh32x64(v)
+ case OpLsh32x8:
+ return rewriteValueS390X_OpLsh32x8(v)
+ case OpLsh64x16:
+ return rewriteValueS390X_OpLsh64x16(v)
+ case OpLsh64x32:
+ return rewriteValueS390X_OpLsh64x32(v)
+ case OpLsh64x64:
+ return rewriteValueS390X_OpLsh64x64(v)
+ case OpLsh64x8:
+ return rewriteValueS390X_OpLsh64x8(v)
+ case OpLsh8x16:
+ return rewriteValueS390X_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValueS390X_OpLsh8x32(v)
+ case OpLsh8x64:
+ return rewriteValueS390X_OpLsh8x64(v)
+ case OpLsh8x8:
+ return rewriteValueS390X_OpLsh8x8(v)
+ case OpMod16:
+ return rewriteValueS390X_OpMod16(v)
+ case OpMod16u:
+ return rewriteValueS390X_OpMod16u(v)
+ case OpMod32:
+ return rewriteValueS390X_OpMod32(v)
+ case OpMod32u:
+ return rewriteValueS390X_OpMod32u(v)
+ case OpMod64:
+ return rewriteValueS390X_OpMod64(v)
+ case OpMod64u:
+ v.Op = OpS390XMODDU
+ return true
+ case OpMod8:
+ return rewriteValueS390X_OpMod8(v)
+ case OpMod8u:
+ return rewriteValueS390X_OpMod8u(v)
+ case OpMove:
+ return rewriteValueS390X_OpMove(v)
+ case OpMul16:
+ v.Op = OpS390XMULLW
+ return true
+ case OpMul32:
+ v.Op = OpS390XMULLW
+ return true
+ case OpMul32F:
+ v.Op = OpS390XFMULS
+ return true
+ case OpMul64:
+ v.Op = OpS390XMULLD
+ return true
+ case OpMul64F:
+ v.Op = OpS390XFMUL
+ return true
+ case OpMul64uhilo:
+ v.Op = OpS390XMLGR
+ return true
+ case OpMul8:
+ v.Op = OpS390XMULLW
+ return true
+ case OpNeg16:
+ v.Op = OpS390XNEGW
+ return true
+ case OpNeg32:
+ v.Op = OpS390XNEGW
+ return true
+ case OpNeg32F:
+ v.Op = OpS390XFNEGS
+ return true
+ case OpNeg64:
+ v.Op = OpS390XNEG
+ return true
+ case OpNeg64F:
+ v.Op = OpS390XFNEG
+ return true
+ case OpNeg8:
+ v.Op = OpS390XNEGW
+ return true
+ case OpNeq16:
+ return rewriteValueS390X_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValueS390X_OpNeq32(v)
+ case OpNeq32F:
+ return rewriteValueS390X_OpNeq32F(v)
+ case OpNeq64:
+ return rewriteValueS390X_OpNeq64(v)
+ case OpNeq64F:
+ return rewriteValueS390X_OpNeq64F(v)
+ case OpNeq8:
+ return rewriteValueS390X_OpNeq8(v)
+ case OpNeqB:
+ return rewriteValueS390X_OpNeqB(v)
+ case OpNeqPtr:
+ return rewriteValueS390X_OpNeqPtr(v)
+ case OpNilCheck:
+ v.Op = OpS390XLoweredNilCheck
+ return true
+ case OpNot:
+ return rewriteValueS390X_OpNot(v)
+ case OpOffPtr:
+ return rewriteValueS390X_OpOffPtr(v)
+ case OpOr16:
+ v.Op = OpS390XORW
+ return true
+ case OpOr32:
+ v.Op = OpS390XORW
+ return true
+ case OpOr64:
+ v.Op = OpS390XOR
+ return true
+ case OpOr8:
+ v.Op = OpS390XORW
+ return true
+ case OpOrB:
+ v.Op = OpS390XORW
+ return true
+ case OpPanicBounds:
+ return rewriteValueS390X_OpPanicBounds(v)
+ case OpPopCount16:
+ return rewriteValueS390X_OpPopCount16(v)
+ case OpPopCount32:
+ return rewriteValueS390X_OpPopCount32(v)
+ case OpPopCount64:
+ return rewriteValueS390X_OpPopCount64(v)
+ case OpPopCount8:
+ return rewriteValueS390X_OpPopCount8(v)
+ case OpRotateLeft16:
+ return rewriteValueS390X_OpRotateLeft16(v)
+ case OpRotateLeft32:
+ v.Op = OpS390XRLL
+ return true
+ case OpRotateLeft64:
+ v.Op = OpS390XRLLG
+ return true
+ case OpRotateLeft8:
+ return rewriteValueS390X_OpRotateLeft8(v)
+ case OpRound:
+ return rewriteValueS390X_OpRound(v)
+ case OpRound32F:
+ v.Op = OpS390XLoweredRound32F
+ return true
+ case OpRound64F:
+ v.Op = OpS390XLoweredRound64F
+ return true
+ case OpRoundToEven:
+ return rewriteValueS390X_OpRoundToEven(v)
+ case OpRsh16Ux16:
+ return rewriteValueS390X_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValueS390X_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValueS390X_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValueS390X_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValueS390X_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValueS390X_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValueS390X_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValueS390X_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValueS390X_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValueS390X_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValueS390X_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValueS390X_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValueS390X_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValueS390X_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValueS390X_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValueS390X_OpRsh32x8(v)
+ case OpRsh64Ux16:
+ return rewriteValueS390X_OpRsh64Ux16(v)
+ case OpRsh64Ux32:
+ return rewriteValueS390X_OpRsh64Ux32(v)
+ case OpRsh64Ux64:
+ return rewriteValueS390X_OpRsh64Ux64(v)
+ case OpRsh64Ux8:
+ return rewriteValueS390X_OpRsh64Ux8(v)
+ case OpRsh64x16:
+ return rewriteValueS390X_OpRsh64x16(v)
+ case OpRsh64x32:
+ return rewriteValueS390X_OpRsh64x32(v)
+ case OpRsh64x64:
+ return rewriteValueS390X_OpRsh64x64(v)
+ case OpRsh64x8:
+ return rewriteValueS390X_OpRsh64x8(v)
+ case OpRsh8Ux16:
+ return rewriteValueS390X_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValueS390X_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValueS390X_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValueS390X_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValueS390X_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValueS390X_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValueS390X_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValueS390X_OpRsh8x8(v)
+ case OpS390XADD:
+ return rewriteValueS390X_OpS390XADD(v)
+ case OpS390XADDC:
+ return rewriteValueS390X_OpS390XADDC(v)
+ case OpS390XADDE:
+ return rewriteValueS390X_OpS390XADDE(v)
+ case OpS390XADDW:
+ return rewriteValueS390X_OpS390XADDW(v)
+ case OpS390XADDWconst:
+ return rewriteValueS390X_OpS390XADDWconst(v)
+ case OpS390XADDWload:
+ return rewriteValueS390X_OpS390XADDWload(v)
+ case OpS390XADDconst:
+ return rewriteValueS390X_OpS390XADDconst(v)
+ case OpS390XADDload:
+ return rewriteValueS390X_OpS390XADDload(v)
+ case OpS390XAND:
+ return rewriteValueS390X_OpS390XAND(v)
+ case OpS390XANDW:
+ return rewriteValueS390X_OpS390XANDW(v)
+ case OpS390XANDWconst:
+ return rewriteValueS390X_OpS390XANDWconst(v)
+ case OpS390XANDWload:
+ return rewriteValueS390X_OpS390XANDWload(v)
+ case OpS390XANDconst:
+ return rewriteValueS390X_OpS390XANDconst(v)
+ case OpS390XANDload:
+ return rewriteValueS390X_OpS390XANDload(v)
+ case OpS390XCMP:
+ return rewriteValueS390X_OpS390XCMP(v)
+ case OpS390XCMPU:
+ return rewriteValueS390X_OpS390XCMPU(v)
+ case OpS390XCMPUconst:
+ return rewriteValueS390X_OpS390XCMPUconst(v)
+ case OpS390XCMPW:
+ return rewriteValueS390X_OpS390XCMPW(v)
+ case OpS390XCMPWU:
+ return rewriteValueS390X_OpS390XCMPWU(v)
+ case OpS390XCMPWUconst:
+ return rewriteValueS390X_OpS390XCMPWUconst(v)
+ case OpS390XCMPWconst:
+ return rewriteValueS390X_OpS390XCMPWconst(v)
+ case OpS390XCMPconst:
+ return rewriteValueS390X_OpS390XCMPconst(v)
+ case OpS390XCPSDR:
+ return rewriteValueS390X_OpS390XCPSDR(v)
+ case OpS390XFCMP:
+ return rewriteValueS390X_OpS390XFCMP(v)
+ case OpS390XFCMPS:
+ return rewriteValueS390X_OpS390XFCMPS(v)
+ case OpS390XFMOVDload:
+ return rewriteValueS390X_OpS390XFMOVDload(v)
+ case OpS390XFMOVDstore:
+ return rewriteValueS390X_OpS390XFMOVDstore(v)
+ case OpS390XFMOVSload:
+ return rewriteValueS390X_OpS390XFMOVSload(v)
+ case OpS390XFMOVSstore:
+ return rewriteValueS390X_OpS390XFMOVSstore(v)
+ case OpS390XFNEG:
+ return rewriteValueS390X_OpS390XFNEG(v)
+ case OpS390XFNEGS:
+ return rewriteValueS390X_OpS390XFNEGS(v)
+ case OpS390XLDGR:
+ return rewriteValueS390X_OpS390XLDGR(v)
+ case OpS390XLEDBR:
+ return rewriteValueS390X_OpS390XLEDBR(v)
+ case OpS390XLGDR:
+ return rewriteValueS390X_OpS390XLGDR(v)
+ case OpS390XLOCGR:
+ return rewriteValueS390X_OpS390XLOCGR(v)
+ case OpS390XLTDBR:
+ return rewriteValueS390X_OpS390XLTDBR(v)
+ case OpS390XLTEBR:
+ return rewriteValueS390X_OpS390XLTEBR(v)
+ case OpS390XLoweredRound32F:
+ return rewriteValueS390X_OpS390XLoweredRound32F(v)
+ case OpS390XLoweredRound64F:
+ return rewriteValueS390X_OpS390XLoweredRound64F(v)
+ case OpS390XMOVBZload:
+ return rewriteValueS390X_OpS390XMOVBZload(v)
+ case OpS390XMOVBZreg:
+ return rewriteValueS390X_OpS390XMOVBZreg(v)
+ case OpS390XMOVBload:
+ return rewriteValueS390X_OpS390XMOVBload(v)
+ case OpS390XMOVBreg:
+ return rewriteValueS390X_OpS390XMOVBreg(v)
+ case OpS390XMOVBstore:
+ return rewriteValueS390X_OpS390XMOVBstore(v)
+ case OpS390XMOVBstoreconst:
+ return rewriteValueS390X_OpS390XMOVBstoreconst(v)
+ case OpS390XMOVDaddridx:
+ return rewriteValueS390X_OpS390XMOVDaddridx(v)
+ case OpS390XMOVDload:
+ return rewriteValueS390X_OpS390XMOVDload(v)
+ case OpS390XMOVDstore:
+ return rewriteValueS390X_OpS390XMOVDstore(v)
+ case OpS390XMOVDstoreconst:
+ return rewriteValueS390X_OpS390XMOVDstoreconst(v)
+ case OpS390XMOVHBRstore:
+ return rewriteValueS390X_OpS390XMOVHBRstore(v)
+ case OpS390XMOVHZload:
+ return rewriteValueS390X_OpS390XMOVHZload(v)
+ case OpS390XMOVHZreg:
+ return rewriteValueS390X_OpS390XMOVHZreg(v)
+ case OpS390XMOVHload:
+ return rewriteValueS390X_OpS390XMOVHload(v)
+ case OpS390XMOVHreg:
+ return rewriteValueS390X_OpS390XMOVHreg(v)
+ case OpS390XMOVHstore:
+ return rewriteValueS390X_OpS390XMOVHstore(v)
+ case OpS390XMOVHstoreconst:
+ return rewriteValueS390X_OpS390XMOVHstoreconst(v)
+ case OpS390XMOVWBRstore:
+ return rewriteValueS390X_OpS390XMOVWBRstore(v)
+ case OpS390XMOVWZload:
+ return rewriteValueS390X_OpS390XMOVWZload(v)
+ case OpS390XMOVWZreg:
+ return rewriteValueS390X_OpS390XMOVWZreg(v)
+ case OpS390XMOVWload:
+ return rewriteValueS390X_OpS390XMOVWload(v)
+ case OpS390XMOVWreg:
+ return rewriteValueS390X_OpS390XMOVWreg(v)
+ case OpS390XMOVWstore:
+ return rewriteValueS390X_OpS390XMOVWstore(v)
+ case OpS390XMOVWstoreconst:
+ return rewriteValueS390X_OpS390XMOVWstoreconst(v)
+ case OpS390XMULLD:
+ return rewriteValueS390X_OpS390XMULLD(v)
+ case OpS390XMULLDconst:
+ return rewriteValueS390X_OpS390XMULLDconst(v)
+ case OpS390XMULLDload:
+ return rewriteValueS390X_OpS390XMULLDload(v)
+ case OpS390XMULLW:
+ return rewriteValueS390X_OpS390XMULLW(v)
+ case OpS390XMULLWconst:
+ return rewriteValueS390X_OpS390XMULLWconst(v)
+ case OpS390XMULLWload:
+ return rewriteValueS390X_OpS390XMULLWload(v)
+ case OpS390XNEG:
+ return rewriteValueS390X_OpS390XNEG(v)
+ case OpS390XNEGW:
+ return rewriteValueS390X_OpS390XNEGW(v)
+ case OpS390XNOT:
+ return rewriteValueS390X_OpS390XNOT(v)
+ case OpS390XNOTW:
+ return rewriteValueS390X_OpS390XNOTW(v)
+ case OpS390XOR:
+ return rewriteValueS390X_OpS390XOR(v)
+ case OpS390XORW:
+ return rewriteValueS390X_OpS390XORW(v)
+ case OpS390XORWconst:
+ return rewriteValueS390X_OpS390XORWconst(v)
+ case OpS390XORWload:
+ return rewriteValueS390X_OpS390XORWload(v)
+ case OpS390XORconst:
+ return rewriteValueS390X_OpS390XORconst(v)
+ case OpS390XORload:
+ return rewriteValueS390X_OpS390XORload(v)
+ case OpS390XRISBGZ:
+ return rewriteValueS390X_OpS390XRISBGZ(v)
+ case OpS390XRLL:
+ return rewriteValueS390X_OpS390XRLL(v)
+ case OpS390XRLLG:
+ return rewriteValueS390X_OpS390XRLLG(v)
+ case OpS390XSLD:
+ return rewriteValueS390X_OpS390XSLD(v)
+ case OpS390XSLDconst:
+ return rewriteValueS390X_OpS390XSLDconst(v)
+ case OpS390XSLW:
+ return rewriteValueS390X_OpS390XSLW(v)
+ case OpS390XSLWconst:
+ return rewriteValueS390X_OpS390XSLWconst(v)
+ case OpS390XSRAD:
+ return rewriteValueS390X_OpS390XSRAD(v)
+ case OpS390XSRADconst:
+ return rewriteValueS390X_OpS390XSRADconst(v)
+ case OpS390XSRAW:
+ return rewriteValueS390X_OpS390XSRAW(v)
+ case OpS390XSRAWconst:
+ return rewriteValueS390X_OpS390XSRAWconst(v)
+ case OpS390XSRD:
+ return rewriteValueS390X_OpS390XSRD(v)
+ case OpS390XSRDconst:
+ return rewriteValueS390X_OpS390XSRDconst(v)
+ case OpS390XSRW:
+ return rewriteValueS390X_OpS390XSRW(v)
+ case OpS390XSRWconst:
+ return rewriteValueS390X_OpS390XSRWconst(v)
+ case OpS390XSTM2:
+ return rewriteValueS390X_OpS390XSTM2(v)
+ case OpS390XSTMG2:
+ return rewriteValueS390X_OpS390XSTMG2(v)
+ case OpS390XSUB:
+ return rewriteValueS390X_OpS390XSUB(v)
+ case OpS390XSUBE:
+ return rewriteValueS390X_OpS390XSUBE(v)
+ case OpS390XSUBW:
+ return rewriteValueS390X_OpS390XSUBW(v)
+ case OpS390XSUBWconst:
+ return rewriteValueS390X_OpS390XSUBWconst(v)
+ case OpS390XSUBWload:
+ return rewriteValueS390X_OpS390XSUBWload(v)
+ case OpS390XSUBconst:
+ return rewriteValueS390X_OpS390XSUBconst(v)
+ case OpS390XSUBload:
+ return rewriteValueS390X_OpS390XSUBload(v)
+ case OpS390XSumBytes2:
+ return rewriteValueS390X_OpS390XSumBytes2(v)
+ case OpS390XSumBytes4:
+ return rewriteValueS390X_OpS390XSumBytes4(v)
+ case OpS390XSumBytes8:
+ return rewriteValueS390X_OpS390XSumBytes8(v)
+ case OpS390XXOR:
+ return rewriteValueS390X_OpS390XXOR(v)
+ case OpS390XXORW:
+ return rewriteValueS390X_OpS390XXORW(v)
+ case OpS390XXORWconst:
+ return rewriteValueS390X_OpS390XXORWconst(v)
+ case OpS390XXORWload:
+ return rewriteValueS390X_OpS390XXORWload(v)
+ case OpS390XXORconst:
+ return rewriteValueS390X_OpS390XXORconst(v)
+ case OpS390XXORload:
+ return rewriteValueS390X_OpS390XXORload(v)
+ case OpSelect0:
+ return rewriteValueS390X_OpSelect0(v)
+ case OpSelect1:
+ return rewriteValueS390X_OpSelect1(v)
+ case OpSignExt16to32:
+ v.Op = OpS390XMOVHreg
+ return true
+ case OpSignExt16to64:
+ v.Op = OpS390XMOVHreg
+ return true
+ case OpSignExt32to64:
+ v.Op = OpS390XMOVWreg
+ return true
+ case OpSignExt8to16:
+ v.Op = OpS390XMOVBreg
+ return true
+ case OpSignExt8to32:
+ v.Op = OpS390XMOVBreg
+ return true
+ case OpSignExt8to64:
+ v.Op = OpS390XMOVBreg
+ return true
+ case OpSlicemask:
+ return rewriteValueS390X_OpSlicemask(v)
+ case OpSqrt:
+ v.Op = OpS390XFSQRT
+ return true
+ case OpStaticCall:
+ v.Op = OpS390XCALLstatic
+ return true
+ case OpStore:
+ return rewriteValueS390X_OpStore(v)
+ case OpSub16:
+ v.Op = OpS390XSUBW
+ return true
+ case OpSub32:
+ v.Op = OpS390XSUBW
+ return true
+ case OpSub32F:
+ return rewriteValueS390X_OpSub32F(v)
+ case OpSub64:
+ v.Op = OpS390XSUB
+ return true
+ case OpSub64F:
+ return rewriteValueS390X_OpSub64F(v)
+ case OpSub8:
+ v.Op = OpS390XSUBW
+ return true
+ case OpSubPtr:
+ v.Op = OpS390XSUB
+ return true
+ case OpTrunc:
+ return rewriteValueS390X_OpTrunc(v)
+ case OpTrunc16to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to32:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to8:
+ v.Op = OpCopy
+ return true
+ case OpWB:
+ v.Op = OpS390XLoweredWB
+ return true
+ case OpXor16:
+ v.Op = OpS390XXORW
+ return true
+ case OpXor32:
+ v.Op = OpS390XXORW
+ return true
+ case OpXor64:
+ v.Op = OpS390XXOR
+ return true
+ case OpXor8:
+ v.Op = OpS390XXORW
+ return true
+ case OpZero:
+ return rewriteValueS390X_OpZero(v)
+ case OpZeroExt16to32:
+ v.Op = OpS390XMOVHZreg
+ return true
+ case OpZeroExt16to64:
+ v.Op = OpS390XMOVHZreg
+ return true
+ case OpZeroExt32to64:
+ v.Op = OpS390XMOVWZreg
+ return true
+ case OpZeroExt8to16:
+ v.Op = OpS390XMOVBZreg
+ return true
+ case OpZeroExt8to32:
+ v.Op = OpS390XMOVBZreg
+ return true
+ case OpZeroExt8to64:
+ v.Op = OpS390XMOVBZreg
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpAdd32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Add32F x y)
+ // result: (Select0 (FADDS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpS390XFADDS, types.NewTuple(typ.Float32, types.TypeFlags))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpAdd64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Add64F x y)
+ // result: (Select0 (FADD x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpS390XFADD, types.NewTuple(typ.Float64, types.TypeFlags))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Addr {sym} base)
+ // result: (MOVDaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpS390XMOVDaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicAdd32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicAdd32 ptr val mem)
+ // result: (AddTupleFirst32 val (LAA ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XAddTupleFirst32)
+ v0 := b.NewValue0(v.Pos, OpS390XLAA, types.NewTuple(typ.UInt32, types.TypeMem))
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg2(val, v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicAdd64(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicAdd64 ptr val mem)
+ // result: (AddTupleFirst64 val (LAAG ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XAddTupleFirst64)
+ v0 := b.NewValue0(v.Pos, OpS390XLAAG, types.NewTuple(typ.UInt64, types.TypeMem))
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg2(val, v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicAnd8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicAnd8 ptr val mem)
+ // result: (LANfloor ptr (RLL <typ.UInt32> (ORWconst <typ.UInt32> val [-1<<8]) (RXSBG <typ.UInt32> {s390x.NewRotateParams(59, 60, 3)} (MOVDconst [3<<3]) ptr)) mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XLANfloor)
+ v0 := b.NewValue0(v.Pos, OpS390XRLL, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpS390XORWconst, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(-1 << 8)
+ v1.AddArg(val)
+ v2 := b.NewValue0(v.Pos, OpS390XRXSBG, typ.UInt32)
+ v2.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(59, 60, 3))
+ v3 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(3 << 3)
+ v2.AddArg2(v3, ptr)
+ v0.AddArg2(v1, v2)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicCompareAndSwap32(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicCompareAndSwap32 ptr old new_ mem)
+ // result: (LoweredAtomicCas32 ptr old new_ mem)
+ for {
+ ptr := v_0
+ old := v_1
+ new_ := v_2
+ mem := v_3
+ v.reset(OpS390XLoweredAtomicCas32)
+ v.AddArg4(ptr, old, new_, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicCompareAndSwap64(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicCompareAndSwap64 ptr old new_ mem)
+ // result: (LoweredAtomicCas64 ptr old new_ mem)
+ for {
+ ptr := v_0
+ old := v_1
+ new_ := v_2
+ mem := v_3
+ v.reset(OpS390XLoweredAtomicCas64)
+ v.AddArg4(ptr, old, new_, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicExchange32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicExchange32 ptr val mem)
+ // result: (LoweredAtomicExchange32 ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XLoweredAtomicExchange32)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicExchange64(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicExchange64 ptr val mem)
+ // result: (LoweredAtomicExchange64 ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XLoweredAtomicExchange64)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicLoad32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoad32 ptr mem)
+ // result: (MOVWZatomicload ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVWZatomicload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicLoad64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoad64 ptr mem)
+ // result: (MOVDatomicload ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVDatomicload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicLoad8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoad8 ptr mem)
+ // result: (MOVBZatomicload ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVBZatomicload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicLoadAcq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoadAcq32 ptr mem)
+ // result: (MOVWZatomicload ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVWZatomicload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicLoadPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicLoadPtr ptr mem)
+ // result: (MOVDatomicload ptr mem)
+ for {
+ ptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVDatomicload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicOr8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AtomicOr8 ptr val mem)
+ // result: (LAOfloor ptr (SLW <typ.UInt32> (MOVBZreg <typ.UInt32> val) (RXSBG <typ.UInt32> {s390x.NewRotateParams(59, 60, 3)} (MOVDconst [3<<3]) ptr)) mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XLAOfloor)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt32)
+ v1.AddArg(val)
+ v2 := b.NewValue0(v.Pos, OpS390XRXSBG, typ.UInt32)
+ v2.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(59, 60, 3))
+ v3 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(3 << 3)
+ v2.AddArg2(v3, ptr)
+ v0.AddArg2(v1, v2)
+ v.AddArg3(ptr, v0, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicStore32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (AtomicStore32 ptr val mem)
+ // result: (SYNC (MOVWatomicstore ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XSYNC)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVWatomicstore, types.TypeMem)
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicStore64(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (AtomicStore64 ptr val mem)
+ // result: (SYNC (MOVDatomicstore ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XSYNC)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDatomicstore, types.TypeMem)
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicStore8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (AtomicStore8 ptr val mem)
+ // result: (SYNC (MOVBatomicstore ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XSYNC)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBatomicstore, types.TypeMem)
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicStorePtrNoWB(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (AtomicStorePtrNoWB ptr val mem)
+ // result: (SYNC (MOVDatomicstore ptr val mem))
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XSYNC)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDatomicstore, types.TypeMem)
+ v0.AddArg3(ptr, val, mem)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpAtomicStoreRel32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AtomicStoreRel32 ptr val mem)
+ // result: (MOVWatomicstore ptr val mem)
+ for {
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ v.reset(OpS390XMOVWatomicstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+}
+func rewriteValueS390X_OpAvg64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Avg64u <t> x y)
+ // result: (ADD (SRDconst <t> (SUB <t> x y) [1]) y)
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XADD)
+ v0 := b.NewValue0(v.Pos, OpS390XSRDconst, t)
+ v0.AuxInt = uint8ToAuxInt(1)
+ v1 := b.NewValue0(v.Pos, OpS390XSUB, t)
+ v1.AddArg2(x, y)
+ v0.AddArg(v1)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueS390X_OpBitLen64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen64 x)
+ // result: (SUB (MOVDconst [64]) (FLOGR x))
+ for {
+ x := v_0
+ v.reset(OpS390XSUB)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(64)
+ v1 := b.NewValue0(v.Pos, OpS390XFLOGR, typ.UInt64)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpCeil(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Ceil x)
+ // result: (FIDBR [6] x)
+ for {
+ x := v_0
+ v.reset(OpS390XFIDBR)
+ v.AuxInt = int8ToAuxInt(6)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueS390X_OpConst16(v *Value) bool {
+ // match: (Const16 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt16(v.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueS390X_OpConst32(v *Value) bool {
+ // match: (Const32 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt32(v.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueS390X_OpConst64(v *Value) bool {
+ // match: (Const64 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt64(v.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueS390X_OpConst8(v *Value) bool {
+ // match: (Const8 [val])
+ // result: (MOVDconst [int64(val)])
+ for {
+ val := auxIntToInt8(v.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(val))
+ return true
+ }
+}
+func rewriteValueS390X_OpConstBool(v *Value) bool {
+ // match: (ConstBool [b])
+ // result: (MOVDconst [b2i(b)])
+ for {
+ b := auxIntToBool(v.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(b2i(b))
+ return true
+ }
+}
+func rewriteValueS390X_OpConstNil(v *Value) bool {
+ // match: (ConstNil)
+ // result: (MOVDconst [0])
+ for {
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+}
+func rewriteValueS390X_OpCtz32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz32 <t> x)
+ // result: (SUB (MOVDconst [64]) (FLOGR (MOVWZreg (ANDW <t> (SUBWconst <t> [1] x) (NOTW <t> x)))))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpS390XSUB)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(64)
+ v1 := b.NewValue0(v.Pos, OpS390XFLOGR, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVWZreg, typ.UInt64)
+ v3 := b.NewValue0(v.Pos, OpS390XANDW, t)
+ v4 := b.NewValue0(v.Pos, OpS390XSUBWconst, t)
+ v4.AuxInt = int32ToAuxInt(1)
+ v4.AddArg(x)
+ v5 := b.NewValue0(v.Pos, OpS390XNOTW, t)
+ v5.AddArg(x)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpCtz64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz64 <t> x)
+ // result: (SUB (MOVDconst [64]) (FLOGR (AND <t> (SUBconst <t> [1] x) (NOT <t> x))))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpS390XSUB)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(64)
+ v1 := b.NewValue0(v.Pos, OpS390XFLOGR, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpS390XAND, t)
+ v3 := b.NewValue0(v.Pos, OpS390XSUBconst, t)
+ v3.AuxInt = int32ToAuxInt(1)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XNOT, t)
+ v4.AddArg(x)
+ v2.AddArg2(v3, v4)
+ v1.AddArg(v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpDiv16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16 x y)
+ // result: (DIVW (MOVHreg x) (MOVHreg y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XDIVW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpDiv16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16u x y)
+ // result: (DIVWU (MOVHZreg x) (MOVHZreg y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XDIVWU)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpDiv32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32 x y)
+ // result: (DIVW (MOVWreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XDIVW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVWreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueS390X_OpDiv32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32u x y)
+ // result: (DIVWU (MOVWZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XDIVWU)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVWZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueS390X_OpDiv64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Div64 x y)
+ // result: (DIVD x y)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XDIVD)
+ v.AddArg2(x, y)
+ return true
+ }
+}
+func rewriteValueS390X_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 x y)
+ // result: (DIVW (MOVBreg x) (MOVBreg y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XDIVW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u x y)
+ // result: (DIVWU (MOVBZreg x) (MOVBZreg y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XDIVWU)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq16 x y)
+ // result: (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOVHreg x) (MOVHreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Equal)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq32 x y)
+ // result: (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Equal)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpEq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq32F x y)
+ // result: (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Equal)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XFCMPS, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpEq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq64 x y)
+ // result: (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Equal)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMP, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpEq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq64F x y)
+ // result: (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Equal)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XFCMP, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq8 x y)
+ // result: (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOVBreg x) (MOVBreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Equal)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpEqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqB x y)
+ // result: (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOVBreg x) (MOVBreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Equal)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpEqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqPtr x y)
+ // result: (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Equal)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMP, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpFMA(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMA x y z)
+ // result: (FMADD z x y)
+ for {
+ x := v_0
+ y := v_1
+ z := v_2
+ v.reset(OpS390XFMADD)
+ v.AddArg3(z, x, y)
+ return true
+ }
+}
+func rewriteValueS390X_OpFloor(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Floor x)
+ // result: (FIDBR [7] x)
+ for {
+ x := v_0
+ v.reset(OpS390XFIDBR)
+ v.AuxInt = int8ToAuxInt(7)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueS390X_OpHmul32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul32 x y)
+ // result: (SRDconst [32] (MULLD (MOVWreg x) (MOVWreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRDconst)
+ v.AuxInt = uint8ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpS390XMULLD, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVWreg, typ.Int64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVWreg, typ.Int64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpHmul32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Hmul32u x y)
+ // result: (SRDconst [32] (MULLD (MOVWZreg x) (MOVWZreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRDconst)
+ v.AuxInt = uint8ToAuxInt(32)
+ v0 := b.NewValue0(v.Pos, OpS390XMULLD, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVWZreg, typ.UInt64)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVWZreg, typ.UInt64)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpITab(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ITab (Load ptr mem))
+ // result: (MOVDload ptr mem)
+ for {
+ if v_0.Op != OpLoad {
+ break
+ }
+ mem := v_0.Args[1]
+ ptr := v_0.Args[0]
+ v.reset(OpS390XMOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpIsInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (IsInBounds idx len)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPU idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPU, types.TypeFlags)
+ v2.AddArg2(idx, len)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (IsNonNil p)
+ // result: (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPconst p [0]))
+ for {
+ p := v_0
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.NotEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(0)
+ v2.AddArg(p)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpIsSliceInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (IsSliceInBounds idx len)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPU idx len))
+ for {
+ idx := v_0
+ len := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPU, types.TypeFlags)
+ v2.AddArg2(idx, len)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16 x y)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOVHreg x) (MOVHreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16U x y)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOVHZreg x) (MOVHZreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32 x y)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32F x y)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XFCMPS, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32U x y)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWU, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq64 x y)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMP, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq64F x y)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XFCMP, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLeq64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq64U x y)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPU, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8 x y)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOVBreg x) (MOVBreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8U x y)
+ // result: (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOVBZreg x) (MOVBZreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16 x y)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOVHreg x) (MOVHreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16U x y)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOVHZreg x) (MOVHZreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less32 x y)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLess32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less32F x y)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XFCMPS, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less32U x y)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWU, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLess64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less64 x y)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMP, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLess64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less64F x y)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XFCMP, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLess64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less64U x y)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPU, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8 x y)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOVBreg x) (MOVBreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8U x y)
+ // result: (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOVBZreg x) (MOVBZreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.Less)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWU, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Load <t> ptr mem)
+ // cond: (is64BitInt(t) || isPtr(t))
+ // result: (MOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitInt(t) || isPtr(t)) {
+ break
+ }
+ v.reset(OpS390XMOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitInt(t) && isSigned(t)
+ // result: (MOVWload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpS390XMOVWload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitInt(t) && !isSigned(t)
+ // result: (MOVWZload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpS390XMOVWZload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is16BitInt(t) && isSigned(t)
+ // result: (MOVHload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpS390XMOVHload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is16BitInt(t) && !isSigned(t)
+ // result: (MOVHZload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is16BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpS390XMOVHZload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is8BitInt(t) && isSigned(t)
+ // result: (MOVBload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is8BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpS390XMOVBload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: (t.IsBoolean() || (is8BitInt(t) && !isSigned(t)))
+ // result: (MOVBZload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsBoolean() || (is8BitInt(t) && !isSigned(t))) {
+ break
+ }
+ v.reset(OpS390XMOVBZload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is32BitFloat(t)
+ // result: (FMOVSload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(OpS390XFMOVSload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitFloat(t)
+ // result: (FMOVDload ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(OpS390XFMOVDload)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpLocalAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LocalAddr {sym} base _)
+ // result: (MOVDaddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpS390XMOVDaddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh16x16 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh16x32 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh16x64 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh16x8 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh32x16 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh32x32 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh32x64 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh32x8 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh64x16 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLD <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLD, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh64x32 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLD <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLD, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh64x64 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLD <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLD, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh64x8 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLD <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLD, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh8x16 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh8x32 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh8x64 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh8x8 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SLW <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSLW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpMod16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16 x y)
+ // result: (MODW (MOVHreg x) (MOVHreg y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XMODW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpMod16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16u x y)
+ // result: (MODWU (MOVHZreg x) (MOVHZreg y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XMODWU)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpMod32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32 x y)
+ // result: (MODW (MOVWreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XMODW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVWreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueS390X_OpMod32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32u x y)
+ // result: (MODWU (MOVWZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XMODWU)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVWZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueS390X_OpMod64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Mod64 x y)
+ // result: (MODD x y)
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XMODD)
+ v.AddArg2(x, y)
+ return true
+ }
+}
+func rewriteValueS390X_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8 x y)
+ // result: (MODW (MOVBreg x) (MOVBreg y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XMODW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8u x y)
+ // result: (MODWU (MOVBZreg x) (MOVBZreg y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XMODWU)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Move [0] _ _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Move [1] dst src mem)
+ // result: (MOVBstore dst (MOVBZload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpS390XMOVBstore)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZload, typ.UInt8)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] dst src mem)
+ // result: (MOVHstore dst (MOVHZload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpS390XMOVHstore)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHZload, typ.UInt16)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [4] dst src mem)
+ // result: (MOVWstore dst (MOVWZload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpS390XMOVWstore)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVWZload, typ.UInt32)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [8] dst src mem)
+ // result: (MOVDstore dst (MOVDload src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpS390XMOVDstore)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDload, typ.UInt64)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [16] dst src mem)
+ // result: (MOVDstore [8] dst (MOVDload [8] src mem) (MOVDstore dst (MOVDload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpS390XMOVDstore)
+ v.AuxInt = int32ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDload, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [24] dst src mem)
+ // result: (MOVDstore [16] dst (MOVDload [16] src mem) (MOVDstore [8] dst (MOVDload [8] src mem) (MOVDstore dst (MOVDload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpS390XMOVDstore)
+ v.AuxInt = int32ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDload, typ.UInt64)
+ v0.AuxInt = int32ToAuxInt(16)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDload, typ.UInt64)
+ v2.AuxInt = int32ToAuxInt(8)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVDstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVDload, typ.UInt64)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [3] dst src mem)
+ // result: (MOVBstore [2] dst (MOVBZload [2] src mem) (MOVHstore dst (MOVHZload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpS390XMOVBstore)
+ v.AuxInt = int32ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVHstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVHZload, typ.UInt16)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [5] dst src mem)
+ // result: (MOVBstore [4] dst (MOVBZload [4] src mem) (MOVWstore dst (MOVWZload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpS390XMOVBstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVWZload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [6] dst src mem)
+ // result: (MOVHstore [4] dst (MOVHZload [4] src mem) (MOVWstore dst (MOVWZload src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpS390XMOVHstore)
+ v.AuxInt = int32ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHZload, typ.UInt16)
+ v0.AuxInt = int32ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVWstore, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVWZload, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [7] dst src mem)
+ // result: (MOVBstore [6] dst (MOVBZload [6] src mem) (MOVHstore [4] dst (MOVHZload [4] src mem) (MOVWstore dst (MOVWZload src mem) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpS390XMOVBstore)
+ v.AuxInt = int32ToAuxInt(6)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZload, typ.UInt8)
+ v0.AuxInt = int32ToAuxInt(6)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVHstore, types.TypeMem)
+ v1.AuxInt = int32ToAuxInt(4)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVHZload, typ.UInt16)
+ v2.AuxInt = int32ToAuxInt(4)
+ v2.AddArg2(src, mem)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVWstore, types.TypeMem)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVWZload, typ.UInt32)
+ v4.AddArg2(src, mem)
+ v3.AddArg3(dst, v4, mem)
+ v1.AddArg3(dst, v2, v3)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 0 && s <= 256 && logLargeCopy(v, s)
+ // result: (MVC [makeValAndOff32(int32(s), 0)] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 0 && s <= 256 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpS390XMVC)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(s), 0))
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 256 && s <= 512 && logLargeCopy(v, s)
+ // result: (MVC [makeValAndOff32(int32(s)-256, 256)] dst src (MVC [makeValAndOff32(256, 0)] dst src mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 256 && s <= 512 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpS390XMVC)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(s)-256, 256))
+ v0 := b.NewValue0(v.Pos, OpS390XMVC, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(256, 0))
+ v0.AddArg3(dst, src, mem)
+ v.AddArg3(dst, src, v0)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 512 && s <= 768 && logLargeCopy(v, s)
+ // result: (MVC [makeValAndOff32(int32(s)-512, 512)] dst src (MVC [makeValAndOff32(256, 256)] dst src (MVC [makeValAndOff32(256, 0)] dst src mem)))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 512 && s <= 768 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpS390XMVC)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(s)-512, 512))
+ v0 := b.NewValue0(v.Pos, OpS390XMVC, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(256, 256))
+ v1 := b.NewValue0(v.Pos, OpS390XMVC, types.TypeMem)
+ v1.AuxInt = valAndOffToAuxInt(makeValAndOff32(256, 0))
+ v1.AddArg3(dst, src, mem)
+ v0.AddArg3(dst, src, v1)
+ v.AddArg3(dst, src, v0)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 768 && s <= 1024 && logLargeCopy(v, s)
+ // result: (MVC [makeValAndOff32(int32(s)-768, 768)] dst src (MVC [makeValAndOff32(256, 512)] dst src (MVC [makeValAndOff32(256, 256)] dst src (MVC [makeValAndOff32(256, 0)] dst src mem))))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 768 && s <= 1024 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpS390XMVC)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(s)-768, 768))
+ v0 := b.NewValue0(v.Pos, OpS390XMVC, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(makeValAndOff32(256, 512))
+ v1 := b.NewValue0(v.Pos, OpS390XMVC, types.TypeMem)
+ v1.AuxInt = valAndOffToAuxInt(makeValAndOff32(256, 256))
+ v2 := b.NewValue0(v.Pos, OpS390XMVC, types.TypeMem)
+ v2.AuxInt = valAndOffToAuxInt(makeValAndOff32(256, 0))
+ v2.AddArg3(dst, src, mem)
+ v1.AddArg3(dst, src, v2)
+ v0.AddArg3(dst, src, v1)
+ v.AddArg3(dst, src, v0)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 1024 && logLargeCopy(v, s)
+ // result: (LoweredMove [s%256] dst src (ADD <src.Type> src (MOVDconst [(s/256)*256])) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 1024 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpS390XLoweredMove)
+ v.AuxInt = int64ToAuxInt(s % 256)
+ v0 := b.NewValue0(v.Pos, OpS390XADD, src.Type)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt((s / 256) * 256)
+ v0.AddArg2(src, v1)
+ v.AddArg4(dst, src, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq16 x y)
+ // result: (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOVHreg x) (MOVHreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.NotEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq32 x y)
+ // result: (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.NotEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpNeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq32F x y)
+ // result: (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.NotEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XFCMPS, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpNeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq64 x y)
+ // result: (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.NotEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMP, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpNeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq64F x y)
+ // result: (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.NotEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XFCMP, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq8 x y)
+ // result: (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOVBreg x) (MOVBreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.NotEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpNeqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (NeqB x y)
+ // result: (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOVBreg x) (MOVBreg y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.NotEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v4.AddArg(y)
+ v2.AddArg2(v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpNeqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (NeqPtr x y)
+ // result: (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(s390x.NotEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(1)
+ v2 := b.NewValue0(v.Pos, OpS390XCMP, types.TypeFlags)
+ v2.AddArg2(x, y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpNot(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Not x)
+ // result: (XORWconst [1] x)
+ for {
+ x := v_0
+ v.reset(OpS390XXORWconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueS390X_OpOffPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (OffPtr [off] ptr:(SP))
+ // result: (MOVDaddr [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ if ptr.Op != OpSP {
+ break
+ }
+ v.reset(OpS390XMOVDaddr)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (OffPtr [off] ptr)
+ // cond: is32Bit(off)
+ // result: (ADDconst [int32(off)] ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ if !(is32Bit(off)) {
+ break
+ }
+ v.reset(OpS390XADDconst)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(ptr)
+ return true
+ }
+ // match: (OffPtr [off] ptr)
+ // result: (ADD (MOVDconst [off]) ptr)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ ptr := v_0
+ v.reset(OpS390XADD)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(off)
+ v.AddArg2(v0, ptr)
+ return true
+ }
+}
+func rewriteValueS390X_OpPanicBounds(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 0
+ // result: (LoweredPanicBoundsA [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 0) {
+ break
+ }
+ v.reset(OpS390XLoweredPanicBoundsA)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 1
+ // result: (LoweredPanicBoundsB [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 1) {
+ break
+ }
+ v.reset(OpS390XLoweredPanicBoundsB)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ // match: (PanicBounds [kind] x y mem)
+ // cond: boundsABI(kind) == 2
+ // result: (LoweredPanicBoundsC [kind] x y mem)
+ for {
+ kind := auxIntToInt64(v.AuxInt)
+ x := v_0
+ y := v_1
+ mem := v_2
+ if !(boundsABI(kind) == 2) {
+ break
+ }
+ v.reset(OpS390XLoweredPanicBoundsC)
+ v.AuxInt = int64ToAuxInt(kind)
+ v.AddArg3(x, y, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpPopCount16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount16 x)
+ // result: (MOVBZreg (SumBytes2 (POPCNT <typ.UInt16> x)))
+ for {
+ x := v_0
+ v.reset(OpS390XMOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpS390XSumBytes2, typ.UInt8)
+ v1 := b.NewValue0(v.Pos, OpS390XPOPCNT, typ.UInt16)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpPopCount32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount32 x)
+ // result: (MOVBZreg (SumBytes4 (POPCNT <typ.UInt32> x)))
+ for {
+ x := v_0
+ v.reset(OpS390XMOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpS390XSumBytes4, typ.UInt8)
+ v1 := b.NewValue0(v.Pos, OpS390XPOPCNT, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpPopCount64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount64 x)
+ // result: (MOVBZreg (SumBytes8 (POPCNT <typ.UInt64> x)))
+ for {
+ x := v_0
+ v.reset(OpS390XMOVBZreg)
+ v0 := b.NewValue0(v.Pos, OpS390XSumBytes8, typ.UInt8)
+ v1 := b.NewValue0(v.Pos, OpS390XPOPCNT, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpPopCount8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount8 x)
+ // result: (POPCNT (MOVBZreg x))
+ for {
+ x := v_0
+ v.reset(OpS390XPOPCNT)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpRotateLeft16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft16 <t> x (MOVDconst [c]))
+ // result: (Or16 (Lsh16x64 <t> x (MOVDconst [c&15])) (Rsh16Ux64 <t> x (MOVDconst [-c&15])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpLsh16x64, t)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c & 15)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh16Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(-c & 15)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpRotateLeft8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft8 <t> x (MOVDconst [c]))
+ // result: (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpLsh8x64, t)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(c & 7)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh8Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(-c & 7)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpRound(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Round x)
+ // result: (FIDBR [1] x)
+ for {
+ x := v_0
+ v.reset(OpS390XFIDBR)
+ v.AuxInt = int8ToAuxInt(1)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueS390X_OpRoundToEven(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (RoundToEven x)
+ // result: (FIDBR [4] x)
+ for {
+ x := v_0
+ v.reset(OpS390XFIDBR)
+ v.AuxInt = int8ToAuxInt(4)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16Ux16 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOVHZreg x) y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16Ux32 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOVHZreg x) y) (MOVDconst [0]) (CMPWUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v3.AddArg(y)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16Ux64 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOVHZreg x) y) (MOVDconst [0]) (CMPUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v3.AddArg(y)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16Ux8 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOVHZreg x) y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16x16 x y)
+ // result: (SRAW (MOVHreg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVHZreg y) [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v1.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16x32 x y)
+ // result: (SRAW (MOVHreg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst y [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v1.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v3.AddArg(y)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16x64 x y)
+ // result: (SRAW (MOVHreg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPUconst y [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v1.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v3.AddArg(y)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh16x8 x y)
+ // result: (SRAW (MOVHreg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVBZreg y) [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v1.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32Ux16 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32Ux32 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32Ux64 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32Ux8 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32x16 x y)
+ // result: (SRAW x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVHZreg y) [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v0.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v1.AuxInt = int64ToAuxInt(63)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32x32 x y)
+ // result: (SRAW x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst y [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v0.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v1.AuxInt = int64ToAuxInt(63)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32x64 x y)
+ // result: (SRAW x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPUconst y [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v0.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v1.AuxInt = int64ToAuxInt(63)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh32x8 x y)
+ // result: (SRAW x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVBZreg y) [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v0.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v1.AuxInt = int64ToAuxInt(63)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh64Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64Ux16 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRD <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRD, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh64Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64Ux32 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRD <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRD, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh64Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64Ux64 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRD <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRD, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh64Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64Ux8 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRD <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRD, t)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64x16 x y)
+ // result: (SRAD x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVHZreg y) [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAD)
+ v0 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v0.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v1.AuxInt = int64ToAuxInt(63)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64x32 x y)
+ // result: (SRAD x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst y [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAD)
+ v0 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v0.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v1.AuxInt = int64ToAuxInt(63)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64x64 x y)
+ // result: (SRAD x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPUconst y [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAD)
+ v0 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v0.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v1.AuxInt = int64ToAuxInt(63)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v2.AddArg(y)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64x8 x y)
+ // result: (SRAD x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVBZreg y) [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAD)
+ v0 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v0.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v1.AuxInt = int64ToAuxInt(63)
+ v2 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v2.AuxInt = int32ToAuxInt(64)
+ v3 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v3.AddArg(y)
+ v2.AddArg(v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8Ux16 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOVBZreg x) y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8Ux32 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOVBZreg x) y) (MOVDconst [0]) (CMPWUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v3.AddArg(y)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8Ux64 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOVBZreg x) y) (MOVDconst [0]) (CMPUconst y [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v3.AddArg(y)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8Ux8 <t> x y)
+ // result: (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOVBZreg x) y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
+ for {
+ t := v.Type
+ x := v_0
+ y := v_1
+ v.reset(OpS390XLOCGR)
+ v.Type = t
+ v.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v0 := b.NewValue0(v.Pos, OpS390XSRW, t)
+ v1 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v1.AddArg(x)
+ v0.AddArg2(v1, y)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v.AddArg3(v0, v2, v3)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8x16 x y)
+ // result: (SRAW (MOVBreg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVHZreg y) [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v1.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8x32 x y)
+ // result: (SRAW (MOVBreg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst y [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v1.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v3.AddArg(y)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8x64 x y)
+ // result: (SRAW (MOVBreg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPUconst y [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v1.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v3.AddArg(y)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+ // match: (Rsh8x8 x y)
+ // result: (SRAW (MOVBreg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVBZreg y) [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XLOCGR, y.Type)
+ v1.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, y.Type)
+ v2.AuxInt = int64ToAuxInt(63)
+ v3 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v3.AuxInt = int32ToAuxInt(64)
+ v4 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.UInt64)
+ v4.AddArg(y)
+ v3.AddArg(v4)
+ v1.AddArg3(y, v2, v3)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueS390X_OpS390XADD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADD x (MOVDconst [c]))
+ // cond: is32Bit(c)
+ // result: (ADDconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpS390XADDconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADD (SLDconst x [c]) (SRDconst x [64-c]))
+ // result: (RISBGZ x {s390x.NewRotateParams(0, 63, c)})
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XSLDconst {
+ continue
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpS390XSRDconst || auxIntToUint8(v_1.AuxInt) != 64-c || x != v_1.Args[0] {
+ continue
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(0, 63, c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADD idx (MOVDaddr [c] {s} ptr))
+ // cond: ptr.Op != OpSB
+ // result: (MOVDaddridx [c] {s} ptr idx)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ idx := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ s := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ if !(ptr.Op != OpSB) {
+ continue
+ }
+ v.reset(OpS390XMOVDaddridx)
+ v.AuxInt = int32ToAuxInt(c)
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, idx)
+ return true
+ }
+ break
+ }
+ // match: (ADD x (NEG y))
+ // result: (SUB x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XNEG {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSUB)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADD <t> x g:(MOVDload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (ADDload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVDload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XADDload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XADDC(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDC x (MOVDconst [c]))
+ // cond: is16Bit(c)
+ // result: (ADDCconst x [int16(c)])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is16Bit(c)) {
+ continue
+ }
+ v.reset(OpS390XADDCconst)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XADDE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDE x y (FlagEQ))
+ // result: (ADDC x y)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpS390XFlagEQ {
+ break
+ }
+ v.reset(OpS390XADDC)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDE x y (FlagLT))
+ // result: (ADDC x y)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpS390XFlagLT {
+ break
+ }
+ v.reset(OpS390XADDC)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDE x y (Select1 (ADDCconst [-1] (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) c)))))
+ // result: (ADDE x y c)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpSelect1 {
+ break
+ }
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpS390XADDCconst || auxIntToInt16(v_2_0.AuxInt) != -1 {
+ break
+ }
+ v_2_0_0 := v_2_0.Args[0]
+ if v_2_0_0.Op != OpSelect0 {
+ break
+ }
+ v_2_0_0_0 := v_2_0_0.Args[0]
+ if v_2_0_0_0.Op != OpS390XADDE {
+ break
+ }
+ c := v_2_0_0_0.Args[2]
+ v_2_0_0_0_0 := v_2_0_0_0.Args[0]
+ if v_2_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_2_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_2_0_0_0_1 := v_2_0_0_0.Args[1]
+ if v_2_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_2_0_0_0_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpS390XADDE)
+ v.AddArg3(x, y, c)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XADDW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDW x (MOVDconst [c]))
+ // result: (ADDWconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XADDWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDW (SLWconst x [c]) (SRWconst x [32-c]))
+ // result: (RLLconst x [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XSLWconst {
+ continue
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpS390XSRWconst || auxIntToUint8(v_1.AuxInt) != 32-c || x != v_1.Args[0] {
+ continue
+ }
+ v.reset(OpS390XRLLconst)
+ v.AuxInt = uint8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ADDW x (NEGW y))
+ // result: (SUBW x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XNEGW {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSUBW)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (ADDW <t> x g:(MOVWload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (ADDWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XADDWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (ADDW <t> x g:(MOVWZload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (ADDWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWZload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XADDWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XADDWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDWconst [c] x)
+ // cond: int32(c)==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(int32(c) == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ADDWconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [int64(c)+d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c) + d)
+ return true
+ }
+ // match: (ADDWconst [c] (ADDWconst [d] x))
+ // result: (ADDWconst [int32(c+d)] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XADDWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpS390XADDWconst)
+ v.AuxInt = int32ToAuxInt(int32(c + d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XADDWload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ADDWload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (ADDWload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XADDWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (ADDWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (ADDWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XADDWload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XADDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ADDconst [c] (MOVDaddr [d] {s} x:(SB)))
+ // cond: ((c+d)&1 == 0) && is32Bit(int64(c)+int64(d))
+ // result: (MOVDaddr [c+d] {s} x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ if x.Op != OpSB || !(((c+d)&1 == 0) && is32Bit(int64(c)+int64(d))) {
+ break
+ }
+ v.reset(OpS390XMOVDaddr)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [c] (MOVDaddr [d] {s} x))
+ // cond: x.Op != OpSB && is20Bit(int64(c)+int64(d))
+ // result: (MOVDaddr [c+d] {s} x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ if !(x.Op != OpSB && is20Bit(int64(c)+int64(d))) {
+ break
+ }
+ v.reset(OpS390XMOVDaddr)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ADDconst [c] (MOVDaddridx [d] {s} x y))
+ // cond: is20Bit(int64(c)+int64(d))
+ // result: (MOVDaddridx [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDaddridx {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ s := auxToSym(v_0.Aux)
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ if !(is20Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpS390XMOVDaddridx)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (ADDconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ADDconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [int64(c)+d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c) + d)
+ return true
+ }
+ // match: (ADDconst [c] (ADDconst [d] x))
+ // cond: is32Bit(int64(c)+int64(d))
+ // result: (ADDconst [c+d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpS390XADDconst)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XADDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ADDload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (ADD x (LGDR <t> y))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr1 := v_1
+ if v_2.Op != OpS390XFMOVDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XADD)
+ v0 := b.NewValue0(v_2.Pos, OpS390XLGDR, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (ADDload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (ADDload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XADDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (ADDload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (ADDload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XADDload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XAND(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (AND x (MOVDconst [c]))
+ // cond: s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c)) != nil
+ // result: (RISBGZ x {*s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c))})
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c)) != nil) {
+ continue
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(*s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c)))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND x (MOVDconst [c]))
+ // cond: is32Bit(c) && c < 0
+ // result: (ANDconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c) && c < 0) {
+ continue
+ }
+ v.reset(OpS390XANDconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (AND x (MOVDconst [c]))
+ // cond: is32Bit(c) && c >= 0
+ // result: (MOVWZreg (ANDWconst <typ.UInt32> [int32(c)] x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c) && c >= 0) {
+ continue
+ }
+ v.reset(OpS390XMOVWZreg)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (AND (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [c&d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(c & d)
+ return true
+ }
+ break
+ }
+ // match: (AND x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (AND <t> x g:(MOVDload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (ANDload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVDload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XANDload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XANDW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ANDW x (MOVDconst [c]))
+ // result: (ANDWconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XANDWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ANDW x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDW <t> x g:(MOVWload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (ANDWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XANDWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (ANDW <t> x g:(MOVWZload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (ANDWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWZload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XANDWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XANDWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ANDWconst [c] (ANDWconst [d] x))
+ // result: (ANDWconst [c&d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XANDWconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpS390XANDWconst)
+ v.AuxInt = int32ToAuxInt(c & d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDWconst [0x00ff] x)
+ // result: (MOVBZreg x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0x00ff {
+ break
+ }
+ x := v_0
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDWconst [0xffff] x)
+ // result: (MOVHZreg x)
+ for {
+ if auxIntToInt32(v.AuxInt) != 0xffff {
+ break
+ }
+ x := v_0
+ v.reset(OpS390XMOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDWconst [c] _)
+ // cond: int32(c)==0
+ // result: (MOVDconst [0])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if !(int32(c) == 0) {
+ break
+ }
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ANDWconst [c] x)
+ // cond: int32(c)==-1
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(int32(c) == -1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDWconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [int64(c)&d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c) & d)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XANDWload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ANDWload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (ANDWload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XANDWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (ANDWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (ANDWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XANDWload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XANDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ANDconst [c] (ANDconst [d] x))
+ // result: (ANDconst [c&d] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpS390XANDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpS390XANDconst)
+ v.AuxInt = int64ToAuxInt(c & d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (ANDconst [0] _)
+ // result: (MOVDconst [0])
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (ANDconst [-1] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != -1 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ANDconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [c&d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(c & d)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XANDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ANDload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (AND x (LGDR <t> y))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr1 := v_1
+ if v_2.Op != OpS390XFMOVDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XAND)
+ v0 := b.NewValue0(v_2.Pos, OpS390XLGDR, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (ANDload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (ANDload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XANDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (ANDload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (ANDload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XANDload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XCMP(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMP x (MOVDconst [c]))
+ // cond: is32Bit(c)
+ // result: (CMPconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpS390XCMPconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMP (MOVDconst [c]) x)
+ // cond: is32Bit(c)
+ // result: (InvertFlags (CMPconst x [int32(c)]))
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpS390XInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpS390XCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMP x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMP y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpS390XInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpS390XCMP, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XCMPU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPU x (MOVDconst [c]))
+ // cond: isU32Bit(c)
+ // result: (CMPUconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isU32Bit(c)) {
+ break
+ }
+ v.reset(OpS390XCMPUconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPU (MOVDconst [c]) x)
+ // cond: isU32Bit(c)
+ // result: (InvertFlags (CMPUconst x [int32(c)]))
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(isU32Bit(c)) {
+ break
+ }
+ v.reset(OpS390XInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPU x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPU y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpS390XInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpS390XCMPU, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XCMPUconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPUconst (MOVDconst [x]) [y])
+ // cond: uint64(x)==uint64(y)
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(uint64(x) == uint64(y)) {
+ break
+ }
+ v.reset(OpS390XFlagEQ)
+ return true
+ }
+ // match: (CMPUconst (MOVDconst [x]) [y])
+ // cond: uint64(x)<uint64(y)
+ // result: (FlagLT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(uint64(x) < uint64(y)) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPUconst (MOVDconst [x]) [y])
+ // cond: uint64(x)>uint64(y)
+ // result: (FlagGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(uint64(x) > uint64(y)) {
+ break
+ }
+ v.reset(OpS390XFlagGT)
+ return true
+ }
+ // match: (CMPUconst (SRDconst _ [c]) [n])
+ // cond: c > 0 && c < 64 && (1<<uint(64-c)) <= uint64(n)
+ // result: (FlagLT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XSRDconst {
+ break
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ if !(c > 0 && c < 64 && (1<<uint(64-c)) <= uint64(n)) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPUconst (RISBGZ x {r}) [c])
+ // cond: r.OutMask() < uint64(uint32(c))
+ // result: (FlagLT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_0.Aux)
+ if !(r.OutMask() < uint64(uint32(c))) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPUconst (MOVWZreg x) [c])
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPUconst x:(MOVHreg _) [c])
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpS390XMOVHreg {
+ break
+ }
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPUconst x:(MOVHZreg _) [c])
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpS390XMOVHZreg {
+ break
+ }
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPUconst x:(MOVBreg _) [c])
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpS390XMOVBreg {
+ break
+ }
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPUconst x:(MOVBZreg _) [c])
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpS390XMOVBZreg {
+ break
+ }
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPUconst (MOVWZreg x:(ANDWconst [m] _)) [c])
+ // cond: int32(m) >= 0
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpS390XANDWconst {
+ break
+ }
+ m := auxIntToInt32(x.AuxInt)
+ if !(int32(m) >= 0) {
+ break
+ }
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPUconst (MOVWreg x:(ANDWconst [m] _)) [c])
+ // cond: int32(m) >= 0
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpS390XANDWconst {
+ break
+ }
+ m := auxIntToInt32(x.AuxInt)
+ if !(int32(m) >= 0) {
+ break
+ }
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XCMPW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPW x (MOVDconst [c]))
+ // result: (CMPWconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XCMPWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPW (MOVDconst [c]) x)
+ // result: (InvertFlags (CMPWconst x [int32(c)]))
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpS390XInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpS390XCMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPW x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPW y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpS390XInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpS390XCMPW, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPW x (MOVWreg y))
+ // result: (CMPW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XCMPW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPW x (MOVWZreg y))
+ // result: (CMPW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XCMPW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPW (MOVWreg x) y)
+ // result: (CMPW x y)
+ for {
+ if v_0.Op != OpS390XMOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpS390XCMPW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPW (MOVWZreg x) y)
+ // result: (CMPW x y)
+ for {
+ if v_0.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpS390XCMPW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XCMPWU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (CMPWU x (MOVDconst [c]))
+ // result: (CMPWUconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPWU (MOVDconst [c]) x)
+ // result: (InvertFlags (CMPWUconst x [int32(c)]))
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpS390XInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPWU x y)
+ // cond: x.ID > y.ID
+ // result: (InvertFlags (CMPWU y x))
+ for {
+ x := v_0
+ y := v_1
+ if !(x.ID > y.ID) {
+ break
+ }
+ v.reset(OpS390XInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpS390XCMPWU, types.TypeFlags)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMPWU x (MOVWreg y))
+ // result: (CMPWU x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XCMPWU)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPWU x (MOVWZreg y))
+ // result: (CMPWU x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XCMPWU)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPWU (MOVWreg x) y)
+ // result: (CMPWU x y)
+ for {
+ if v_0.Op != OpS390XMOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpS390XCMPWU)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (CMPWU (MOVWZreg x) y)
+ // result: (CMPWU x y)
+ for {
+ if v_0.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := v_0.Args[0]
+ y := v_1
+ v.reset(OpS390XCMPWU)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XCMPWUconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPWUconst (MOVDconst [x]) [y])
+ // cond: uint32(x)==uint32(y)
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(uint32(x) == uint32(y)) {
+ break
+ }
+ v.reset(OpS390XFlagEQ)
+ return true
+ }
+ // match: (CMPWUconst (MOVDconst [x]) [y])
+ // cond: uint32(x)<uint32(y)
+ // result: (FlagLT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(uint32(x) < uint32(y)) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPWUconst (MOVDconst [x]) [y])
+ // cond: uint32(x)>uint32(y)
+ // result: (FlagGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(uint32(x) > uint32(y)) {
+ break
+ }
+ v.reset(OpS390XFlagGT)
+ return true
+ }
+ // match: (CMPWUconst (MOVBZreg _) [c])
+ // cond: 0xff < c
+ // result: (FlagLT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVBZreg || !(0xff < c) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPWUconst (MOVHZreg _) [c])
+ // cond: 0xffff < c
+ // result: (FlagLT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVHZreg || !(0xffff < c) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPWUconst (SRWconst _ [c]) [n])
+ // cond: c > 0 && c < 32 && (1<<uint(32-c)) <= uint32(n)
+ // result: (FlagLT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XSRWconst {
+ break
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ if !(c > 0 && c < 32 && (1<<uint(32-c)) <= uint32(n)) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPWUconst (ANDWconst _ [m]) [n])
+ // cond: uint32(m) < uint32(n)
+ // result: (FlagLT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XANDWconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(uint32(m) < uint32(n)) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPWUconst (MOVWreg x) [c])
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPWUconst (MOVWZreg x) [c])
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XCMPWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPWconst (MOVDconst [x]) [y])
+ // cond: int32(x)==int32(y)
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(int32(x) == int32(y)) {
+ break
+ }
+ v.reset(OpS390XFlagEQ)
+ return true
+ }
+ // match: (CMPWconst (MOVDconst [x]) [y])
+ // cond: int32(x)<int32(y)
+ // result: (FlagLT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(int32(x) < int32(y)) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPWconst (MOVDconst [x]) [y])
+ // cond: int32(x)>int32(y)
+ // result: (FlagGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(int32(x) > int32(y)) {
+ break
+ }
+ v.reset(OpS390XFlagGT)
+ return true
+ }
+ // match: (CMPWconst (MOVBZreg _) [c])
+ // cond: 0xff < c
+ // result: (FlagLT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVBZreg || !(0xff < c) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPWconst (MOVHZreg _) [c])
+ // cond: 0xffff < c
+ // result: (FlagLT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVHZreg || !(0xffff < c) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPWconst (SRWconst _ [c]) [n])
+ // cond: c > 0 && n < 0
+ // result: (FlagGT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XSRWconst {
+ break
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ if !(c > 0 && n < 0) {
+ break
+ }
+ v.reset(OpS390XFlagGT)
+ return true
+ }
+ // match: (CMPWconst (ANDWconst _ [m]) [n])
+ // cond: int32(m) >= 0 && int32(m) < int32(n)
+ // result: (FlagLT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XANDWconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if !(int32(m) >= 0 && int32(m) < int32(n)) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPWconst x:(SRWconst _ [c]) [n])
+ // cond: c > 0 && n >= 0
+ // result: (CMPWUconst x [n])
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpS390XSRWconst {
+ break
+ }
+ c := auxIntToUint8(x.AuxInt)
+ if !(c > 0 && n >= 0) {
+ break
+ }
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(n)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPWconst (MOVWreg x) [c])
+ // result: (CMPWconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpS390XCMPWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPWconst (MOVWZreg x) [c])
+ // result: (CMPWconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpS390XCMPWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XCMPconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CMPconst (MOVDconst [x]) [y])
+ // cond: x==int64(y)
+ // result: (FlagEQ)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x == int64(y)) {
+ break
+ }
+ v.reset(OpS390XFlagEQ)
+ return true
+ }
+ // match: (CMPconst (MOVDconst [x]) [y])
+ // cond: x<int64(y)
+ // result: (FlagLT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x < int64(y)) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPconst (MOVDconst [x]) [y])
+ // cond: x>int64(y)
+ // result: (FlagGT)
+ for {
+ y := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x > int64(y)) {
+ break
+ }
+ v.reset(OpS390XFlagGT)
+ return true
+ }
+ // match: (CMPconst (SRDconst _ [c]) [n])
+ // cond: c > 0 && n < 0
+ // result: (FlagGT)
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XSRDconst {
+ break
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ if !(c > 0 && n < 0) {
+ break
+ }
+ v.reset(OpS390XFlagGT)
+ return true
+ }
+ // match: (CMPconst (RISBGZ x {r}) [c])
+ // cond: c > 0 && r.OutMask() < uint64(c)
+ // result: (FlagLT)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_0.Aux)
+ if !(c > 0 && r.OutMask() < uint64(c)) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (CMPconst (MOVWreg x) [c])
+ // result: (CMPWconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpS390XCMPWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPconst x:(MOVHreg _) [c])
+ // result: (CMPWconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpS390XMOVHreg {
+ break
+ }
+ v.reset(OpS390XCMPWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPconst x:(MOVHZreg _) [c])
+ // result: (CMPWconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpS390XMOVHZreg {
+ break
+ }
+ v.reset(OpS390XCMPWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPconst x:(MOVBreg _) [c])
+ // result: (CMPWconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpS390XMOVBreg {
+ break
+ }
+ v.reset(OpS390XCMPWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPconst x:(MOVBZreg _) [c])
+ // result: (CMPWconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpS390XMOVBZreg {
+ break
+ }
+ v.reset(OpS390XCMPWconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPconst (MOVWZreg x:(ANDWconst [m] _)) [c])
+ // cond: int32(m) >= 0 && c >= 0
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpS390XANDWconst {
+ break
+ }
+ m := auxIntToInt32(x.AuxInt)
+ if !(int32(m) >= 0 && c >= 0) {
+ break
+ }
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPconst (MOVWreg x:(ANDWconst [m] _)) [c])
+ // cond: int32(m) >= 0 && c >= 0
+ // result: (CMPWUconst x [c])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpS390XANDWconst {
+ break
+ }
+ m := auxIntToInt32(x.AuxInt)
+ if !(int32(m) >= 0 && c >= 0) {
+ break
+ }
+ v.reset(OpS390XCMPWUconst)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMPconst x:(SRDconst _ [c]) [n])
+ // cond: c > 0 && n >= 0
+ // result: (CMPUconst x [n])
+ for {
+ n := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpS390XSRDconst {
+ break
+ }
+ c := auxIntToUint8(x.AuxInt)
+ if !(c > 0 && n >= 0) {
+ break
+ }
+ v.reset(OpS390XCMPUconst)
+ v.AuxInt = int32ToAuxInt(n)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XCPSDR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (CPSDR y (FMOVDconst [c]))
+ // cond: !math.Signbit(c)
+ // result: (LPDFR y)
+ for {
+ y := v_0
+ if v_1.Op != OpS390XFMOVDconst {
+ break
+ }
+ c := auxIntToFloat64(v_1.AuxInt)
+ if !(!math.Signbit(c)) {
+ break
+ }
+ v.reset(OpS390XLPDFR)
+ v.AddArg(y)
+ return true
+ }
+ // match: (CPSDR y (FMOVDconst [c]))
+ // cond: math.Signbit(c)
+ // result: (LNDFR y)
+ for {
+ y := v_0
+ if v_1.Op != OpS390XFMOVDconst {
+ break
+ }
+ c := auxIntToFloat64(v_1.AuxInt)
+ if !(math.Signbit(c)) {
+ break
+ }
+ v.reset(OpS390XLNDFR)
+ v.AddArg(y)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XFCMP(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (FCMP x (FMOVDconst [0.0]))
+ // result: (LTDBR x)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XFMOVDconst || auxIntToFloat64(v_1.AuxInt) != 0.0 {
+ break
+ }
+ v.reset(OpS390XLTDBR)
+ v.AddArg(x)
+ return true
+ }
+ // match: (FCMP (FMOVDconst [0.0]) x)
+ // result: (InvertFlags (LTDBR <v.Type> x))
+ for {
+ if v_0.Op != OpS390XFMOVDconst || auxIntToFloat64(v_0.AuxInt) != 0.0 {
+ break
+ }
+ x := v_1
+ v.reset(OpS390XInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpS390XLTDBR, v.Type)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XFCMPS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (FCMPS x (FMOVSconst [0.0]))
+ // result: (LTEBR x)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XFMOVSconst || auxIntToFloat32(v_1.AuxInt) != 0.0 {
+ break
+ }
+ v.reset(OpS390XLTEBR)
+ v.AddArg(x)
+ return true
+ }
+ // match: (FCMPS (FMOVSconst [0.0]) x)
+ // result: (InvertFlags (LTEBR <v.Type> x))
+ for {
+ if v_0.Op != OpS390XFMOVSconst || auxIntToFloat32(v_0.AuxInt) != 0.0 {
+ break
+ }
+ x := v_1
+ v.reset(OpS390XInvertFlags)
+ v0 := b.NewValue0(v.Pos, OpS390XLTEBR, v.Type)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XFMOVDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVDload [off] {sym} ptr1 (MOVDstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (LDGR x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XMOVDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XLDGR)
+ v.AddArg(x)
+ return true
+ }
+ // match: (FMOVDload [off] {sym} ptr1 (FMOVDstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XFMOVDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (FMOVDload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XFMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpS390XFMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XFMOVDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (FMOVDstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XFMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpS390XFMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XFMOVSload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVSload [off] {sym} ptr1 (FMOVSstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XFMOVSstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (FMOVSload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XFMOVSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpS390XFMOVSload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XFMOVSstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (FMOVSstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XFMOVSstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpS390XFMOVSstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XFNEG(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (FNEG (LPDFR x))
+ // result: (LNDFR x)
+ for {
+ if v_0.Op != OpS390XLPDFR {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpS390XLNDFR)
+ v.AddArg(x)
+ return true
+ }
+ // match: (FNEG (LNDFR x))
+ // result: (LPDFR x)
+ for {
+ if v_0.Op != OpS390XLNDFR {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpS390XLPDFR)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XFNEGS(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (FNEGS (LPDFR x))
+ // result: (LNDFR x)
+ for {
+ if v_0.Op != OpS390XLPDFR {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpS390XLNDFR)
+ v.AddArg(x)
+ return true
+ }
+ // match: (FNEGS (LNDFR x))
+ // result: (LPDFR x)
+ for {
+ if v_0.Op != OpS390XLNDFR {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpS390XLPDFR)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XLDGR(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (LDGR <t> (RISBGZ x {r}))
+ // cond: r == s390x.NewRotateParams(1, 63, 0)
+ // result: (LPDFR (LDGR <t> x))
+ for {
+ t := v.Type
+ if v_0.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_0.Aux)
+ x := v_0.Args[0]
+ if !(r == s390x.NewRotateParams(1, 63, 0)) {
+ break
+ }
+ v.reset(OpS390XLPDFR)
+ v0 := b.NewValue0(v.Pos, OpS390XLDGR, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (LDGR <t> (OR (MOVDconst [-1<<63]) x))
+ // result: (LNDFR (LDGR <t> x))
+ for {
+ t := v.Type
+ if v_0.Op != OpS390XOR {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0.AuxInt) != -1<<63 {
+ continue
+ }
+ x := v_0_1
+ v.reset(OpS390XLNDFR)
+ v0 := b.NewValue0(v.Pos, OpS390XLDGR, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (LDGR <t> x:(ORload <t1> [off] {sym} (MOVDconst [-1<<63]) ptr mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (LNDFR <t> (LDGR <t> (MOVDload <t1> [off] {sym} ptr mem)))
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpS390XORload {
+ break
+ }
+ t1 := x.Type
+ off := auxIntToInt32(x.AuxInt)
+ sym := auxToSym(x.Aux)
+ mem := x.Args[2]
+ x_0 := x.Args[0]
+ if x_0.Op != OpS390XMOVDconst || auxIntToInt64(x_0.AuxInt) != -1<<63 {
+ break
+ }
+ ptr := x.Args[1]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpS390XLNDFR, t)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x.Pos, OpS390XLDGR, t)
+ v2 := b.NewValue0(x.Pos, OpS390XMOVDload, t1)
+ v2.AuxInt = int32ToAuxInt(off)
+ v2.Aux = symToAux(sym)
+ v2.AddArg2(ptr, mem)
+ v1.AddArg(v2)
+ v0.AddArg(v1)
+ return true
+ }
+ // match: (LDGR (LGDR x))
+ // result: x
+ for {
+ if v_0.Op != OpS390XLGDR {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XLEDBR(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LEDBR (LPDFR (LDEBR x)))
+ // result: (LPDFR x)
+ for {
+ if v_0.Op != OpS390XLPDFR {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XLDEBR {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpS390XLPDFR)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LEDBR (LNDFR (LDEBR x)))
+ // result: (LNDFR x)
+ for {
+ if v_0.Op != OpS390XLNDFR {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XLDEBR {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpS390XLNDFR)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XLGDR(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LGDR (LDGR x))
+ // result: x
+ for {
+ if v_0.Op != OpS390XLDGR {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XLOCGR(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (LOCGR {c} x y (InvertFlags cmp))
+ // result: (LOCGR {c.ReverseComparison()} x y cmp)
+ for {
+ c := auxToS390xCCMask(v.Aux)
+ x := v_0
+ y := v_1
+ if v_2.Op != OpS390XInvertFlags {
+ break
+ }
+ cmp := v_2.Args[0]
+ v.reset(OpS390XLOCGR)
+ v.Aux = s390xCCMaskToAux(c.ReverseComparison())
+ v.AddArg3(x, y, cmp)
+ return true
+ }
+ // match: (LOCGR {c} _ x (FlagEQ))
+ // cond: c&s390x.Equal != 0
+ // result: x
+ for {
+ c := auxToS390xCCMask(v.Aux)
+ x := v_1
+ if v_2.Op != OpS390XFlagEQ || !(c&s390x.Equal != 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (LOCGR {c} _ x (FlagLT))
+ // cond: c&s390x.Less != 0
+ // result: x
+ for {
+ c := auxToS390xCCMask(v.Aux)
+ x := v_1
+ if v_2.Op != OpS390XFlagLT || !(c&s390x.Less != 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (LOCGR {c} _ x (FlagGT))
+ // cond: c&s390x.Greater != 0
+ // result: x
+ for {
+ c := auxToS390xCCMask(v.Aux)
+ x := v_1
+ if v_2.Op != OpS390XFlagGT || !(c&s390x.Greater != 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (LOCGR {c} _ x (FlagOV))
+ // cond: c&s390x.Unordered != 0
+ // result: x
+ for {
+ c := auxToS390xCCMask(v.Aux)
+ x := v_1
+ if v_2.Op != OpS390XFlagOV || !(c&s390x.Unordered != 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (LOCGR {c} x _ (FlagEQ))
+ // cond: c&s390x.Equal == 0
+ // result: x
+ for {
+ c := auxToS390xCCMask(v.Aux)
+ x := v_0
+ if v_2.Op != OpS390XFlagEQ || !(c&s390x.Equal == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (LOCGR {c} x _ (FlagLT))
+ // cond: c&s390x.Less == 0
+ // result: x
+ for {
+ c := auxToS390xCCMask(v.Aux)
+ x := v_0
+ if v_2.Op != OpS390XFlagLT || !(c&s390x.Less == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (LOCGR {c} x _ (FlagGT))
+ // cond: c&s390x.Greater == 0
+ // result: x
+ for {
+ c := auxToS390xCCMask(v.Aux)
+ x := v_0
+ if v_2.Op != OpS390XFlagGT || !(c&s390x.Greater == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (LOCGR {c} x _ (FlagOV))
+ // cond: c&s390x.Unordered == 0
+ // result: x
+ for {
+ c := auxToS390xCCMask(v.Aux)
+ x := v_0
+ if v_2.Op != OpS390XFlagOV || !(c&s390x.Unordered == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XLTDBR(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (LTDBR (Select0 x:(FADD _ _)))
+ // cond: b == x.Block
+ // result: (Select1 x)
+ for {
+ if v_0.Op != OpSelect0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpS390XFADD || !(b == x.Block) {
+ break
+ }
+ v.reset(OpSelect1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LTDBR (Select0 x:(FSUB _ _)))
+ // cond: b == x.Block
+ // result: (Select1 x)
+ for {
+ if v_0.Op != OpSelect0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpS390XFSUB || !(b == x.Block) {
+ break
+ }
+ v.reset(OpSelect1)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XLTEBR(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (LTEBR (Select0 x:(FADDS _ _)))
+ // cond: b == x.Block
+ // result: (Select1 x)
+ for {
+ if v_0.Op != OpSelect0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpS390XFADDS || !(b == x.Block) {
+ break
+ }
+ v.reset(OpSelect1)
+ v.AddArg(x)
+ return true
+ }
+ // match: (LTEBR (Select0 x:(FSUBS _ _)))
+ // cond: b == x.Block
+ // result: (Select1 x)
+ for {
+ if v_0.Op != OpSelect0 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpS390XFSUBS || !(b == x.Block) {
+ break
+ }
+ v.reset(OpSelect1)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XLoweredRound32F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LoweredRound32F x:(FMOVSconst))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XFMOVSconst {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XLoweredRound64F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LoweredRound64F x:(FMOVDconst))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XFMOVDconst {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVBZload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBZload [off] {sym} ptr1 (MOVBstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (MOVBZreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XMOVBstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVBZload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVBZload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBZload [off1] {sym1} (MOVDaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVBZload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpS390XMOVBZload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVBZreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVBZreg e:(MOVBreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVBreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg e:(MOVHreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVHreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg e:(MOVWreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg e:(MOVBZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVBZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg e:(MOVHZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVHZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg e:(MOVWZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg x:(MOVBZload _ _))
+ // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVBZload || !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVBZreg <t> x:(MOVBload [o] {s} p mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBZload <t> [o] {s} p mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpS390XMOVBload {
+ break
+ }
+ o := auxIntToInt32(x.AuxInt)
+ s := auxToSym(x.Aux)
+ mem := x.Args[1]
+ p := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpS390XMOVBZload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(o)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVBZreg x:(Arg <t>))
+ // cond: !t.IsSigned() && t.Size() == 1
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !(!t.IsSigned() && t.Size() == 1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVBZreg (MOVDconst [c]))
+ // result: (MOVDconst [int64( uint8(c))])
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ return true
+ }
+ // match: (MOVBZreg x:(LOCGR (MOVDconst [c]) (MOVDconst [d]) _))
+ // cond: int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XLOCGR {
+ break
+ }
+ _ = x.Args[1]
+ x_0 := x.Args[0]
+ if x_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(x_0.AuxInt)
+ x_1 := x.Args[1]
+ if x_1.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(x_1.AuxInt)
+ if !(int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVBZreg (RISBGZ x {r}))
+ // cond: r.OutMerge(0x000000ff) != nil
+ // result: (RISBGZ x {*r.OutMerge(0x000000ff)})
+ for {
+ if v_0.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_0.Aux)
+ x := v_0.Args[0]
+ if !(r.OutMerge(0x000000ff) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(*r.OutMerge(0x000000ff))
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg (ANDWconst [m] x))
+ // result: (MOVWZreg (ANDWconst <typ.UInt32> [int32( uint8(m))] x))
+ for {
+ if v_0.Op != OpS390XANDWconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpS390XMOVWZreg)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(uint8(m)))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVBload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBload [off] {sym} ptr1 (MOVBstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (MOVBreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XMOVBstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVBload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpS390XMOVBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVBreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVBreg e:(MOVBreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVBreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg e:(MOVHreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVHreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg e:(MOVWreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg e:(MOVBZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVBZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg e:(MOVHZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVHZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg e:(MOVWZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg x:(MOVBload _ _))
+ // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVBload || !(x.Type.IsSigned() || x.Type.Size() == 8) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVBreg <t> x:(MOVBZload [o] {s} p mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVBload <t> [o] {s} p mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpS390XMOVBZload {
+ break
+ }
+ o := auxIntToInt32(x.AuxInt)
+ s := auxToSym(x.Aux)
+ mem := x.Args[1]
+ p := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpS390XMOVBload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(o)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVBreg x:(Arg <t>))
+ // cond: t.IsSigned() && t.Size() == 1
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !(t.IsSigned() && t.Size() == 1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVBreg (MOVDconst [c]))
+ // result: (MOVDconst [int64( int8(c))])
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int8(c)))
+ return true
+ }
+ // match: (MOVBreg (ANDWconst [m] x))
+ // cond: int8(m) >= 0
+ // result: (MOVWZreg (ANDWconst <typ.UInt32> [int32( uint8(m))] x))
+ for {
+ if v_0.Op != OpS390XANDWconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(int8(m) >= 0) {
+ break
+ }
+ v.reset(OpS390XMOVWZreg)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(uint8(m)))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVBstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstore [off] {sym} ptr (MOVBreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpS390XMOVBreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpS390XMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVBZreg x) mem)
+ // result: (MOVBstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpS390XMOVBZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpS390XMOVBstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVBstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVBstore [off] {sym} ptr (MOVDconst [c]) mem)
+ // cond: is20Bit(int64(off)) && ptr.Op != OpSB
+ // result: (MOVBstoreconst [makeValAndOff32(int32(int8(c)),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is20Bit(int64(off)) && ptr.Op != OpSB) {
+ break
+ }
+ v.reset(OpS390XMOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(int8(c)), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)
+ // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpS390XMOVBstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w x:(MOVBstore [i-1] {s} p (SRDconst [8] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVHstore [i-1] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpS390XMOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpS390XSRDconst || auxIntToUint8(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w0:(SRDconst [j] w) x:(MOVBstore [i-1] {s} p (SRDconst [j+8] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVHstore [i-1] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w0 := v_1
+ if w0.Op != OpS390XSRDconst {
+ break
+ }
+ j := auxIntToUint8(w0.AuxInt)
+ w := w0.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpS390XSRDconst || auxIntToUint8(x_1.AuxInt) != j+8 || w != x_1.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w x:(MOVBstore [i-1] {s} p (SRWconst [8] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVHstore [i-1] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpS390XMOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpS390XSRWconst || auxIntToUint8(x_1.AuxInt) != 8 || w != x_1.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p w0:(SRWconst [j] w) x:(MOVBstore [i-1] {s} p (SRWconst [j+8] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVHstore [i-1] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w0 := v_1
+ if w0.Op != OpS390XSRWconst {
+ break
+ }
+ j := auxIntToUint8(w0.AuxInt)
+ w := w0.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpS390XSRWconst || auxIntToUint8(x_1.AuxInt) != j+8 || w != x_1.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVHstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SRDconst [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVHBRstore [i-1] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRDconst || auxIntToUint8(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVHBRstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SRDconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SRDconst [j-8] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVHBRstore [i-1] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRDconst {
+ break
+ }
+ j := auxIntToUint8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != OpS390XSRDconst || auxIntToUint8(w0.AuxInt) != j-8 || w != w0.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVHBRstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SRWconst [8] w) x:(MOVBstore [i-1] {s} p w mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVHBRstore [i-1] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRWconst || auxIntToUint8(v_1.AuxInt) != 8 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVHBRstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVBstore [i] {s} p (SRWconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SRWconst [j-8] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVHBRstore [i-1] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRWconst {
+ break
+ }
+ j := auxIntToUint8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVBstore || auxIntToInt32(x.AuxInt) != i-1 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != OpS390XSRWconst || auxIntToUint8(w0.AuxInt) != j-8 || w != w0.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVHBRstore)
+ v.AuxInt = int32ToAuxInt(i - 1)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVBstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVBstoreconst [sc] {s} (ADDconst [off] ptr) mem)
+ // cond: is20Bit(sc.Off()+int64(off))
+ // result: (MOVBstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is20Bit(sc.Off() + int64(off))) {
+ break
+ }
+ v.reset(OpS390XMOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
+ // cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off)
+ // result: (MOVBstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpS390XMOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && a.Off() + 1 == c.Off() && clobber(x)
+ // result: (MOVHstoreconst [makeValAndOff32(c.Val32()&0xff | a.Val32()<<8, a.Off32())] {s} p mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != OpS390XMOVBstoreconst {
+ break
+ }
+ a := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(p.Op != OpSB && x.Uses == 1 && a.Off()+1 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVHstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(c.Val32()&0xff|a.Val32()<<8, a.Off32()))
+ v.Aux = symToAux(s)
+ v.AddArg2(p, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVDaddridx(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDaddridx [c] {s} (ADDconst [d] x) y)
+ // cond: is20Bit(int64(c)+int64(d))
+ // result: (MOVDaddridx [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is20Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpS390XMOVDaddridx)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (MOVDaddridx [c] {s} x (ADDconst [d] y))
+ // cond: is20Bit(int64(c)+int64(d))
+ // result: (MOVDaddridx [c+d] {s} x y)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(is20Bit(int64(c) + int64(d))) {
+ break
+ }
+ v.reset(OpS390XMOVDaddridx)
+ v.AuxInt = int32ToAuxInt(c + d)
+ v.Aux = symToAux(s)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (MOVDaddridx [off1] {sym1} (MOVDaddr [off2] {sym2} x) y)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB
+ // result: (MOVDaddridx [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ x := v_0.Args[0]
+ y := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB) {
+ break
+ }
+ v.reset(OpS390XMOVDaddridx)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (MOVDaddridx [off1] {sym1} x (MOVDaddr [off2] {sym2} y))
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && y.Op != OpSB
+ // result: (MOVDaddridx [off1+off2] {mergeSym(sym1,sym2)} x y)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ sym2 := auxToSym(v_1.Aux)
+ y := v_1.Args[0]
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && y.Op != OpSB) {
+ break
+ }
+ v.reset(OpS390XMOVDaddridx)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVDload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDload [off] {sym} ptr1 (MOVDstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: x
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XMOVDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVDload [off] {sym} ptr1 (FMOVDstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (LGDR x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XFMOVDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XLGDR)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVDload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDload [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%8 == 0 && (off1+off2)%8 == 0))
+ // result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ t := v_0.Type
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%8 == 0 && (off1+off2)%8 == 0))) {
+ break
+ }
+ v.reset(OpS390XMOVDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVDstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVDstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVDstore [off] {sym} ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c) && isU12Bit(int64(off)) && ptr.Op != OpSB
+ // result: (MOVDstoreconst [makeValAndOff32(int32(c),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is16Bit(c) && isU12Bit(int64(off)) && ptr.Op != OpSB) {
+ break
+ }
+ v.reset(OpS390XMOVDstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDstore [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%8 == 0 && (off1+off2)%8 == 0))
+ // result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ t := v_0.Type
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%8 == 0 && (off1+off2)%8 == 0))) {
+ break
+ }
+ v.reset(OpS390XMOVDstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVDstore [i] {s} p w1 x:(MOVDstore [i-8] {s} p w0 mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && is20Bit(int64(i)-8) && clobber(x)
+ // result: (STMG2 [i-8] {s} p w0 w1 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w1 := v_1
+ x := v_2
+ if x.Op != OpS390XMOVDstore || auxIntToInt32(x.AuxInt) != i-8 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if !(p.Op != OpSB && x.Uses == 1 && is20Bit(int64(i)-8) && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XSTMG2)
+ v.AuxInt = int32ToAuxInt(i - 8)
+ v.Aux = symToAux(s)
+ v.AddArg4(p, w0, w1, mem)
+ return true
+ }
+ // match: (MOVDstore [i] {s} p w2 x:(STMG2 [i-16] {s} p w0 w1 mem))
+ // cond: x.Uses == 1 && is20Bit(int64(i)-16) && clobber(x)
+ // result: (STMG3 [i-16] {s} p w0 w1 w2 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w2 := v_1
+ x := v_2
+ if x.Op != OpS390XSTMG2 || auxIntToInt32(x.AuxInt) != i-16 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[3]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ w1 := x.Args[2]
+ if !(x.Uses == 1 && is20Bit(int64(i)-16) && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XSTMG3)
+ v.AuxInt = int32ToAuxInt(i - 16)
+ v.Aux = symToAux(s)
+ v.AddArg5(p, w0, w1, w2, mem)
+ return true
+ }
+ // match: (MOVDstore [i] {s} p w3 x:(STMG3 [i-24] {s} p w0 w1 w2 mem))
+ // cond: x.Uses == 1 && is20Bit(int64(i)-24) && clobber(x)
+ // result: (STMG4 [i-24] {s} p w0 w1 w2 w3 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w3 := v_1
+ x := v_2
+ if x.Op != OpS390XSTMG3 || auxIntToInt32(x.AuxInt) != i-24 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[4]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ w1 := x.Args[2]
+ w2 := x.Args[3]
+ if !(x.Uses == 1 && is20Bit(int64(i)-24) && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XSTMG4)
+ v.AuxInt = int32ToAuxInt(i - 24)
+ v.Aux = symToAux(s)
+ v.AddArg6(p, w0, w1, w2, w3, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVDstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVDstoreconst [sc] {s} (ADDconst [off] ptr) mem)
+ // cond: isU12Bit(sc.Off()+int64(off))
+ // result: (MOVDstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(isU12Bit(sc.Off() + int64(off))) {
+ break
+ }
+ v.reset(OpS390XMOVDstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVDstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
+ // cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off)
+ // result: (MOVDstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpS390XMOVDstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVHBRstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHBRstore [i] {s} p (SRDconst [16] w) x:(MOVHBRstore [i-2] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWBRstore [i-2] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRDconst || auxIntToUint8(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVHBRstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVWBRstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVHBRstore [i] {s} p (SRDconst [j] w) x:(MOVHBRstore [i-2] {s} p w0:(SRDconst [j-16] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWBRstore [i-2] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRDconst {
+ break
+ }
+ j := auxIntToUint8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVHBRstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != OpS390XSRDconst || auxIntToUint8(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVWBRstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVHBRstore [i] {s} p (SRWconst [16] w) x:(MOVHBRstore [i-2] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWBRstore [i-2] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRWconst || auxIntToUint8(v_1.AuxInt) != 16 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVHBRstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVWBRstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVHBRstore [i] {s} p (SRWconst [j] w) x:(MOVHBRstore [i-2] {s} p w0:(SRWconst [j-16] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVWBRstore [i-2] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRWconst {
+ break
+ }
+ j := auxIntToUint8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVHBRstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != OpS390XSRWconst || auxIntToUint8(w0.AuxInt) != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVWBRstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVHZload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHZload [off] {sym} ptr1 (MOVHstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (MOVHZreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XMOVHstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XMOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVHZload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVHZload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHZload [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%2 == 0 && (off1+off2)%2 == 0))
+ // result: (MOVHZload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ t := v_0.Type
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%2 == 0 && (off1+off2)%2 == 0))) {
+ break
+ }
+ v.reset(OpS390XMOVHZload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVHZreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVHZreg e:(MOVBZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVBZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg e:(MOVHreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVHZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVHreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg e:(MOVWreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVHZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg e:(MOVHZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVHZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVHZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg e:(MOVWZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVHZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg x:(MOVBZload _ _))
+ // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVBZload || !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHZreg x:(MOVHZload _ _))
+ // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVHZload || !(!x.Type.IsSigned() || x.Type.Size() > 2) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHZreg <t> x:(MOVHload [o] {s} p mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVHZload <t> [o] {s} p mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpS390XMOVHload {
+ break
+ }
+ o := auxIntToInt32(x.AuxInt)
+ s := auxToSym(x.Aux)
+ mem := x.Args[1]
+ p := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpS390XMOVHZload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(o)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVHZreg x:(Arg <t>))
+ // cond: !t.IsSigned() && t.Size() <= 2
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !(!t.IsSigned() && t.Size() <= 2) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHZreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(uint16(c))])
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ return true
+ }
+ // match: (MOVHZreg (RISBGZ x {r}))
+ // cond: r.OutMerge(0x0000ffff) != nil
+ // result: (RISBGZ x {*r.OutMerge(0x0000ffff)})
+ for {
+ if v_0.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_0.Aux)
+ x := v_0.Args[0]
+ if !(r.OutMerge(0x0000ffff) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(*r.OutMerge(0x0000ffff))
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg (ANDWconst [m] x))
+ // result: (MOVWZreg (ANDWconst <typ.UInt32> [int32(uint16(m))] x))
+ for {
+ if v_0.Op != OpS390XANDWconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpS390XMOVWZreg)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(uint16(m)))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVHload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHload [off] {sym} ptr1 (MOVHstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (MOVHreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XMOVHstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XMOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVHload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHload [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%2 == 0 && (off1+off2)%2 == 0))
+ // result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ t := v_0.Type
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%2 == 0 && (off1+off2)%2 == 0))) {
+ break
+ }
+ v.reset(OpS390XMOVHload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVHreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVHreg e:(MOVBreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVBreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg e:(MOVHreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVHreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVHreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg e:(MOVWreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVHreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg e:(MOVHZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVHreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVHZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg e:(MOVWZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVHreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBload _ _))
+ // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVBload || !(x.Type.IsSigned() || x.Type.Size() == 8) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVHload _ _))
+ // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVHload || !(x.Type.IsSigned() || x.Type.Size() == 8) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHreg x:(MOVBZload _ _))
+ // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVBZload || !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHreg <t> x:(MOVHZload [o] {s} p mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVHload <t> [o] {s} p mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpS390XMOVHZload {
+ break
+ }
+ o := auxIntToInt32(x.AuxInt)
+ s := auxToSym(x.Aux)
+ mem := x.Args[1]
+ p := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpS390XMOVHload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(o)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVHreg x:(Arg <t>))
+ // cond: t.IsSigned() && t.Size() <= 2
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !(t.IsSigned() && t.Size() <= 2) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVHreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(int16(c))])
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int16(c)))
+ return true
+ }
+ // match: (MOVHreg (ANDWconst [m] x))
+ // cond: int16(m) >= 0
+ // result: (MOVWZreg (ANDWconst <typ.UInt32> [int32(uint16(m))] x))
+ for {
+ if v_0.Op != OpS390XANDWconst {
+ break
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(int16(m) >= 0) {
+ break
+ }
+ v.reset(OpS390XMOVWZreg)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(uint16(m)))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVHstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVHstore [off] {sym} ptr (MOVHreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpS390XMOVHreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpS390XMOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVHZreg x) mem)
+ // result: (MOVHstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpS390XMOVHZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpS390XMOVHstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVHstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVHstore [off] {sym} ptr (MOVDconst [c]) mem)
+ // cond: isU12Bit(int64(off)) && ptr.Op != OpSB
+ // result: (MOVHstoreconst [makeValAndOff32(int32(int16(c)),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(isU12Bit(int64(off)) && ptr.Op != OpSB) {
+ break
+ }
+ v.reset(OpS390XMOVHstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(int16(c)), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstore [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%2 == 0 && (off1+off2)%2 == 0))
+ // result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ t := v_0.Type
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%2 == 0 && (off1+off2)%2 == 0))) {
+ break
+ }
+ v.reset(OpS390XMOVHstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVHstore [i] {s} p w x:(MOVHstore [i-2] {s} p (SRDconst [16] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-2] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpS390XMOVHstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpS390XSRDconst || auxIntToUint8(x_1.AuxInt) != 16 || w != x_1.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVHstore [i] {s} p w0:(SRDconst [j] w) x:(MOVHstore [i-2] {s} p (SRDconst [j+16] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-2] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w0 := v_1
+ if w0.Op != OpS390XSRDconst {
+ break
+ }
+ j := auxIntToUint8(w0.AuxInt)
+ w := w0.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVHstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpS390XSRDconst || auxIntToUint8(x_1.AuxInt) != j+16 || w != x_1.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVHstore [i] {s} p w x:(MOVHstore [i-2] {s} p (SRWconst [16] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-2] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w := v_1
+ x := v_2
+ if x.Op != OpS390XMOVHstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpS390XSRWconst || auxIntToUint8(x_1.AuxInt) != 16 || w != x_1.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVHstore [i] {s} p w0:(SRWconst [j] w) x:(MOVHstore [i-2] {s} p (SRWconst [j+16] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVWstore [i-2] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w0 := v_1
+ if w0.Op != OpS390XSRWconst {
+ break
+ }
+ j := auxIntToUint8(w0.AuxInt)
+ w := w0.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVHstore || auxIntToInt32(x.AuxInt) != i-2 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpS390XSRWconst || auxIntToUint8(x_1.AuxInt) != j+16 || w != x_1.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVWstore)
+ v.AuxInt = int32ToAuxInt(i - 2)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVHstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVHstoreconst [sc] {s} (ADDconst [off] ptr) mem)
+ // cond: isU12Bit(sc.Off()+int64(off))
+ // result: (MOVHstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(isU12Bit(sc.Off() + int64(off))) {
+ break
+ }
+ v.reset(OpS390XMOVHstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
+ // cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off)
+ // result: (MOVHstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpS390XMOVHstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVHstoreconst [c] {s} p x:(MOVHstoreconst [a] {s} p mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && a.Off() + 2 == c.Off() && clobber(x)
+ // result: (MOVWstore [a.Off32()] {s} p (MOVDconst [int64(c.Val32()&0xffff | a.Val32()<<16)]) mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != OpS390XMOVHstoreconst {
+ break
+ }
+ a := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(p.Op != OpSB && x.Uses == 1 && a.Off()+2 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVWstore)
+ v.AuxInt = int32ToAuxInt(a.Off32())
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(int64(c.Val32()&0xffff | a.Val32()<<16))
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVWBRstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWBRstore [i] {s} p (SRDconst [32] w) x:(MOVWBRstore [i-4] {s} p w mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVDBRstore [i-4] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRDconst || auxIntToUint8(v_1.AuxInt) != 32 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVWBRstore || auxIntToInt32(x.AuxInt) != i-4 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVDBRstore)
+ v.AuxInt = int32ToAuxInt(i - 4)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVWBRstore [i] {s} p (SRDconst [j] w) x:(MOVWBRstore [i-4] {s} p w0:(SRDconst [j-32] w) mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: (MOVDBRstore [i-4] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRDconst {
+ break
+ }
+ j := auxIntToUint8(v_1.AuxInt)
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVWBRstore || auxIntToInt32(x.AuxInt) != i-4 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if w0.Op != OpS390XSRDconst || auxIntToUint8(w0.AuxInt) != j-32 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVDBRstore)
+ v.AuxInt = int32ToAuxInt(i - 4)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVWZload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWZload [off] {sym} ptr1 (MOVWstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (MOVWZreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XMOVWstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XMOVWZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVWZload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVWZload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWZload [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%4 == 0 && (off1+off2)%4 == 0))
+ // result: (MOVWZload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ t := v_0.Type
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%4 == 0 && (off1+off2)%4 == 0))) {
+ break
+ }
+ v.reset(OpS390XMOVWZload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVWZreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVWZreg e:(MOVBZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVBZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg e:(MOVHZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVHZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVHZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg e:(MOVWreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVWZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVWZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg e:(MOVWZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVWZreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVWZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVBZload _ _))
+ // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVBZload || !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVHZload _ _))
+ // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVHZload || !(!x.Type.IsSigned() || x.Type.Size() > 2) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVWZload _ _))
+ // cond: (!x.Type.IsSigned() || x.Type.Size() > 4)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVWZload || !(!x.Type.IsSigned() || x.Type.Size() > 4) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg <t> x:(MOVWload [o] {s} p mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWZload <t> [o] {s} p mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpS390XMOVWload {
+ break
+ }
+ o := auxIntToInt32(x.AuxInt)
+ s := auxToSym(x.Aux)
+ mem := x.Args[1]
+ p := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpS390XMOVWZload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(o)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVWZreg x:(Arg <t>))
+ // cond: !t.IsSigned() && t.Size() <= 4
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !(!t.IsSigned() && t.Size() <= 4) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWZreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(uint32(c))])
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ return true
+ }
+ // match: (MOVWZreg (RISBGZ x {r}))
+ // cond: r.OutMerge(0xffffffff) != nil
+ // result: (RISBGZ x {*r.OutMerge(0xffffffff)})
+ for {
+ if v_0.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_0.Aux)
+ x := v_0.Args[0]
+ if !(r.OutMerge(0xffffffff) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(*r.OutMerge(0xffffffff))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVWload(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWload [off] {sym} ptr1 (MOVWstore [off] {sym} ptr2 x _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (MOVWreg x)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr1 := v_0
+ if v_1.Op != OpS390XMOVWstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
+ break
+ }
+ x := v_1.Args[1]
+ ptr2 := v_1.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWload [off1] {sym} (ADDconst [off2] ptr) mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVWload [off1+off2] {sym} ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWload [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%4 == 0 && (off1+off2)%4 == 0))
+ // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ t := v_0.Type
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ mem := v_1
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%4 == 0 && (off1+off2)%4 == 0))) {
+ break
+ }
+ v.reset(OpS390XMOVWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(base, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVWreg(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MOVWreg e:(MOVBreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVBreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVBreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVBreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg e:(MOVHreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVHreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVHreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVHreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg e:(MOVWreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVWreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg e:(MOVWZreg x))
+ // cond: clobberIfDead(e)
+ // result: (MOVWreg x)
+ for {
+ e := v_0
+ if e.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := e.Args[0]
+ if !(clobberIfDead(e)) {
+ break
+ }
+ v.reset(OpS390XMOVWreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBload _ _))
+ // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVBload || !(x.Type.IsSigned() || x.Type.Size() == 8) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHload _ _))
+ // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVHload || !(x.Type.IsSigned() || x.Type.Size() == 8) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWload _ _))
+ // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVWload || !(x.Type.IsSigned() || x.Type.Size() == 8) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVBZload _ _))
+ // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVBZload || !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHZload _ _))
+ // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpS390XMOVHZload || !(!x.Type.IsSigned() || x.Type.Size() > 2) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg <t> x:(MOVWZload [o] {s} p mem))
+ // cond: x.Uses == 1 && clobber(x)
+ // result: @x.Block (MOVWload <t> [o] {s} p mem)
+ for {
+ t := v.Type
+ x := v_0
+ if x.Op != OpS390XMOVWZload {
+ break
+ }
+ o := auxIntToInt32(x.AuxInt)
+ s := auxToSym(x.Aux)
+ mem := x.Args[1]
+ p := x.Args[0]
+ if !(x.Uses == 1 && clobber(x)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(x.Pos, OpS390XMOVWload, t)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(o)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ // match: (MOVWreg x:(Arg <t>))
+ // cond: t.IsSigned() && t.Size() <= 4
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !(t.IsSigned() && t.Size() <= 4) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (MOVWreg (MOVDconst [c]))
+ // result: (MOVDconst [int64(int32(c))])
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVWstore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MOVWstore [off] {sym} ptr (MOVWreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpS390XMOVWreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpS390XMOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVWZreg x) mem)
+ // result: (MOVWstore [off] {sym} ptr x mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := v_1.Args[0]
+ mem := v_2
+ v.reset(OpS390XMOVWstore)
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, x, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem)
+ // cond: is20Bit(int64(off1)+int64(off2))
+ // result: (MOVWstore [off1+off2] {sym} ptr val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is20Bit(int64(off1) + int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (MOVWstore [off] {sym} ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c) && isU12Bit(int64(off)) && ptr.Op != OpSB
+ // result: (MOVWstoreconst [makeValAndOff32(int32(c),off)] {sym} ptr mem)
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ ptr := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ mem := v_2
+ if !(is16Bit(c) && isU12Bit(int64(off)) && ptr.Op != OpSB) {
+ break
+ }
+ v.reset(OpS390XMOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(c), off))
+ v.Aux = symToAux(sym)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstore [off1] {sym1} (MOVDaddr <t> [off2] {sym2} base) val mem)
+ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%4 == 0 && (off1+off2)%4 == 0))
+ // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ t := v_0.Type
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || (t.IsPtr() && t.Elem().Alignment()%4 == 0 && (off1+off2)%4 == 0))) {
+ break
+ }
+ v.reset(OpS390XMOVWstore)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg3(base, val, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p (SRDconst [32] w) x:(MOVWstore [i-4] {s} p w mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVDstore [i-4] {s} p w mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRDconst || auxIntToUint8(v_1.AuxInt) != 32 {
+ break
+ }
+ w := v_1.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVWstore || auxIntToInt32(x.AuxInt) != i-4 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] || w != x.Args[1] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVDstore)
+ v.AuxInt = int32ToAuxInt(i - 4)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p w0:(SRDconst [j] w) x:(MOVWstore [i-4] {s} p (SRDconst [j+32] w) mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && clobber(x)
+ // result: (MOVDstore [i-4] {s} p w0 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w0 := v_1
+ if w0.Op != OpS390XSRDconst {
+ break
+ }
+ j := auxIntToUint8(w0.AuxInt)
+ w := w0.Args[0]
+ x := v_2
+ if x.Op != OpS390XMOVWstore || auxIntToInt32(x.AuxInt) != i-4 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ x_1 := x.Args[1]
+ if x_1.Op != OpS390XSRDconst || auxIntToUint8(x_1.AuxInt) != j+32 || w != x_1.Args[0] || !(p.Op != OpSB && x.Uses == 1 && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVDstore)
+ v.AuxInt = int32ToAuxInt(i - 4)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, w0, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p w1 x:(MOVWstore [i-4] {s} p w0 mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && is20Bit(int64(i)-4) && clobber(x)
+ // result: (STM2 [i-4] {s} p w0 w1 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w1 := v_1
+ x := v_2
+ if x.Op != OpS390XMOVWstore || auxIntToInt32(x.AuxInt) != i-4 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[2]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ if !(p.Op != OpSB && x.Uses == 1 && is20Bit(int64(i)-4) && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XSTM2)
+ v.AuxInt = int32ToAuxInt(i - 4)
+ v.Aux = symToAux(s)
+ v.AddArg4(p, w0, w1, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p w2 x:(STM2 [i-8] {s} p w0 w1 mem))
+ // cond: x.Uses == 1 && is20Bit(int64(i)-8) && clobber(x)
+ // result: (STM3 [i-8] {s} p w0 w1 w2 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w2 := v_1
+ x := v_2
+ if x.Op != OpS390XSTM2 || auxIntToInt32(x.AuxInt) != i-8 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[3]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ w1 := x.Args[2]
+ if !(x.Uses == 1 && is20Bit(int64(i)-8) && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XSTM3)
+ v.AuxInt = int32ToAuxInt(i - 8)
+ v.Aux = symToAux(s)
+ v.AddArg5(p, w0, w1, w2, mem)
+ return true
+ }
+ // match: (MOVWstore [i] {s} p w3 x:(STM3 [i-12] {s} p w0 w1 w2 mem))
+ // cond: x.Uses == 1 && is20Bit(int64(i)-12) && clobber(x)
+ // result: (STM4 [i-12] {s} p w0 w1 w2 w3 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w3 := v_1
+ x := v_2
+ if x.Op != OpS390XSTM3 || auxIntToInt32(x.AuxInt) != i-12 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[4]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ w1 := x.Args[2]
+ w2 := x.Args[3]
+ if !(x.Uses == 1 && is20Bit(int64(i)-12) && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XSTM4)
+ v.AuxInt = int32ToAuxInt(i - 12)
+ v.Aux = symToAux(s)
+ v.AddArg6(p, w0, w1, w2, w3, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMOVWstoreconst(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (MOVWstoreconst [sc] {s} (ADDconst [off] ptr) mem)
+ // cond: isU12Bit(sc.Off()+int64(off))
+ // result: (MOVWstoreconst [sc.addOffset32(off)] {s} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(isU12Bit(sc.Off() + int64(off))) {
+ break
+ }
+ v.reset(OpS390XMOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(s)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
+ // cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off)
+ // result: (MOVWstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem)
+ for {
+ sc := auxIntToValAndOff(v.AuxInt)
+ sym1 := auxToSym(v.Aux)
+ if v_0.Op != OpS390XMOVDaddr {
+ break
+ }
+ off := auxIntToInt32(v_0.AuxInt)
+ sym2 := auxToSym(v_0.Aux)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && sc.canAdd32(off)) {
+ break
+ }
+ v.reset(OpS390XMOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off))
+ v.Aux = symToAux(mergeSym(sym1, sym2))
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem))
+ // cond: p.Op != OpSB && x.Uses == 1 && a.Off() + 4 == c.Off() && clobber(x)
+ // result: (MOVDstore [a.Off32()] {s} p (MOVDconst [c.Val()&0xffffffff | a.Val()<<32]) mem)
+ for {
+ c := auxIntToValAndOff(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ x := v_1
+ if x.Op != OpS390XMOVWstoreconst {
+ break
+ }
+ a := auxIntToValAndOff(x.AuxInt)
+ if auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[1]
+ if p != x.Args[0] || !(p.Op != OpSB && x.Uses == 1 && a.Off()+4 == c.Off() && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XMOVDstore)
+ v.AuxInt = int32ToAuxInt(a.Off32())
+ v.Aux = symToAux(s)
+ v0 := b.NewValue0(x.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(c.Val()&0xffffffff | a.Val()<<32)
+ v.AddArg3(p, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMULLD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULLD x (MOVDconst [c]))
+ // cond: is32Bit(c)
+ // result: (MULLDconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ continue
+ }
+ v.reset(OpS390XMULLDconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MULLD <t> x g:(MOVDload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (MULLDload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVDload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XMULLDload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMULLDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MULLDconst <t> x [c])
+ // cond: isPowerOfTwo32(c&(c-1))
+ // result: (ADD (SLDconst <t> x [uint8(log32(c&(c-1)))]) (SLDconst <t> x [uint8(log32(c&^(c-1)))]))
+ for {
+ t := v.Type
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c & (c - 1))) {
+ break
+ }
+ v.reset(OpS390XADD)
+ v0 := b.NewValue0(v.Pos, OpS390XSLDconst, t)
+ v0.AuxInt = uint8ToAuxInt(uint8(log32(c & (c - 1))))
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XSLDconst, t)
+ v1.AuxInt = uint8ToAuxInt(uint8(log32(c &^ (c - 1))))
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (MULLDconst <t> x [c])
+ // cond: isPowerOfTwo32(c+(c&^(c-1)))
+ // result: (SUB (SLDconst <t> x [uint8(log32(c+(c&^(c-1))))]) (SLDconst <t> x [uint8(log32(c&^(c-1)))]))
+ for {
+ t := v.Type
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c + (c &^ (c - 1)))) {
+ break
+ }
+ v.reset(OpS390XSUB)
+ v0 := b.NewValue0(v.Pos, OpS390XSLDconst, t)
+ v0.AuxInt = uint8ToAuxInt(uint8(log32(c + (c &^ (c - 1)))))
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XSLDconst, t)
+ v1.AuxInt = uint8ToAuxInt(uint8(log32(c &^ (c - 1))))
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (MULLDconst <t> x [c])
+ // cond: isPowerOfTwo32(-c+(-c&^(-c-1)))
+ // result: (SUB (SLDconst <t> x [uint8(log32(-c&^(-c-1)))]) (SLDconst <t> x [uint8(log32(-c+(-c&^(-c-1))))]))
+ for {
+ t := v.Type
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(-c + (-c &^ (-c - 1)))) {
+ break
+ }
+ v.reset(OpS390XSUB)
+ v0 := b.NewValue0(v.Pos, OpS390XSLDconst, t)
+ v0.AuxInt = uint8ToAuxInt(uint8(log32(-c &^ (-c - 1))))
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XSLDconst, t)
+ v1.AuxInt = uint8ToAuxInt(uint8(log32(-c + (-c &^ (-c - 1)))))
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (MULLDconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [int64(c)*d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c) * d)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMULLDload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MULLDload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (MULLD x (LGDR <t> y))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr1 := v_1
+ if v_2.Op != OpS390XFMOVDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XMULLD)
+ v0 := b.NewValue0(v_2.Pos, OpS390XLGDR, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (MULLDload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (MULLDload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMULLDload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (MULLDload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (MULLDload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XMULLDload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMULLW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULLW x (MOVDconst [c]))
+ // result: (MULLWconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XMULLWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (MULLW <t> x g:(MOVWload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (MULLWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XMULLWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (MULLW <t> x g:(MOVWZload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (MULLWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWZload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XMULLWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMULLWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (MULLWconst <t> x [c])
+ // cond: isPowerOfTwo32(c&(c-1))
+ // result: (ADDW (SLWconst <t> x [uint8(log32(c&(c-1)))]) (SLWconst <t> x [uint8(log32(c&^(c-1)))]))
+ for {
+ t := v.Type
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c & (c - 1))) {
+ break
+ }
+ v.reset(OpS390XADDW)
+ v0 := b.NewValue0(v.Pos, OpS390XSLWconst, t)
+ v0.AuxInt = uint8ToAuxInt(uint8(log32(c & (c - 1))))
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XSLWconst, t)
+ v1.AuxInt = uint8ToAuxInt(uint8(log32(c &^ (c - 1))))
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (MULLWconst <t> x [c])
+ // cond: isPowerOfTwo32(c+(c&^(c-1)))
+ // result: (SUBW (SLWconst <t> x [uint8(log32(c+(c&^(c-1))))]) (SLWconst <t> x [uint8(log32(c&^(c-1)))]))
+ for {
+ t := v.Type
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(c + (c &^ (c - 1)))) {
+ break
+ }
+ v.reset(OpS390XSUBW)
+ v0 := b.NewValue0(v.Pos, OpS390XSLWconst, t)
+ v0.AuxInt = uint8ToAuxInt(uint8(log32(c + (c &^ (c - 1)))))
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XSLWconst, t)
+ v1.AuxInt = uint8ToAuxInt(uint8(log32(c &^ (c - 1))))
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (MULLWconst <t> x [c])
+ // cond: isPowerOfTwo32(-c+(-c&^(-c-1)))
+ // result: (SUBW (SLWconst <t> x [uint8(log32(-c&^(-c-1)))]) (SLWconst <t> x [uint8(log32(-c+(-c&^(-c-1))))]))
+ for {
+ t := v.Type
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(isPowerOfTwo32(-c + (-c &^ (-c - 1)))) {
+ break
+ }
+ v.reset(OpS390XSUBW)
+ v0 := b.NewValue0(v.Pos, OpS390XSLWconst, t)
+ v0.AuxInt = uint8ToAuxInt(uint8(log32(-c &^ (-c - 1))))
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpS390XSLWconst, t)
+ v1.AuxInt = uint8ToAuxInt(uint8(log32(-c + (-c &^ (-c - 1)))))
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (MULLWconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [int64(c*int32(d))])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c * int32(d)))
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XMULLWload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (MULLWload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (MULLWload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XMULLWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (MULLWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (MULLWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XMULLWload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XNEG(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEG (MOVDconst [c]))
+ // result: (MOVDconst [-c])
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(-c)
+ return true
+ }
+ // match: (NEG (ADDconst [c] (NEG x)))
+ // cond: c != -(1<<31)
+ // result: (ADDconst [-c] x)
+ for {
+ if v_0.Op != OpS390XADDconst {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XNEG {
+ break
+ }
+ x := v_0_0.Args[0]
+ if !(c != -(1 << 31)) {
+ break
+ }
+ v.reset(OpS390XADDconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XNEGW(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NEGW (MOVDconst [c]))
+ // result: (MOVDconst [int64(int32(-c))])
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(-c)))
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XNOT(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (NOT x)
+ // result: (XOR (MOVDconst [-1]) x)
+ for {
+ x := v_0
+ v.reset(OpS390XXOR)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(-1)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueS390X_OpS390XNOTW(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (NOTW x)
+ // result: (XORWconst [-1] x)
+ for {
+ x := v_0
+ v.reset(OpS390XXORWconst)
+ v.AuxInt = int32ToAuxInt(-1)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueS390X_OpS390XOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (OR x (MOVDconst [c]))
+ // cond: isU32Bit(c)
+ // result: (ORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isU32Bit(c)) {
+ continue
+ }
+ v.reset(OpS390XORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (OR (SLDconst x [c]) (SRDconst x [64-c]))
+ // result: (RISBGZ x {s390x.NewRotateParams(0, 63, c)})
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XSLDconst {
+ continue
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpS390XSRDconst || auxIntToUint8(v_1.AuxInt) != 64-c || x != v_1.Args[0] {
+ continue
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(0, 63, c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (OR (MOVDconst [-1<<63]) (LGDR <t> x))
+ // result: (LGDR <t> (LNDFR <x.Type> x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0.AuxInt) != -1<<63 || v_1.Op != OpS390XLGDR {
+ continue
+ }
+ t := v_1.Type
+ x := v_1.Args[0]
+ v.reset(OpS390XLGDR)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpS390XLNDFR, x.Type)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (OR (RISBGZ (LGDR x) {r}) (LGDR (LPDFR <t> y)))
+ // cond: r == s390x.NewRotateParams(0, 0, 0)
+ // result: (LGDR (CPSDR <t> y x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XRISBGZ {
+ continue
+ }
+ r := auxToS390xRotateParams(v_0.Aux)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XLGDR {
+ continue
+ }
+ x := v_0_0.Args[0]
+ if v_1.Op != OpS390XLGDR {
+ continue
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpS390XLPDFR {
+ continue
+ }
+ t := v_1_0.Type
+ y := v_1_0.Args[0]
+ if !(r == s390x.NewRotateParams(0, 0, 0)) {
+ continue
+ }
+ v.reset(OpS390XLGDR)
+ v0 := b.NewValue0(v.Pos, OpS390XCPSDR, t)
+ v0.AddArg2(y, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (OR (RISBGZ (LGDR x) {r}) (MOVDconst [c]))
+ // cond: c >= 0 && r == s390x.NewRotateParams(0, 0, 0)
+ // result: (LGDR (CPSDR <x.Type> (FMOVDconst <x.Type> [math.Float64frombits(uint64(c))]) x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XRISBGZ {
+ continue
+ }
+ r := auxToS390xRotateParams(v_0.Aux)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XLGDR {
+ continue
+ }
+ x := v_0_0.Args[0]
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c >= 0 && r == s390x.NewRotateParams(0, 0, 0)) {
+ continue
+ }
+ v.reset(OpS390XLGDR)
+ v0 := b.NewValue0(v.Pos, OpS390XCPSDR, x.Type)
+ v1 := b.NewValue0(v.Pos, OpS390XFMOVDconst, x.Type)
+ v1.AuxInt = float64ToAuxInt(math.Float64frombits(uint64(c)))
+ v0.AddArg2(v1, x)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (OR (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [c|d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(c | d)
+ return true
+ }
+ break
+ }
+ // match: (OR x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (OR <t> x g:(MOVDload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (ORload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVDload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XORload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR x1:(MOVBZload [i1] {s} p mem) sh:(SLDconst [8] x0:(MOVBZload [i0] {s} p mem)))
+ // cond: i1 == i0+1 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVHZload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x1 := v_0
+ if x1.Op != OpS390XMOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpS390XSLDconst || auxIntToUint8(sh.AuxInt) != 8 {
+ continue
+ }
+ x0 := sh.Args[0]
+ if x0.Op != OpS390XMOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+1 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpS390XMOVHZload, typ.UInt16)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR x1:(MOVHZload [i1] {s} p mem) sh:(SLDconst [16] x0:(MOVHZload [i0] {s} p mem)))
+ // cond: i1 == i0+2 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVWZload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x1 := v_0
+ if x1.Op != OpS390XMOVHZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpS390XSLDconst || auxIntToUint8(sh.AuxInt) != 16 {
+ continue
+ }
+ x0 := sh.Args[0]
+ if x0.Op != OpS390XMOVHZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+2 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpS390XMOVWZload, typ.UInt32)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR x1:(MOVWZload [i1] {s} p mem) sh:(SLDconst [32] x0:(MOVWZload [i0] {s} p mem)))
+ // cond: i1 == i0+4 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVDload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x1 := v_0
+ if x1.Op != OpS390XMOVWZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpS390XSLDconst || auxIntToUint8(sh.AuxInt) != 32 {
+ continue
+ }
+ x0 := sh.Args[0]
+ if x0.Op != OpS390XMOVWZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+4 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpS390XMOVDload, typ.UInt64)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR s0:(SLDconst [j0] x0:(MOVBZload [i0] {s} p mem)) or:(OR s1:(SLDconst [j1] x1:(MOVBZload [i1] {s} p mem)) y))
+ // cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVHZload [i0] {s} p mem)) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpS390XSLDconst {
+ continue
+ }
+ j0 := auxIntToUint8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpS390XMOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ or := v_1
+ if or.Op != OpS390XOR {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s1 := or_0
+ if s1.Op != OpS390XSLDconst {
+ continue
+ }
+ j1 := auxIntToUint8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpS390XMOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(i1 == i0+1 && j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x1.Pos, OpS390XOR, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpS390XSLDconst, v.Type)
+ v1.AuxInt = uint8ToAuxInt(j1)
+ v2 := b.NewValue0(x1.Pos, OpS390XMOVHZload, typ.UInt16)
+ v2.AuxInt = int32ToAuxInt(i0)
+ v2.Aux = symToAux(s)
+ v2.AddArg2(p, mem)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR s0:(SLDconst [j0] x0:(MOVHZload [i0] {s} p mem)) or:(OR s1:(SLDconst [j1] x1:(MOVHZload [i1] {s} p mem)) y))
+ // cond: i1 == i0+2 && j1 == j0-16 && j1 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVWZload [i0] {s} p mem)) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpS390XSLDconst {
+ continue
+ }
+ j0 := auxIntToUint8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpS390XMOVHZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ or := v_1
+ if or.Op != OpS390XOR {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s1 := or_0
+ if s1.Op != OpS390XSLDconst {
+ continue
+ }
+ j1 := auxIntToUint8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpS390XMOVHZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(i1 == i0+2 && j1 == j0-16 && j1%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x1.Pos, OpS390XOR, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpS390XSLDconst, v.Type)
+ v1.AuxInt = uint8ToAuxInt(j1)
+ v2 := b.NewValue0(x1.Pos, OpS390XMOVWZload, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(i0)
+ v2.Aux = symToAux(s)
+ v2.AddArg2(p, mem)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR x0:(MOVBZload [i0] {s} p mem) sh:(SLDconst [8] x1:(MOVBZload [i1] {s} p mem)))
+ // cond: p.Op != OpSB && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVHZreg (MOVHBRload [i0] {s} p mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpS390XMOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpS390XSLDconst || auxIntToUint8(sh.AuxInt) != 8 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpS390XMOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(p.Op != OpSB && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpS390XMOVHBRload, typ.UInt16)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (OR r0:(MOVHZreg x0:(MOVHBRload [i0] {s} p mem)) sh:(SLDconst [16] r1:(MOVHZreg x1:(MOVHBRload [i1] {s} p mem))))
+ // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVWZreg (MOVWBRload [i0] {s} p mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ r0 := v_0
+ if r0.Op != OpS390XMOVHZreg {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpS390XMOVHBRload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpS390XSLDconst || auxIntToUint8(sh.AuxInt) != 16 {
+ continue
+ }
+ r1 := sh.Args[0]
+ if r1.Op != OpS390XMOVHZreg {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpS390XMOVHBRload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpS390XMOVWZreg, typ.UInt64)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpS390XMOVWBRload, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (OR r0:(MOVWZreg x0:(MOVWBRload [i0] {s} p mem)) sh:(SLDconst [32] r1:(MOVWZreg x1:(MOVWBRload [i1] {s} p mem))))
+ // cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVDBRload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ r0 := v_0
+ if r0.Op != OpS390XMOVWZreg {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpS390XMOVWBRload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpS390XSLDconst || auxIntToUint8(sh.AuxInt) != 32 {
+ continue
+ }
+ r1 := sh.Args[0]
+ if r1.Op != OpS390XMOVWZreg {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpS390XMOVWBRload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpS390XMOVDBRload, typ.UInt64)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (OR s1:(SLDconst [j1] x1:(MOVBZload [i1] {s} p mem)) or:(OR s0:(SLDconst [j0] x0:(MOVBZload [i0] {s} p mem)) y))
+ // cond: p.Op != OpSB && i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVHZreg (MOVHBRload [i0] {s} p mem))) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpS390XSLDconst {
+ continue
+ }
+ j1 := auxIntToUint8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpS390XMOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ or := v_1
+ if or.Op != OpS390XOR {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s0 := or_0
+ if s0.Op != OpS390XSLDconst {
+ continue
+ }
+ j0 := auxIntToUint8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpS390XMOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(p.Op != OpSB && i1 == i0+1 && j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x0.Pos, OpS390XOR, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpS390XSLDconst, v.Type)
+ v1.AuxInt = uint8ToAuxInt(j0)
+ v2 := b.NewValue0(x0.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3 := b.NewValue0(x0.Pos, OpS390XMOVHBRload, typ.UInt16)
+ v3.AuxInt = int32ToAuxInt(i0)
+ v3.Aux = symToAux(s)
+ v3.AddArg2(p, mem)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (OR s1:(SLDconst [j1] r1:(MOVHZreg x1:(MOVHBRload [i1] {s} p mem))) or:(OR s0:(SLDconst [j0] r0:(MOVHZreg x0:(MOVHBRload [i0] {s} p mem))) y))
+ // cond: i1 == i0+2 && j1 == j0+16 && j0 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, r0, r1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVWZreg (MOVWBRload [i0] {s} p mem))) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpS390XSLDconst {
+ continue
+ }
+ j1 := auxIntToUint8(s1.AuxInt)
+ r1 := s1.Args[0]
+ if r1.Op != OpS390XMOVHZreg {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpS390XMOVHBRload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ or := v_1
+ if or.Op != OpS390XOR {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s0 := or_0
+ if s0.Op != OpS390XSLDconst {
+ continue
+ }
+ j0 := auxIntToUint8(s0.AuxInt)
+ r0 := s0.Args[0]
+ if r0.Op != OpS390XMOVHZreg {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpS390XMOVHBRload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(i1 == i0+2 && j1 == j0+16 && j0%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, r0, r1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x0.Pos, OpS390XOR, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpS390XSLDconst, v.Type)
+ v1.AuxInt = uint8ToAuxInt(j0)
+ v2 := b.NewValue0(x0.Pos, OpS390XMOVWZreg, typ.UInt64)
+ v3 := b.NewValue0(x0.Pos, OpS390XMOVWBRload, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(i0)
+ v3.Aux = symToAux(s)
+ v3.AddArg2(p, mem)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XORW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ORW x (MOVDconst [c]))
+ // result: (ORWconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XORWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORW (SLWconst x [c]) (SRWconst x [32-c]))
+ // result: (RLLconst x [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XSLWconst {
+ continue
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpS390XSRWconst || auxIntToUint8(v_1.AuxInt) != 32-c || x != v_1.Args[0] {
+ continue
+ }
+ v.reset(OpS390XRLLconst)
+ v.AuxInt = uint8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (ORW x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORW <t> x g:(MOVWload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (ORWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XORWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORW <t> x g:(MOVWZload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (ORWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWZload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XORWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORW x1:(MOVBZload [i1] {s} p mem) sh:(SLWconst [8] x0:(MOVBZload [i0] {s} p mem)))
+ // cond: i1 == i0+1 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVHZload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x1 := v_0
+ if x1.Op != OpS390XMOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpS390XSLWconst || auxIntToUint8(sh.AuxInt) != 8 {
+ continue
+ }
+ x0 := sh.Args[0]
+ if x0.Op != OpS390XMOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+1 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpS390XMOVHZload, typ.UInt16)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORW x1:(MOVHZload [i1] {s} p mem) sh:(SLWconst [16] x0:(MOVHZload [i0] {s} p mem)))
+ // cond: i1 == i0+2 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVWZload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x1 := v_0
+ if x1.Op != OpS390XMOVHZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ sh := v_1
+ if sh.Op != OpS390XSLWconst || auxIntToUint8(sh.AuxInt) != 16 {
+ continue
+ }
+ x0 := sh.Args[0]
+ if x0.Op != OpS390XMOVHZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+2 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x0.Pos, OpS390XMOVWZload, typ.UInt32)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORW s0:(SLWconst [j0] x0:(MOVBZload [i0] {s} p mem)) or:(ORW s1:(SLWconst [j1] x1:(MOVBZload [i1] {s} p mem)) y))
+ // cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORW <v.Type> (SLWconst <v.Type> [j1] (MOVHZload [i0] {s} p mem)) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s0 := v_0
+ if s0.Op != OpS390XSLWconst {
+ continue
+ }
+ j0 := auxIntToUint8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpS390XMOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ or := v_1
+ if or.Op != OpS390XORW {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s1 := or_0
+ if s1.Op != OpS390XSLWconst {
+ continue
+ }
+ j1 := auxIntToUint8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpS390XMOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(i1 == i0+1 && j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x1.Pos, OpS390XORW, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpS390XSLWconst, v.Type)
+ v1.AuxInt = uint8ToAuxInt(j1)
+ v2 := b.NewValue0(x1.Pos, OpS390XMOVHZload, typ.UInt16)
+ v2.AuxInt = int32ToAuxInt(i0)
+ v2.Aux = symToAux(s)
+ v2.AddArg2(p, mem)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (ORW x0:(MOVBZload [i0] {s} p mem) sh:(SLWconst [8] x1:(MOVBZload [i1] {s} p mem)))
+ // cond: p.Op != OpSB && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVHZreg (MOVHBRload [i0] {s} p mem))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x0 := v_0
+ if x0.Op != OpS390XMOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpS390XSLWconst || auxIntToUint8(sh.AuxInt) != 8 {
+ continue
+ }
+ x1 := sh.Args[0]
+ if x1.Op != OpS390XMOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(p.Op != OpSB && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x1.Pos, OpS390XMOVHBRload, typ.UInt16)
+ v1.AuxInt = int32ToAuxInt(i0)
+ v1.Aux = symToAux(s)
+ v1.AddArg2(p, mem)
+ v0.AddArg(v1)
+ return true
+ }
+ break
+ }
+ // match: (ORW r0:(MOVHZreg x0:(MOVHBRload [i0] {s} p mem)) sh:(SLWconst [16] r1:(MOVHZreg x1:(MOVHBRload [i1] {s} p mem))))
+ // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh)
+ // result: @mergePoint(b,x0,x1) (MOVWBRload [i0] {s} p mem)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ r0 := v_0
+ if r0.Op != OpS390XMOVHZreg {
+ continue
+ }
+ x0 := r0.Args[0]
+ if x0.Op != OpS390XMOVHBRload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ s := auxToSym(x0.Aux)
+ mem := x0.Args[1]
+ p := x0.Args[0]
+ sh := v_1
+ if sh.Op != OpS390XSLWconst || auxIntToUint8(sh.AuxInt) != 16 {
+ continue
+ }
+ r1 := sh.Args[0]
+ if r1.Op != OpS390XMOVHZreg {
+ continue
+ }
+ x1 := r1.Args[0]
+ if x1.Op != OpS390XMOVHBRload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ if auxToSym(x1.Aux) != s {
+ continue
+ }
+ _ = x1.Args[1]
+ if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1)
+ v0 := b.NewValue0(x1.Pos, OpS390XMOVWBRload, typ.UInt32)
+ v.copyOf(v0)
+ v0.AuxInt = int32ToAuxInt(i0)
+ v0.Aux = symToAux(s)
+ v0.AddArg2(p, mem)
+ return true
+ }
+ break
+ }
+ // match: (ORW s1:(SLWconst [j1] x1:(MOVBZload [i1] {s} p mem)) or:(ORW s0:(SLWconst [j0] x0:(MOVBZload [i0] {s} p mem)) y))
+ // cond: p.Op != OpSB && i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or)
+ // result: @mergePoint(b,x0,x1,y) (ORW <v.Type> (SLWconst <v.Type> [j0] (MOVHZreg (MOVHBRload [i0] {s} p mem))) y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s1 := v_0
+ if s1.Op != OpS390XSLWconst {
+ continue
+ }
+ j1 := auxIntToUint8(s1.AuxInt)
+ x1 := s1.Args[0]
+ if x1.Op != OpS390XMOVBZload {
+ continue
+ }
+ i1 := auxIntToInt32(x1.AuxInt)
+ s := auxToSym(x1.Aux)
+ mem := x1.Args[1]
+ p := x1.Args[0]
+ or := v_1
+ if or.Op != OpS390XORW {
+ continue
+ }
+ _ = or.Args[1]
+ or_0 := or.Args[0]
+ or_1 := or.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, or_0, or_1 = _i1+1, or_1, or_0 {
+ s0 := or_0
+ if s0.Op != OpS390XSLWconst {
+ continue
+ }
+ j0 := auxIntToUint8(s0.AuxInt)
+ x0 := s0.Args[0]
+ if x0.Op != OpS390XMOVBZload {
+ continue
+ }
+ i0 := auxIntToInt32(x0.AuxInt)
+ if auxToSym(x0.Aux) != s {
+ continue
+ }
+ _ = x0.Args[1]
+ if p != x0.Args[0] || mem != x0.Args[1] {
+ continue
+ }
+ y := or_1
+ if !(p.Op != OpSB && i1 == i0+1 && j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) {
+ continue
+ }
+ b = mergePoint(b, x0, x1, y)
+ v0 := b.NewValue0(x0.Pos, OpS390XORW, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(x0.Pos, OpS390XSLWconst, v.Type)
+ v1.AuxInt = uint8ToAuxInt(j0)
+ v2 := b.NewValue0(x0.Pos, OpS390XMOVHZreg, typ.UInt64)
+ v3 := b.NewValue0(x0.Pos, OpS390XMOVHBRload, typ.UInt16)
+ v3.AuxInt = int32ToAuxInt(i0)
+ v3.Aux = symToAux(s)
+ v3.AddArg2(p, mem)
+ v2.AddArg(v3)
+ v1.AddArg(v2)
+ v0.AddArg2(v1, y)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XORWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ORWconst [c] x)
+ // cond: int32(c)==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(int32(c) == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORWconst [c] _)
+ // cond: int32(c)==-1
+ // result: (MOVDconst [-1])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (ORWconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [int64(c)|d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c) | d)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XORWload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ORWload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (ORWload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XORWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (ORWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (ORWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XORWload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (ORconst [-1] _)
+ // result: (MOVDconst [-1])
+ for {
+ if auxIntToInt64(v.AuxInt) != -1 {
+ break
+ }
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (ORconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [c|d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(c | d)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XORload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (ORload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (OR x (LGDR <t> y))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr1 := v_1
+ if v_2.Op != OpS390XFMOVDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XOR)
+ v0 := b.NewValue0(v_2.Pos, OpS390XLGDR, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (ORload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (ORload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XORload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (ORload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (ORload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XORload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XRISBGZ(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (RISBGZ (MOVWZreg x) {r})
+ // cond: r.InMerge(0xffffffff) != nil
+ // result: (RISBGZ x {*r.InMerge(0xffffffff)})
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ if v_0.Op != OpS390XMOVWZreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(r.InMerge(0xffffffff) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(*r.InMerge(0xffffffff))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ (MOVHZreg x) {r})
+ // cond: r.InMerge(0x0000ffff) != nil
+ // result: (RISBGZ x {*r.InMerge(0x0000ffff)})
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ if v_0.Op != OpS390XMOVHZreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(r.InMerge(0x0000ffff) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(*r.InMerge(0x0000ffff))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ (MOVBZreg x) {r})
+ // cond: r.InMerge(0x000000ff) != nil
+ // result: (RISBGZ x {*r.InMerge(0x000000ff)})
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ if v_0.Op != OpS390XMOVBZreg {
+ break
+ }
+ x := v_0.Args[0]
+ if !(r.InMerge(0x000000ff) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(*r.InMerge(0x000000ff))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ (SLDconst x [c]) {r})
+ // cond: r.InMerge(^uint64(0)<<c) != nil
+ // result: (RISBGZ x {(*r.InMerge(^uint64(0)<<c)).RotateLeft(c)})
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ if v_0.Op != OpS390XSLDconst {
+ break
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(r.InMerge(^uint64(0)<<c) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux((*r.InMerge(^uint64(0) << c)).RotateLeft(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ (SRDconst x [c]) {r})
+ // cond: r.InMerge(^uint64(0)>>c) != nil
+ // result: (RISBGZ x {(*r.InMerge(^uint64(0)>>c)).RotateLeft(-c)})
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ if v_0.Op != OpS390XSRDconst {
+ break
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(r.InMerge(^uint64(0)>>c) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux((*r.InMerge(^uint64(0) >> c)).RotateLeft(-c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ (RISBGZ x {y}) {z})
+ // cond: z.InMerge(y.OutMask()) != nil
+ // result: (RISBGZ x {(*z.InMerge(y.OutMask())).RotateLeft(y.Amount)})
+ for {
+ z := auxToS390xRotateParams(v.Aux)
+ if v_0.Op != OpS390XRISBGZ {
+ break
+ }
+ y := auxToS390xRotateParams(v_0.Aux)
+ x := v_0.Args[0]
+ if !(z.InMerge(y.OutMask()) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux((*z.InMerge(y.OutMask())).RotateLeft(y.Amount))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ x {r})
+ // cond: r.End == 63 && r.Start == -r.Amount&63
+ // result: (SRDconst x [-r.Amount&63])
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ x := v_0
+ if !(r.End == 63 && r.Start == -r.Amount&63) {
+ break
+ }
+ v.reset(OpS390XSRDconst)
+ v.AuxInt = uint8ToAuxInt(-r.Amount & 63)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ x {r})
+ // cond: r.Start == 0 && r.End == 63-r.Amount
+ // result: (SLDconst x [r.Amount])
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ x := v_0
+ if !(r.Start == 0 && r.End == 63-r.Amount) {
+ break
+ }
+ v.reset(OpS390XSLDconst)
+ v.AuxInt = uint8ToAuxInt(r.Amount)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ (SRADconst x [c]) {r})
+ // cond: r.Start == r.End && (r.Start+r.Amount)&63 <= c
+ // result: (RISBGZ x {s390x.NewRotateParams(r.Start, r.Start, -r.Start&63)})
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ if v_0.Op != OpS390XSRADconst {
+ break
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(r.Start == r.End && (r.Start+r.Amount)&63 <= c) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(r.Start, r.Start, -r.Start&63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ x {r})
+ // cond: r == s390x.NewRotateParams(56, 63, 0)
+ // result: (MOVBZreg x)
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ x := v_0
+ if !(r == s390x.NewRotateParams(56, 63, 0)) {
+ break
+ }
+ v.reset(OpS390XMOVBZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ x {r})
+ // cond: r == s390x.NewRotateParams(48, 63, 0)
+ // result: (MOVHZreg x)
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ x := v_0
+ if !(r == s390x.NewRotateParams(48, 63, 0)) {
+ break
+ }
+ v.reset(OpS390XMOVHZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ x {r})
+ // cond: r == s390x.NewRotateParams(32, 63, 0)
+ // result: (MOVWZreg x)
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ x := v_0
+ if !(r == s390x.NewRotateParams(32, 63, 0)) {
+ break
+ }
+ v.reset(OpS390XMOVWZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (RISBGZ (LGDR <t> x) {r})
+ // cond: r == s390x.NewRotateParams(1, 63, 0)
+ // result: (LGDR <t> (LPDFR <x.Type> x))
+ for {
+ r := auxToS390xRotateParams(v.Aux)
+ if v_0.Op != OpS390XLGDR {
+ break
+ }
+ t := v_0.Type
+ x := v_0.Args[0]
+ if !(r == s390x.NewRotateParams(1, 63, 0)) {
+ break
+ }
+ v.reset(OpS390XLGDR)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpS390XLPDFR, x.Type)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XRLL(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RLL x (MOVDconst [c]))
+ // result: (RLLconst x [uint8(c&31)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XRLLconst)
+ v.AuxInt = uint8ToAuxInt(uint8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XRLLG(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RLLG x (MOVDconst [c]))
+ // result: (RISBGZ x {s390x.NewRotateParams(0, 63, uint8(c&63))})
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(0, 63, uint8(c&63)))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSLD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SLD x (MOVDconst [c]))
+ // result: (SLDconst x [uint8(c&63)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XSLDconst)
+ v.AuxInt = uint8ToAuxInt(uint8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLD x (RISBGZ y {r}))
+ // cond: r.Amount == 0 && r.OutMask()&63 == 63
+ // result: (SLD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_1.Aux)
+ y := v_1.Args[0]
+ if !(r.Amount == 0 && r.OutMask()&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLD x (AND (MOVDconst [c]) y))
+ // result: (SLD x (ANDWconst <typ.UInt32> [int32(c&63)] y))
+ for {
+ x := v_0
+ if v_1.Op != OpS390XAND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ y := v_1_1
+ v.reset(OpS390XSLD)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(c & 63))
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (SLD x (ANDWconst [c] y))
+ // cond: c&63 == 63
+ // result: (SLD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XANDWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLD x (MOVWreg y))
+ // result: (SLD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLD x (MOVHreg y))
+ // result: (SLD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLD x (MOVBreg y))
+ // result: (SLD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLD x (MOVWZreg y))
+ // result: (SLD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLD x (MOVHZreg y))
+ // result: (SLD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLD x (MOVBZreg y))
+ // result: (SLD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLD)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSLDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SLDconst (SRDconst x [c]) [d])
+ // result: (RISBGZ x {s390x.NewRotateParams(uint8(max8(0, int8(c-d))), 63-d, uint8(int8(d-c)&63))})
+ for {
+ d := auxIntToUint8(v.AuxInt)
+ if v_0.Op != OpS390XSRDconst {
+ break
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(uint8(max8(0, int8(c-d))), 63-d, uint8(int8(d-c)&63)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLDconst (RISBGZ x {r}) [c])
+ // cond: s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask()) != nil
+ // result: (RISBGZ x {(*s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask())).RotateLeft(r.Amount)})
+ for {
+ c := auxIntToUint8(v.AuxInt)
+ if v_0.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_0.Aux)
+ x := v_0.Args[0]
+ if !(s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask()) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux((*s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask())).RotateLeft(r.Amount))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLDconst x [0])
+ // result: x
+ for {
+ if auxIntToUint8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSLW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SLW x (MOVDconst [c]))
+ // cond: c&32 == 0
+ // result: (SLWconst x [uint8(c&31)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c&32 == 0) {
+ break
+ }
+ v.reset(OpS390XSLWconst)
+ v.AuxInt = uint8ToAuxInt(uint8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SLW _ (MOVDconst [c]))
+ // cond: c&32 != 0
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c&32 != 0) {
+ break
+ }
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SLW x (RISBGZ y {r}))
+ // cond: r.Amount == 0 && r.OutMask()&63 == 63
+ // result: (SLW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_1.Aux)
+ y := v_1.Args[0]
+ if !(r.Amount == 0 && r.OutMask()&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLW x (AND (MOVDconst [c]) y))
+ // result: (SLW x (ANDWconst <typ.UInt32> [int32(c&63)] y))
+ for {
+ x := v_0
+ if v_1.Op != OpS390XAND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ y := v_1_1
+ v.reset(OpS390XSLW)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(c & 63))
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (SLW x (ANDWconst [c] y))
+ // cond: c&63 == 63
+ // result: (SLW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XANDWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLW x (MOVWreg y))
+ // result: (SLW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLW x (MOVHreg y))
+ // result: (SLW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLW x (MOVBreg y))
+ // result: (SLW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLW x (MOVWZreg y))
+ // result: (SLW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLW x (MOVHZreg y))
+ // result: (SLW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SLW x (MOVBZreg y))
+ // result: (SLW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSLW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSLWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SLWconst x [0])
+ // result: x
+ for {
+ if auxIntToUint8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSRAD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SRAD x (MOVDconst [c]))
+ // result: (SRADconst x [uint8(c&63)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XSRADconst)
+ v.AuxInt = uint8ToAuxInt(uint8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAD x (RISBGZ y {r}))
+ // cond: r.Amount == 0 && r.OutMask()&63 == 63
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_1.Aux)
+ y := v_1.Args[0]
+ if !(r.Amount == 0 && r.OutMask()&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAD x (AND (MOVDconst [c]) y))
+ // result: (SRAD x (ANDWconst <typ.UInt32> [int32(c&63)] y))
+ for {
+ x := v_0
+ if v_1.Op != OpS390XAND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ y := v_1_1
+ v.reset(OpS390XSRAD)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(c & 63))
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (SRAD x (ANDWconst [c] y))
+ // cond: c&63 == 63
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XANDWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAD x (MOVWreg y))
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAD x (MOVHreg y))
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAD x (MOVBreg y))
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAD x (MOVWZreg y))
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAD x (MOVHZreg y))
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAD x (MOVBZreg y))
+ // result: (SRAD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAD)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSRADconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRADconst x [0])
+ // result: x
+ for {
+ if auxIntToUint8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SRADconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [d>>uint64(c)])
+ for {
+ c := auxIntToUint8(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(d >> uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSRAW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SRAW x (MOVDconst [c]))
+ // cond: c&32 == 0
+ // result: (SRAWconst x [uint8(c&31)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c&32 == 0) {
+ break
+ }
+ v.reset(OpS390XSRAWconst)
+ v.AuxInt = uint8ToAuxInt(uint8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAW x (MOVDconst [c]))
+ // cond: c&32 != 0
+ // result: (SRAWconst x [31])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c&32 != 0) {
+ break
+ }
+ v.reset(OpS390XSRAWconst)
+ v.AuxInt = uint8ToAuxInt(31)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRAW x (RISBGZ y {r}))
+ // cond: r.Amount == 0 && r.OutMask()&63 == 63
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_1.Aux)
+ y := v_1.Args[0]
+ if !(r.Amount == 0 && r.OutMask()&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAW x (AND (MOVDconst [c]) y))
+ // result: (SRAW x (ANDWconst <typ.UInt32> [int32(c&63)] y))
+ for {
+ x := v_0
+ if v_1.Op != OpS390XAND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ y := v_1_1
+ v.reset(OpS390XSRAW)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(c & 63))
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (SRAW x (ANDWconst [c] y))
+ // cond: c&63 == 63
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XANDWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAW x (MOVWreg y))
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAW x (MOVHreg y))
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAW x (MOVBreg y))
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAW x (MOVWZreg y))
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAW x (MOVHZreg y))
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRAW x (MOVBZreg y))
+ // result: (SRAW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRAW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSRAWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRAWconst x [0])
+ // result: x
+ for {
+ if auxIntToUint8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SRAWconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [int64(int32(d))>>uint64(c)])
+ for {
+ c := auxIntToUint8(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(int32(d)) >> uint64(c))
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSRD(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SRD x (MOVDconst [c]))
+ // result: (SRDconst x [uint8(c&63)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XSRDconst)
+ v.AuxInt = uint8ToAuxInt(uint8(c & 63))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRD x (RISBGZ y {r}))
+ // cond: r.Amount == 0 && r.OutMask()&63 == 63
+ // result: (SRD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_1.Aux)
+ y := v_1.Args[0]
+ if !(r.Amount == 0 && r.OutMask()&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRD x (AND (MOVDconst [c]) y))
+ // result: (SRD x (ANDWconst <typ.UInt32> [int32(c&63)] y))
+ for {
+ x := v_0
+ if v_1.Op != OpS390XAND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ y := v_1_1
+ v.reset(OpS390XSRD)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(c & 63))
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (SRD x (ANDWconst [c] y))
+ // cond: c&63 == 63
+ // result: (SRD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XANDWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRD x (MOVWreg y))
+ // result: (SRD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRD x (MOVHreg y))
+ // result: (SRD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRD x (MOVBreg y))
+ // result: (SRD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRD x (MOVWZreg y))
+ // result: (SRD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRD x (MOVHZreg y))
+ // result: (SRD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRD x (MOVBZreg y))
+ // result: (SRD x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRD)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSRDconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRDconst (SLDconst x [c]) [d])
+ // result: (RISBGZ x {s390x.NewRotateParams(d, uint8(min8(63, int8(63-c+d))), uint8(int8(c-d)&63))})
+ for {
+ d := auxIntToUint8(v.AuxInt)
+ if v_0.Op != OpS390XSLDconst {
+ break
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(d, uint8(min8(63, int8(63-c+d))), uint8(int8(c-d)&63)))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRDconst (RISBGZ x {r}) [c])
+ // cond: s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask()) != nil
+ // result: (RISBGZ x {(*s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask())).RotateLeft(r.Amount)})
+ for {
+ c := auxIntToUint8(v.AuxInt)
+ if v_0.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_0.Aux)
+ x := v_0.Args[0]
+ if !(s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask()) != nil) {
+ break
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux((*s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask())).RotateLeft(r.Amount))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRDconst x [0])
+ // result: x
+ for {
+ if auxIntToUint8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSRW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SRW x (MOVDconst [c]))
+ // cond: c&32 == 0
+ // result: (SRWconst x [uint8(c&31)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c&32 == 0) {
+ break
+ }
+ v.reset(OpS390XSRWconst)
+ v.AuxInt = uint8ToAuxInt(uint8(c & 31))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SRW _ (MOVDconst [c]))
+ // cond: c&32 != 0
+ // result: (MOVDconst [0])
+ for {
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c&32 != 0) {
+ break
+ }
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SRW x (RISBGZ y {r}))
+ // cond: r.Amount == 0 && r.OutMask()&63 == 63
+ // result: (SRW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XRISBGZ {
+ break
+ }
+ r := auxToS390xRotateParams(v_1.Aux)
+ y := v_1.Args[0]
+ if !(r.Amount == 0 && r.OutMask()&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRW x (AND (MOVDconst [c]) y))
+ // result: (SRW x (ANDWconst <typ.UInt32> [int32(c&63)] y))
+ for {
+ x := v_0
+ if v_1.Op != OpS390XAND {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ y := v_1_1
+ v.reset(OpS390XSRW)
+ v0 := b.NewValue0(v.Pos, OpS390XANDWconst, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(c & 63))
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ break
+ }
+ // match: (SRW x (ANDWconst [c] y))
+ // cond: c&63 == 63
+ // result: (SRW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XANDWconst {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ y := v_1.Args[0]
+ if !(c&63 == 63) {
+ break
+ }
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRW x (MOVWreg y))
+ // result: (SRW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRW x (MOVHreg y))
+ // result: (SRW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRW x (MOVBreg y))
+ // result: (SRW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRW x (MOVWZreg y))
+ // result: (SRW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVWZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRW x (MOVHZreg y))
+ // result: (SRW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVHZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SRW x (MOVBZreg y))
+ // result: (SRW x y)
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVBZreg {
+ break
+ }
+ y := v_1.Args[0]
+ v.reset(OpS390XSRW)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSRWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SRWconst x [0])
+ // result: x
+ for {
+ if auxIntToUint8(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSTM2(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (STM2 [i] {s} p w2 w3 x:(STM2 [i-8] {s} p w0 w1 mem))
+ // cond: x.Uses == 1 && is20Bit(int64(i)-8) && clobber(x)
+ // result: (STM4 [i-8] {s} p w0 w1 w2 w3 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w2 := v_1
+ w3 := v_2
+ x := v_3
+ if x.Op != OpS390XSTM2 || auxIntToInt32(x.AuxInt) != i-8 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[3]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ w1 := x.Args[2]
+ if !(x.Uses == 1 && is20Bit(int64(i)-8) && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XSTM4)
+ v.AuxInt = int32ToAuxInt(i - 8)
+ v.Aux = symToAux(s)
+ v.AddArg6(p, w0, w1, w2, w3, mem)
+ return true
+ }
+ // match: (STM2 [i] {s} p (SRDconst [32] x) x mem)
+ // result: (MOVDstore [i] {s} p x mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ if v_1.Op != OpS390XSRDconst || auxIntToUint8(v_1.AuxInt) != 32 {
+ break
+ }
+ x := v_1.Args[0]
+ if x != v_2 {
+ break
+ }
+ mem := v_3
+ v.reset(OpS390XMOVDstore)
+ v.AuxInt = int32ToAuxInt(i)
+ v.Aux = symToAux(s)
+ v.AddArg3(p, x, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSTMG2(v *Value) bool {
+ v_3 := v.Args[3]
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (STMG2 [i] {s} p w2 w3 x:(STMG2 [i-16] {s} p w0 w1 mem))
+ // cond: x.Uses == 1 && is20Bit(int64(i)-16) && clobber(x)
+ // result: (STMG4 [i-16] {s} p w0 w1 w2 w3 mem)
+ for {
+ i := auxIntToInt32(v.AuxInt)
+ s := auxToSym(v.Aux)
+ p := v_0
+ w2 := v_1
+ w3 := v_2
+ x := v_3
+ if x.Op != OpS390XSTMG2 || auxIntToInt32(x.AuxInt) != i-16 || auxToSym(x.Aux) != s {
+ break
+ }
+ mem := x.Args[3]
+ if p != x.Args[0] {
+ break
+ }
+ w0 := x.Args[1]
+ w1 := x.Args[2]
+ if !(x.Uses == 1 && is20Bit(int64(i)-16) && clobber(x)) {
+ break
+ }
+ v.reset(OpS390XSTMG4)
+ v.AuxInt = int32ToAuxInt(i - 16)
+ v.Aux = symToAux(s)
+ v.AddArg6(p, w0, w1, w2, w3, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSUB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUB x (MOVDconst [c]))
+ // cond: is32Bit(c)
+ // result: (SUBconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpS390XSUBconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUB (MOVDconst [c]) x)
+ // cond: is32Bit(c)
+ // result: (NEG (SUBconst <v.Type> x [int32(c)]))
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ if !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpS390XNEG)
+ v0 := b.NewValue0(v.Pos, OpS390XSUBconst, v.Type)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUB x x)
+ // result: (MOVDconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SUB <t> x g:(MOVDload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (SUBload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVDload {
+ break
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ break
+ }
+ v.reset(OpS390XSUBload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSUBE(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBE x y (FlagGT))
+ // result: (SUBC x y)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpS390XFlagGT {
+ break
+ }
+ v.reset(OpS390XSUBC)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUBE x y (FlagOV))
+ // result: (SUBC x y)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpS390XFlagOV {
+ break
+ }
+ v.reset(OpS390XSUBC)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (SUBE x y (Select1 (SUBC (MOVDconst [0]) (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) c))))))
+ // result: (SUBE x y c)
+ for {
+ x := v_0
+ y := v_1
+ if v_2.Op != OpSelect1 {
+ break
+ }
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpS390XSUBC {
+ break
+ }
+ _ = v_2_0.Args[1]
+ v_2_0_0 := v_2_0.Args[0]
+ if v_2_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_2_0_0.AuxInt) != 0 {
+ break
+ }
+ v_2_0_1 := v_2_0.Args[1]
+ if v_2_0_1.Op != OpS390XNEG {
+ break
+ }
+ v_2_0_1_0 := v_2_0_1.Args[0]
+ if v_2_0_1_0.Op != OpSelect0 {
+ break
+ }
+ v_2_0_1_0_0 := v_2_0_1_0.Args[0]
+ if v_2_0_1_0_0.Op != OpS390XSUBE {
+ break
+ }
+ c := v_2_0_1_0_0.Args[2]
+ v_2_0_1_0_0_0 := v_2_0_1_0_0.Args[0]
+ if v_2_0_1_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_2_0_1_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_2_0_1_0_0_1 := v_2_0_1_0_0.Args[1]
+ if v_2_0_1_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_2_0_1_0_0_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpS390XSUBE)
+ v.AddArg3(x, y, c)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSUBW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBW x (MOVDconst [c]))
+ // result: (SUBWconst x [int32(c)])
+ for {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XSUBWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBW (MOVDconst [c]) x)
+ // result: (NEGW (SUBWconst <v.Type> x [int32(c)]))
+ for {
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ x := v_1
+ v.reset(OpS390XNEGW)
+ v0 := b.NewValue0(v.Pos, OpS390XSUBWconst, v.Type)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SUBW x x)
+ // result: (MOVDconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (SUBW <t> x g:(MOVWload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (SUBWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWload {
+ break
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ break
+ }
+ v.reset(OpS390XSUBWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (SUBW <t> x g:(MOVWZload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (SUBWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWZload {
+ break
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ break
+ }
+ v.reset(OpS390XSUBWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSUBWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SUBWconst [c] x)
+ // cond: int32(c) == 0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(int32(c) == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUBWconst [c] x)
+ // result: (ADDWconst [-int32(c)] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ v.reset(OpS390XADDWconst)
+ v.AuxInt = int32ToAuxInt(-int32(c))
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueS390X_OpS390XSUBWload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (SUBWload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (SUBWload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XSUBWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (SUBWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (SUBWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XSUBWload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSUBconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SUBconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt32(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (SUBconst [c] x)
+ // cond: c != -(1<<31)
+ // result: (ADDconst [-c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(c != -(1 << 31)) {
+ break
+ }
+ v.reset(OpS390XADDconst)
+ v.AuxInt = int32ToAuxInt(-c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SUBconst (MOVDconst [d]) [c])
+ // result: (MOVDconst [d-int64(c)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(d - int64(c))
+ return true
+ }
+ // match: (SUBconst (SUBconst x [d]) [c])
+ // cond: is32Bit(-int64(c)-int64(d))
+ // result: (ADDconst [-c-d] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XSUBconst {
+ break
+ }
+ d := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(is32Bit(-int64(c) - int64(d))) {
+ break
+ }
+ v.reset(OpS390XADDconst)
+ v.AuxInt = int32ToAuxInt(-c - d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSUBload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (SUBload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (SUB x (LGDR <t> y))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr1 := v_1
+ if v_2.Op != OpS390XFMOVDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XSUB)
+ v0 := b.NewValue0(v_2.Pos, OpS390XLGDR, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (SUBload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (SUBload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XSUBload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (SUBload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (SUBload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XSUBload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XSumBytes2(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SumBytes2 x)
+ // result: (ADDW (SRWconst <typ.UInt8> x [8]) x)
+ for {
+ x := v_0
+ v.reset(OpS390XADDW)
+ v0 := b.NewValue0(v.Pos, OpS390XSRWconst, typ.UInt8)
+ v0.AuxInt = uint8ToAuxInt(8)
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueS390X_OpS390XSumBytes4(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SumBytes4 x)
+ // result: (SumBytes2 (ADDW <typ.UInt16> (SRWconst <typ.UInt16> x [16]) x))
+ for {
+ x := v_0
+ v.reset(OpS390XSumBytes2)
+ v0 := b.NewValue0(v.Pos, OpS390XADDW, typ.UInt16)
+ v1 := b.NewValue0(v.Pos, OpS390XSRWconst, typ.UInt16)
+ v1.AuxInt = uint8ToAuxInt(16)
+ v1.AddArg(x)
+ v0.AddArg2(v1, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpS390XSumBytes8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SumBytes8 x)
+ // result: (SumBytes4 (ADDW <typ.UInt32> (SRDconst <typ.UInt32> x [32]) x))
+ for {
+ x := v_0
+ v.reset(OpS390XSumBytes4)
+ v0 := b.NewValue0(v.Pos, OpS390XADDW, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpS390XSRDconst, typ.UInt32)
+ v1.AuxInt = uint8ToAuxInt(32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpS390XXOR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XOR x (MOVDconst [c]))
+ // cond: isU32Bit(c)
+ // result: (XORconst [c] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isU32Bit(c)) {
+ continue
+ }
+ v.reset(OpS390XXORconst)
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR (SLDconst x [c]) (SRDconst x [64-c]))
+ // result: (RISBGZ x {s390x.NewRotateParams(0, 63, c)})
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XSLDconst {
+ continue
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpS390XSRDconst || auxIntToUint8(v_1.AuxInt) != 64-c || x != v_1.Args[0] {
+ continue
+ }
+ v.reset(OpS390XRISBGZ)
+ v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(0, 63, c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XOR (MOVDconst [c]) (MOVDconst [d]))
+ // result: (MOVDconst [c^d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(c ^ d)
+ return true
+ }
+ break
+ }
+ // match: (XOR x x)
+ // result: (MOVDconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (XOR <t> x g:(MOVDload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (XORload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVDload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XXORload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XXORW(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XORW x (MOVDconst [c]))
+ // result: (XORWconst [int32(c)] x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpS390XMOVDconst {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpS390XXORWconst)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORW (SLWconst x [c]) (SRWconst x [32-c]))
+ // result: (RLLconst x [c])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpS390XSLWconst {
+ continue
+ }
+ c := auxIntToUint8(v_0.AuxInt)
+ x := v_0.Args[0]
+ if v_1.Op != OpS390XSRWconst || auxIntToUint8(v_1.AuxInt) != 32-c || x != v_1.Args[0] {
+ continue
+ }
+ v.reset(OpS390XRLLconst)
+ v.AuxInt = uint8ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (XORW x x)
+ // result: (MOVDconst [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (XORW <t> x g:(MOVWload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (XORWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XXORWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ // match: (XORW <t> x g:(MOVWZload [off] {sym} ptr mem))
+ // cond: ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)
+ // result: (XORWload <t> [off] {sym} x ptr mem)
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ g := v_1
+ if g.Op != OpS390XMOVWZload {
+ continue
+ }
+ off := auxIntToInt32(g.AuxInt)
+ sym := auxToSym(g.Aux)
+ mem := g.Args[1]
+ ptr := g.Args[0]
+ if !(ptr.Op != OpSB && is20Bit(int64(off)) && canMergeLoadClobber(v, g, x) && clobber(g)) {
+ continue
+ }
+ v.reset(OpS390XXORWload)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(off)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XXORWconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (XORWconst [c] x)
+ // cond: int32(c)==0
+ // result: x
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if !(int32(c) == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (XORWconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [int64(c)^d])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(int64(c) ^ d)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XXORWload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (XORWload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (XORWload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XXORWload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (XORWload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (XORWload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XXORWload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XXORconst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (XORconst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (XORconst [c] (MOVDconst [d]))
+ // result: (MOVDconst [c^d])
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(c ^ d)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpS390XXORload(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (XORload <t> [off] {sym} x ptr1 (FMOVDstore [off] {sym} ptr2 y _))
+ // cond: isSamePtr(ptr1, ptr2)
+ // result: (XOR x (LGDR <t> y))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ ptr1 := v_1
+ if v_2.Op != OpS390XFMOVDstore || auxIntToInt32(v_2.AuxInt) != off || auxToSym(v_2.Aux) != sym {
+ break
+ }
+ y := v_2.Args[1]
+ ptr2 := v_2.Args[0]
+ if !(isSamePtr(ptr1, ptr2)) {
+ break
+ }
+ v.reset(OpS390XXOR)
+ v0 := b.NewValue0(v_2.Pos, OpS390XLGDR, t)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (XORload [off1] {sym} x (ADDconst [off2] ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))
+ // result: (XORload [off1+off2] {sym} x ptr mem)
+ for {
+ off1 := auxIntToInt32(v.AuxInt)
+ sym := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XADDconst {
+ break
+ }
+ off2 := auxIntToInt32(v_1.AuxInt)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(off1)+int64(off2))) {
+ break
+ }
+ v.reset(OpS390XXORload)
+ v.AuxInt = int32ToAuxInt(off1 + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ // match: (XORload [o1] {s1} x (MOVDaddr [o2] {s2} ptr) mem)
+ // cond: ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)
+ // result: (XORload [o1+o2] {mergeSym(s1, s2)} x ptr mem)
+ for {
+ o1 := auxIntToInt32(v.AuxInt)
+ s1 := auxToSym(v.Aux)
+ x := v_0
+ if v_1.Op != OpS390XMOVDaddr {
+ break
+ }
+ o2 := auxIntToInt32(v_1.AuxInt)
+ s2 := auxToSym(v_1.Aux)
+ ptr := v_1.Args[0]
+ mem := v_2
+ if !(ptr.Op != OpSB && is20Bit(int64(o1)+int64(o2)) && canMergeSym(s1, s2)) {
+ break
+ }
+ v.reset(OpS390XXORload)
+ v.AuxInt = int32ToAuxInt(o1 + o2)
+ v.Aux = symToAux(mergeSym(s1, s2))
+ v.AddArg3(x, ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpSelect0(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select0 (Add64carry x y c))
+ // result: (Select0 <typ.UInt64> (ADDE x y (Select1 <types.TypeFlags> (ADDCconst c [-1]))))
+ for {
+ if v_0.Op != OpAdd64carry {
+ break
+ }
+ c := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpSelect0)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpS390XADDE, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v2 := b.NewValue0(v.Pos, OpS390XADDCconst, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v2.AuxInt = int16ToAuxInt(-1)
+ v2.AddArg(c)
+ v1.AddArg(v2)
+ v0.AddArg3(x, y, v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select0 (Sub64borrow x y c))
+ // result: (Select0 <typ.UInt64> (SUBE x y (Select1 <types.TypeFlags> (SUBC (MOVDconst [0]) c))))
+ for {
+ if v_0.Op != OpSub64borrow {
+ break
+ }
+ c := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpSelect0)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpS390XSUBE, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v2 := b.NewValue0(v.Pos, OpS390XSUBC, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v3 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(0)
+ v2.AddArg2(v3, c)
+ v1.AddArg(v2)
+ v0.AddArg3(x, y, v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select0 <t> (AddTupleFirst32 val tuple))
+ // result: (ADDW val (Select0 <t> tuple))
+ for {
+ t := v.Type
+ if v_0.Op != OpS390XAddTupleFirst32 {
+ break
+ }
+ tuple := v_0.Args[1]
+ val := v_0.Args[0]
+ v.reset(OpS390XADDW)
+ v0 := b.NewValue0(v.Pos, OpSelect0, t)
+ v0.AddArg(tuple)
+ v.AddArg2(val, v0)
+ return true
+ }
+ // match: (Select0 <t> (AddTupleFirst64 val tuple))
+ // result: (ADD val (Select0 <t> tuple))
+ for {
+ t := v.Type
+ if v_0.Op != OpS390XAddTupleFirst64 {
+ break
+ }
+ tuple := v_0.Args[1]
+ val := v_0.Args[0]
+ v.reset(OpS390XADD)
+ v0 := b.NewValue0(v.Pos, OpSelect0, t)
+ v0.AddArg(tuple)
+ v.AddArg2(val, v0)
+ return true
+ }
+ // match: (Select0 (ADDCconst (MOVDconst [c]) [d]))
+ // result: (MOVDconst [c+int64(d)])
+ for {
+ if v_0.Op != OpS390XADDCconst {
+ break
+ }
+ d := auxIntToInt16(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(c + int64(d))
+ return true
+ }
+ // match: (Select0 (SUBC (MOVDconst [c]) (MOVDconst [d])))
+ // result: (MOVDconst [c-d])
+ for {
+ if v_0.Op != OpS390XSUBC {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0_1.AuxInt)
+ v.reset(OpS390XMOVDconst)
+ v.AuxInt = int64ToAuxInt(c - d)
+ return true
+ }
+ // match: (Select0 (FADD (FMUL y z) x))
+ // result: (FMADD x y z)
+ for {
+ if v_0.Op != OpS390XFADD {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpS390XFMUL {
+ continue
+ }
+ z := v_0_0.Args[1]
+ y := v_0_0.Args[0]
+ x := v_0_1
+ v.reset(OpS390XFMADD)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (Select0 (FSUB (FMUL y z) x))
+ // result: (FMSUB x y z)
+ for {
+ if v_0.Op != OpS390XFSUB {
+ break
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XFMUL {
+ break
+ }
+ z := v_0_0.Args[1]
+ y := v_0_0.Args[0]
+ v.reset(OpS390XFMSUB)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ // match: (Select0 (FADDS (FMULS y z) x))
+ // result: (FMADDS x y z)
+ for {
+ if v_0.Op != OpS390XFADDS {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpS390XFMULS {
+ continue
+ }
+ z := v_0_0.Args[1]
+ y := v_0_0.Args[0]
+ x := v_0_1
+ v.reset(OpS390XFMADDS)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ break
+ }
+ // match: (Select0 (FSUBS (FMULS y z) x))
+ // result: (FMSUBS x y z)
+ for {
+ if v_0.Op != OpS390XFSUBS {
+ break
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XFMULS {
+ break
+ }
+ z := v_0_0.Args[1]
+ y := v_0_0.Args[0]
+ v.reset(OpS390XFMSUBS)
+ v.AddArg3(x, y, z)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpSelect1(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Select1 (Add64carry x y c))
+ // result: (Select0 <typ.UInt64> (ADDE (MOVDconst [0]) (MOVDconst [0]) (Select1 <types.TypeFlags> (ADDE x y (Select1 <types.TypeFlags> (ADDCconst c [-1]))))))
+ for {
+ if v_0.Op != OpAdd64carry {
+ break
+ }
+ c := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpSelect0)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpS390XADDE, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v3 := b.NewValue0(v.Pos, OpS390XADDE, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v4 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v5 := b.NewValue0(v.Pos, OpS390XADDCconst, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v5.AuxInt = int16ToAuxInt(-1)
+ v5.AddArg(c)
+ v4.AddArg(v5)
+ v3.AddArg3(x, y, v4)
+ v2.AddArg(v3)
+ v0.AddArg3(v1, v1, v2)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select1 (Sub64borrow x y c))
+ // result: (NEG (Select0 <typ.UInt64> (SUBE (MOVDconst [0]) (MOVDconst [0]) (Select1 <types.TypeFlags> (SUBE x y (Select1 <types.TypeFlags> (SUBC (MOVDconst [0]) c)))))))
+ for {
+ if v_0.Op != OpSub64borrow {
+ break
+ }
+ c := v_0.Args[2]
+ x := v_0.Args[0]
+ y := v_0.Args[1]
+ v.reset(OpS390XNEG)
+ v0 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpS390XSUBE, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v3 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpS390XSUBE, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v5 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v6 := b.NewValue0(v.Pos, OpS390XSUBC, types.NewTuple(typ.UInt64, types.TypeFlags))
+ v6.AddArg2(v2, c)
+ v5.AddArg(v6)
+ v4.AddArg3(x, y, v5)
+ v3.AddArg(v4)
+ v1.AddArg3(v2, v2, v3)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Select1 (AddTupleFirst32 _ tuple))
+ // result: (Select1 tuple)
+ for {
+ if v_0.Op != OpS390XAddTupleFirst32 {
+ break
+ }
+ tuple := v_0.Args[1]
+ v.reset(OpSelect1)
+ v.AddArg(tuple)
+ return true
+ }
+ // match: (Select1 (AddTupleFirst64 _ tuple))
+ // result: (Select1 tuple)
+ for {
+ if v_0.Op != OpS390XAddTupleFirst64 {
+ break
+ }
+ tuple := v_0.Args[1]
+ v.reset(OpSelect1)
+ v.AddArg(tuple)
+ return true
+ }
+ // match: (Select1 (ADDCconst (MOVDconst [c]) [d]))
+ // cond: uint64(c+int64(d)) >= uint64(c) && c+int64(d) == 0
+ // result: (FlagEQ)
+ for {
+ if v_0.Op != OpS390XADDCconst {
+ break
+ }
+ d := auxIntToInt16(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if !(uint64(c+int64(d)) >= uint64(c) && c+int64(d) == 0) {
+ break
+ }
+ v.reset(OpS390XFlagEQ)
+ return true
+ }
+ // match: (Select1 (ADDCconst (MOVDconst [c]) [d]))
+ // cond: uint64(c+int64(d)) >= uint64(c) && c+int64(d) != 0
+ // result: (FlagLT)
+ for {
+ if v_0.Op != OpS390XADDCconst {
+ break
+ }
+ d := auxIntToInt16(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if !(uint64(c+int64(d)) >= uint64(c) && c+int64(d) != 0) {
+ break
+ }
+ v.reset(OpS390XFlagLT)
+ return true
+ }
+ // match: (Select1 (SUBC (MOVDconst [c]) (MOVDconst [d])))
+ // cond: uint64(d) <= uint64(c) && c-d == 0
+ // result: (FlagGT)
+ for {
+ if v_0.Op != OpS390XSUBC {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0_1.AuxInt)
+ if !(uint64(d) <= uint64(c) && c-d == 0) {
+ break
+ }
+ v.reset(OpS390XFlagGT)
+ return true
+ }
+ // match: (Select1 (SUBC (MOVDconst [c]) (MOVDconst [d])))
+ // cond: uint64(d) <= uint64(c) && c-d != 0
+ // result: (FlagOV)
+ for {
+ if v_0.Op != OpS390XSUBC {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XMOVDconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpS390XMOVDconst {
+ break
+ }
+ d := auxIntToInt64(v_0_1.AuxInt)
+ if !(uint64(d) <= uint64(c) && c-d != 0) {
+ break
+ }
+ v.reset(OpS390XFlagOV)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Slicemask <t> x)
+ // result: (SRADconst (NEG <t> x) [63])
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpS390XSRADconst)
+ v.AuxInt = uint8ToAuxInt(63)
+ v0 := b.NewValue0(v.Pos, OpS390XNEG, t)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8 && is64BitFloat(val.Type)
+ // result: (FMOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8 && is64BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpS390XFMOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4 && is32BitFloat(val.Type)
+ // result: (FMOVSstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4 && is32BitFloat(val.Type)) {
+ break
+ }
+ v.reset(OpS390XFMOVSstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8
+ // result: (MOVDstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8) {
+ break
+ }
+ v.reset(OpS390XMOVDstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4
+ // result: (MOVWstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4) {
+ break
+ }
+ v.reset(OpS390XMOVWstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 2
+ // result: (MOVHstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 2) {
+ break
+ }
+ v.reset(OpS390XMOVHstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 1
+ // result: (MOVBstore ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 1) {
+ break
+ }
+ v.reset(OpS390XMOVBstore)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueS390X_OpSub32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Sub32F x y)
+ // result: (Select0 (FSUBS x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpS390XFSUBS, types.NewTuple(typ.Float32, types.TypeFlags))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpSub64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Sub64F x y)
+ // result: (Select0 (FSUB x y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpSelect0)
+ v0 := b.NewValue0(v.Pos, OpS390XFSUB, types.NewTuple(typ.Float64, types.TypeFlags))
+ v0.AddArg2(x, y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueS390X_OpTrunc(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc x)
+ // result: (FIDBR [5] x)
+ for {
+ x := v_0
+ v.reset(OpS390XFIDBR)
+ v.AuxInt = int8ToAuxInt(5)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValueS390X_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Zero [0] _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_1
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero [1] destptr mem)
+ // result: (MOVBstoreconst [0] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(0)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [2] destptr mem)
+ // result: (MOVHstoreconst [0] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVHstoreconst)
+ v.AuxInt = valAndOffToAuxInt(0)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [4] destptr mem)
+ // result: (MOVWstoreconst [0] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(0)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [8] destptr mem)
+ // result: (MOVDstoreconst [0] destptr mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVDstoreconst)
+ v.AuxInt = valAndOffToAuxInt(0)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [3] destptr mem)
+ // result: (MOVBstoreconst [makeValAndOff32(0,2)] destptr (MOVHstoreconst [0] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 2))
+ v0 := b.NewValue0(v.Pos, OpS390XMOVHstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(0)
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [5] destptr mem)
+ // result: (MOVBstoreconst [makeValAndOff32(0,4)] destptr (MOVWstoreconst [0] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVBstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 4))
+ v0 := b.NewValue0(v.Pos, OpS390XMOVWstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(0)
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [6] destptr mem)
+ // result: (MOVHstoreconst [makeValAndOff32(0,4)] destptr (MOVWstoreconst [0] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVHstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 4))
+ v0 := b.NewValue0(v.Pos, OpS390XMOVWstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(0)
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [7] destptr mem)
+ // result: (MOVWstoreconst [makeValAndOff32(0,3)] destptr (MOVWstoreconst [0] destptr mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpS390XMOVWstoreconst)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(0, 3))
+ v0 := b.NewValue0(v.Pos, OpS390XMOVWstoreconst, types.TypeMem)
+ v0.AuxInt = valAndOffToAuxInt(0)
+ v0.AddArg2(destptr, mem)
+ v.AddArg2(destptr, v0)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s > 0 && s <= 1024
+ // result: (CLEAR [makeValAndOff32(int32(s), 0)] destptr mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s > 0 && s <= 1024) {
+ break
+ }
+ v.reset(OpS390XCLEAR)
+ v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(s), 0))
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s > 1024
+ // result: (LoweredZero [s%256] destptr (ADDconst <destptr.Type> destptr [(int32(s)/256)*256]) mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s > 1024) {
+ break
+ }
+ v.reset(OpS390XLoweredZero)
+ v.AuxInt = int64ToAuxInt(s % 256)
+ v0 := b.NewValue0(v.Pos, OpS390XADDconst, destptr.Type)
+ v0.AuxInt = int32ToAuxInt((int32(s) / 256) * 256)
+ v0.AddArg(destptr)
+ v.AddArg3(destptr, v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteBlockS390X(b *Block) bool {
+ typ := &b.Func.Config.Types
+ switch b.Kind {
+ case BlockS390XBRC:
+ // match: (BRC {c} x:(CMP _ _) yes no)
+ // cond: c&s390x.Unordered != 0
+ // result: (BRC {c&^s390x.Unordered} x yes no)
+ for b.Controls[0].Op == OpS390XCMP {
+ x := b.Controls[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Unordered != 0) {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, x)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} x:(CMPW _ _) yes no)
+ // cond: c&s390x.Unordered != 0
+ // result: (BRC {c&^s390x.Unordered} x yes no)
+ for b.Controls[0].Op == OpS390XCMPW {
+ x := b.Controls[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Unordered != 0) {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, x)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} x:(CMPU _ _) yes no)
+ // cond: c&s390x.Unordered != 0
+ // result: (BRC {c&^s390x.Unordered} x yes no)
+ for b.Controls[0].Op == OpS390XCMPU {
+ x := b.Controls[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Unordered != 0) {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, x)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} x:(CMPWU _ _) yes no)
+ // cond: c&s390x.Unordered != 0
+ // result: (BRC {c&^s390x.Unordered} x yes no)
+ for b.Controls[0].Op == OpS390XCMPWU {
+ x := b.Controls[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Unordered != 0) {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, x)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} x:(CMPconst _) yes no)
+ // cond: c&s390x.Unordered != 0
+ // result: (BRC {c&^s390x.Unordered} x yes no)
+ for b.Controls[0].Op == OpS390XCMPconst {
+ x := b.Controls[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Unordered != 0) {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, x)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} x:(CMPWconst _) yes no)
+ // cond: c&s390x.Unordered != 0
+ // result: (BRC {c&^s390x.Unordered} x yes no)
+ for b.Controls[0].Op == OpS390XCMPWconst {
+ x := b.Controls[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Unordered != 0) {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, x)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} x:(CMPUconst _) yes no)
+ // cond: c&s390x.Unordered != 0
+ // result: (BRC {c&^s390x.Unordered} x yes no)
+ for b.Controls[0].Op == OpS390XCMPUconst {
+ x := b.Controls[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Unordered != 0) {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, x)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} x:(CMPWUconst _) yes no)
+ // cond: c&s390x.Unordered != 0
+ // result: (BRC {c&^s390x.Unordered} x yes no)
+ for b.Controls[0].Op == OpS390XCMPWUconst {
+ x := b.Controls[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Unordered != 0) {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, x)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} (CMP x y) yes no)
+ // result: (CGRJ {c&^s390x.Unordered} x y yes no)
+ for b.Controls[0].Op == OpS390XCMP {
+ v_0 := b.Controls[0]
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ b.resetWithControl2(BlockS390XCGRJ, x, y)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} (CMPW x y) yes no)
+ // result: (CRJ {c&^s390x.Unordered} x y yes no)
+ for b.Controls[0].Op == OpS390XCMPW {
+ v_0 := b.Controls[0]
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ b.resetWithControl2(BlockS390XCRJ, x, y)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} (CMPU x y) yes no)
+ // result: (CLGRJ {c&^s390x.Unordered} x y yes no)
+ for b.Controls[0].Op == OpS390XCMPU {
+ v_0 := b.Controls[0]
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ b.resetWithControl2(BlockS390XCLGRJ, x, y)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} (CMPWU x y) yes no)
+ // result: (CLRJ {c&^s390x.Unordered} x y yes no)
+ for b.Controls[0].Op == OpS390XCMPWU {
+ v_0 := b.Controls[0]
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ b.resetWithControl2(BlockS390XCLRJ, x, y)
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} (CMPconst x [y]) yes no)
+ // cond: y == int32( int8(y))
+ // result: (CGIJ {c&^s390x.Unordered} x [ int8(y)] yes no)
+ for b.Controls[0].Op == OpS390XCMPconst {
+ v_0 := b.Controls[0]
+ y := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(y == int32(int8(y))) {
+ break
+ }
+ b.resetWithControl(BlockS390XCGIJ, x)
+ b.AuxInt = int8ToAuxInt(int8(y))
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} (CMPWconst x [y]) yes no)
+ // cond: y == int32( int8(y))
+ // result: (CIJ {c&^s390x.Unordered} x [ int8(y)] yes no)
+ for b.Controls[0].Op == OpS390XCMPWconst {
+ v_0 := b.Controls[0]
+ y := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(y == int32(int8(y))) {
+ break
+ }
+ b.resetWithControl(BlockS390XCIJ, x)
+ b.AuxInt = int8ToAuxInt(int8(y))
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} (CMPUconst x [y]) yes no)
+ // cond: y == int32(uint8(y))
+ // result: (CLGIJ {c&^s390x.Unordered} x [uint8(y)] yes no)
+ for b.Controls[0].Op == OpS390XCMPUconst {
+ v_0 := b.Controls[0]
+ y := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(y == int32(uint8(y))) {
+ break
+ }
+ b.resetWithControl(BlockS390XCLGIJ, x)
+ b.AuxInt = uint8ToAuxInt(uint8(y))
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {c} (CMPWUconst x [y]) yes no)
+ // cond: y == int32(uint8(y))
+ // result: (CLIJ {c&^s390x.Unordered} x [uint8(y)] yes no)
+ for b.Controls[0].Op == OpS390XCMPWUconst {
+ v_0 := b.Controls[0]
+ y := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(y == int32(uint8(y))) {
+ break
+ }
+ b.resetWithControl(BlockS390XCLIJ, x)
+ b.AuxInt = uint8ToAuxInt(uint8(y))
+ b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered)
+ return true
+ }
+ // match: (BRC {s390x.Less} (CMPconst x [ 128]) yes no)
+ // result: (CGIJ {s390x.LessOrEqual} x [ 127] yes no)
+ for b.Controls[0].Op == OpS390XCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 128 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.Less {
+ break
+ }
+ b.resetWithControl(BlockS390XCGIJ, x)
+ b.AuxInt = int8ToAuxInt(127)
+ b.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ return true
+ }
+ // match: (BRC {s390x.Less} (CMPWconst x [ 128]) yes no)
+ // result: (CIJ {s390x.LessOrEqual} x [ 127] yes no)
+ for b.Controls[0].Op == OpS390XCMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 128 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.Less {
+ break
+ }
+ b.resetWithControl(BlockS390XCIJ, x)
+ b.AuxInt = int8ToAuxInt(127)
+ b.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ return true
+ }
+ // match: (BRC {s390x.LessOrEqual} (CMPconst x [-129]) yes no)
+ // result: (CGIJ {s390x.Less} x [-128] yes no)
+ for b.Controls[0].Op == OpS390XCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != -129 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.LessOrEqual {
+ break
+ }
+ b.resetWithControl(BlockS390XCGIJ, x)
+ b.AuxInt = int8ToAuxInt(-128)
+ b.Aux = s390xCCMaskToAux(s390x.Less)
+ return true
+ }
+ // match: (BRC {s390x.LessOrEqual} (CMPWconst x [-129]) yes no)
+ // result: (CIJ {s390x.Less} x [-128] yes no)
+ for b.Controls[0].Op == OpS390XCMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != -129 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.LessOrEqual {
+ break
+ }
+ b.resetWithControl(BlockS390XCIJ, x)
+ b.AuxInt = int8ToAuxInt(-128)
+ b.Aux = s390xCCMaskToAux(s390x.Less)
+ return true
+ }
+ // match: (BRC {s390x.Greater} (CMPconst x [-129]) yes no)
+ // result: (CGIJ {s390x.GreaterOrEqual} x [-128] yes no)
+ for b.Controls[0].Op == OpS390XCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != -129 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.Greater {
+ break
+ }
+ b.resetWithControl(BlockS390XCGIJ, x)
+ b.AuxInt = int8ToAuxInt(-128)
+ b.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ return true
+ }
+ // match: (BRC {s390x.Greater} (CMPWconst x [-129]) yes no)
+ // result: (CIJ {s390x.GreaterOrEqual} x [-128] yes no)
+ for b.Controls[0].Op == OpS390XCMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != -129 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.Greater {
+ break
+ }
+ b.resetWithControl(BlockS390XCIJ, x)
+ b.AuxInt = int8ToAuxInt(-128)
+ b.Aux = s390xCCMaskToAux(s390x.GreaterOrEqual)
+ return true
+ }
+ // match: (BRC {s390x.GreaterOrEqual} (CMPconst x [ 128]) yes no)
+ // result: (CGIJ {s390x.Greater} x [ 127] yes no)
+ for b.Controls[0].Op == OpS390XCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 128 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.GreaterOrEqual {
+ break
+ }
+ b.resetWithControl(BlockS390XCGIJ, x)
+ b.AuxInt = int8ToAuxInt(127)
+ b.Aux = s390xCCMaskToAux(s390x.Greater)
+ return true
+ }
+ // match: (BRC {s390x.GreaterOrEqual} (CMPWconst x [ 128]) yes no)
+ // result: (CIJ {s390x.Greater} x [ 127] yes no)
+ for b.Controls[0].Op == OpS390XCMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 128 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.GreaterOrEqual {
+ break
+ }
+ b.resetWithControl(BlockS390XCIJ, x)
+ b.AuxInt = int8ToAuxInt(127)
+ b.Aux = s390xCCMaskToAux(s390x.Greater)
+ return true
+ }
+ // match: (BRC {s390x.Less} (CMPWUconst x [256]) yes no)
+ // result: (CLIJ {s390x.LessOrEqual} x [255] yes no)
+ for b.Controls[0].Op == OpS390XCMPWUconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 256 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.Less {
+ break
+ }
+ b.resetWithControl(BlockS390XCLIJ, x)
+ b.AuxInt = uint8ToAuxInt(255)
+ b.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ return true
+ }
+ // match: (BRC {s390x.Less} (CMPUconst x [256]) yes no)
+ // result: (CLGIJ {s390x.LessOrEqual} x [255] yes no)
+ for b.Controls[0].Op == OpS390XCMPUconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 256 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.Less {
+ break
+ }
+ b.resetWithControl(BlockS390XCLGIJ, x)
+ b.AuxInt = uint8ToAuxInt(255)
+ b.Aux = s390xCCMaskToAux(s390x.LessOrEqual)
+ return true
+ }
+ // match: (BRC {s390x.GreaterOrEqual} (CMPWUconst x [256]) yes no)
+ // result: (CLIJ {s390x.Greater} x [255] yes no)
+ for b.Controls[0].Op == OpS390XCMPWUconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 256 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.GreaterOrEqual {
+ break
+ }
+ b.resetWithControl(BlockS390XCLIJ, x)
+ b.AuxInt = uint8ToAuxInt(255)
+ b.Aux = s390xCCMaskToAux(s390x.Greater)
+ return true
+ }
+ // match: (BRC {s390x.GreaterOrEqual} (CMPUconst x [256]) yes no)
+ // result: (CLGIJ {s390x.Greater} x [255] yes no)
+ for b.Controls[0].Op == OpS390XCMPUconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 256 {
+ break
+ }
+ x := v_0.Args[0]
+ if auxToS390xCCMask(b.Aux) != s390x.GreaterOrEqual {
+ break
+ }
+ b.resetWithControl(BlockS390XCLGIJ, x)
+ b.AuxInt = uint8ToAuxInt(255)
+ b.Aux = s390xCCMaskToAux(s390x.Greater)
+ return true
+ }
+ // match: (BRC {c} (CMPconst x [y]) yes no)
+ // cond: y == int32(uint8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)
+ // result: (CLGIJ {c} x [uint8(y)] yes no)
+ for b.Controls[0].Op == OpS390XCMPconst {
+ v_0 := b.Controls[0]
+ y := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(y == int32(uint8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCLGIJ, x)
+ b.AuxInt = uint8ToAuxInt(uint8(y))
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (BRC {c} (CMPWconst x [y]) yes no)
+ // cond: y == int32(uint8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)
+ // result: (CLIJ {c} x [uint8(y)] yes no)
+ for b.Controls[0].Op == OpS390XCMPWconst {
+ v_0 := b.Controls[0]
+ y := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(y == int32(uint8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCLIJ, x)
+ b.AuxInt = uint8ToAuxInt(uint8(y))
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (BRC {c} (CMPUconst x [y]) yes no)
+ // cond: y == int32( int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)
+ // result: (CGIJ {c} x [ int8(y)] yes no)
+ for b.Controls[0].Op == OpS390XCMPUconst {
+ v_0 := b.Controls[0]
+ y := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(y == int32(int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCGIJ, x)
+ b.AuxInt = int8ToAuxInt(int8(y))
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (BRC {c} (CMPWUconst x [y]) yes no)
+ // cond: y == int32( int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)
+ // result: (CIJ {c} x [ int8(y)] yes no)
+ for b.Controls[0].Op == OpS390XCMPWUconst {
+ v_0 := b.Controls[0]
+ y := auxIntToInt32(v_0.AuxInt)
+ x := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ if !(y == int32(int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCIJ, x)
+ b.AuxInt = int8ToAuxInt(int8(y))
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (BRC {c} (InvertFlags cmp) yes no)
+ // result: (BRC {c.ReverseComparison()} cmp yes no)
+ for b.Controls[0].Op == OpS390XInvertFlags {
+ v_0 := b.Controls[0]
+ cmp := v_0.Args[0]
+ c := auxToS390xCCMask(b.Aux)
+ b.resetWithControl(BlockS390XBRC, cmp)
+ b.Aux = s390xCCMaskToAux(c.ReverseComparison())
+ return true
+ }
+ // match: (BRC {c} (FlagEQ) yes no)
+ // cond: c&s390x.Equal != 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XFlagEQ {
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Equal != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (BRC {c} (FlagLT) yes no)
+ // cond: c&s390x.Less != 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XFlagLT {
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Less != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (BRC {c} (FlagGT) yes no)
+ // cond: c&s390x.Greater != 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XFlagGT {
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Greater != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (BRC {c} (FlagOV) yes no)
+ // cond: c&s390x.Unordered != 0
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XFlagOV {
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Unordered != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (BRC {c} (FlagEQ) yes no)
+ // cond: c&s390x.Equal == 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XFlagEQ {
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Equal == 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (BRC {c} (FlagLT) yes no)
+ // cond: c&s390x.Less == 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XFlagLT {
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Less == 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (BRC {c} (FlagGT) yes no)
+ // cond: c&s390x.Greater == 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XFlagGT {
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Greater == 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (BRC {c} (FlagOV) yes no)
+ // cond: c&s390x.Unordered == 0
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XFlagOV {
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Unordered == 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockS390XCGIJ:
+ // match: (CGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Equal != 0 && int64(x) == int64(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Equal != 0 && int64(x) == int64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Less != 0 && int64(x) < int64(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Less != 0 && int64(x) < int64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Greater != 0 && int64(x) > int64(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Greater != 0 && int64(x) > int64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Equal == 0 && int64(x) == int64(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Equal == 0 && int64(x) == int64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Less == 0 && int64(x) < int64(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Less == 0 && int64(x) < int64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Greater == 0 && int64(x) > int64(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Greater == 0 && int64(x) > int64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CGIJ {s390x.Equal} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [0])
+ // result: (BRC {s390x.NoCarry} carry)
+ for b.Controls[0].Op == OpSelect0 {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XADDE {
+ break
+ }
+ carry := v_0_0.Args[2]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_1.AuxInt) != 0 || auxIntToInt8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.Equal {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, carry)
+ b.Aux = s390xCCMaskToAux(s390x.NoCarry)
+ return true
+ }
+ // match: (CGIJ {s390x.Equal} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [1])
+ // result: (BRC {s390x.Carry} carry)
+ for b.Controls[0].Op == OpSelect0 {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XADDE {
+ break
+ }
+ carry := v_0_0.Args[2]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_1.AuxInt) != 0 || auxIntToInt8(b.AuxInt) != 1 || auxToS390xCCMask(b.Aux) != s390x.Equal {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, carry)
+ b.Aux = s390xCCMaskToAux(s390x.Carry)
+ return true
+ }
+ // match: (CGIJ {s390x.LessOrGreater} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [0])
+ // result: (BRC {s390x.Carry} carry)
+ for b.Controls[0].Op == OpSelect0 {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XADDE {
+ break
+ }
+ carry := v_0_0.Args[2]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_1.AuxInt) != 0 || auxIntToInt8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.LessOrGreater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, carry)
+ b.Aux = s390xCCMaskToAux(s390x.Carry)
+ return true
+ }
+ // match: (CGIJ {s390x.LessOrGreater} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [1])
+ // result: (BRC {s390x.NoCarry} carry)
+ for b.Controls[0].Op == OpSelect0 {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XADDE {
+ break
+ }
+ carry := v_0_0.Args[2]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_1.AuxInt) != 0 || auxIntToInt8(b.AuxInt) != 1 || auxToS390xCCMask(b.Aux) != s390x.LessOrGreater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, carry)
+ b.Aux = s390xCCMaskToAux(s390x.NoCarry)
+ return true
+ }
+ // match: (CGIJ {s390x.Greater} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [0])
+ // result: (BRC {s390x.Carry} carry)
+ for b.Controls[0].Op == OpSelect0 {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XADDE {
+ break
+ }
+ carry := v_0_0.Args[2]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_1.AuxInt) != 0 || auxIntToInt8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.Greater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, carry)
+ b.Aux = s390xCCMaskToAux(s390x.Carry)
+ return true
+ }
+ // match: (CGIJ {s390x.Equal} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [0])
+ // result: (BRC {s390x.NoBorrow} borrow)
+ for b.Controls[0].Op == OpS390XNEG {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelect0 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XSUBE {
+ break
+ }
+ borrow := v_0_0_0.Args[2]
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_0_1 := v_0_0_0.Args[1]
+ if v_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_1.AuxInt) != 0 || auxIntToInt8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.Equal {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, borrow)
+ b.Aux = s390xCCMaskToAux(s390x.NoBorrow)
+ return true
+ }
+ // match: (CGIJ {s390x.Equal} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [1])
+ // result: (BRC {s390x.Borrow} borrow)
+ for b.Controls[0].Op == OpS390XNEG {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelect0 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XSUBE {
+ break
+ }
+ borrow := v_0_0_0.Args[2]
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_0_1 := v_0_0_0.Args[1]
+ if v_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_1.AuxInt) != 0 || auxIntToInt8(b.AuxInt) != 1 || auxToS390xCCMask(b.Aux) != s390x.Equal {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, borrow)
+ b.Aux = s390xCCMaskToAux(s390x.Borrow)
+ return true
+ }
+ // match: (CGIJ {s390x.LessOrGreater} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [0])
+ // result: (BRC {s390x.Borrow} borrow)
+ for b.Controls[0].Op == OpS390XNEG {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelect0 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XSUBE {
+ break
+ }
+ borrow := v_0_0_0.Args[2]
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_0_1 := v_0_0_0.Args[1]
+ if v_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_1.AuxInt) != 0 || auxIntToInt8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.LessOrGreater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, borrow)
+ b.Aux = s390xCCMaskToAux(s390x.Borrow)
+ return true
+ }
+ // match: (CGIJ {s390x.LessOrGreater} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [1])
+ // result: (BRC {s390x.NoBorrow} borrow)
+ for b.Controls[0].Op == OpS390XNEG {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelect0 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XSUBE {
+ break
+ }
+ borrow := v_0_0_0.Args[2]
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_0_1 := v_0_0_0.Args[1]
+ if v_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_1.AuxInt) != 0 || auxIntToInt8(b.AuxInt) != 1 || auxToS390xCCMask(b.Aux) != s390x.LessOrGreater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, borrow)
+ b.Aux = s390xCCMaskToAux(s390x.NoBorrow)
+ return true
+ }
+ // match: (CGIJ {s390x.Greater} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [0])
+ // result: (BRC {s390x.Borrow} borrow)
+ for b.Controls[0].Op == OpS390XNEG {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelect0 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XSUBE {
+ break
+ }
+ borrow := v_0_0_0.Args[2]
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_0_1 := v_0_0_0.Args[1]
+ if v_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_1.AuxInt) != 0 || auxIntToInt8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.Greater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, borrow)
+ b.Aux = s390xCCMaskToAux(s390x.Borrow)
+ return true
+ }
+ case BlockS390XCGRJ:
+ // match: (CGRJ {c} x (MOVDconst [y]) yes no)
+ // cond: is8Bit(y)
+ // result: (CGIJ {c} x [ int8(y)] yes no)
+ for b.Controls[1].Op == OpS390XMOVDconst {
+ x := b.Controls[0]
+ v_1 := b.Controls[1]
+ y := auxIntToInt64(v_1.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(is8Bit(y)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCGIJ, x)
+ b.AuxInt = int8ToAuxInt(int8(y))
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CGRJ {c} (MOVDconst [x]) y yes no)
+ // cond: is8Bit(x)
+ // result: (CGIJ {c.ReverseComparison()} y [ int8(x)] yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(is8Bit(x)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCGIJ, y)
+ b.AuxInt = int8ToAuxInt(int8(x))
+ b.Aux = s390xCCMaskToAux(c.ReverseComparison())
+ return true
+ }
+ // match: (CGRJ {c} x (MOVDconst [y]) yes no)
+ // cond: !is8Bit(y) && is32Bit(y)
+ // result: (BRC {c} (CMPconst x [int32(y)]) yes no)
+ for b.Controls[1].Op == OpS390XMOVDconst {
+ x := b.Controls[0]
+ v_1 := b.Controls[1]
+ y := auxIntToInt64(v_1.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(!is8Bit(y) && is32Bit(y)) {
+ break
+ }
+ v0 := b.NewValue0(x.Pos, OpS390XCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(y))
+ v0.AddArg(x)
+ b.resetWithControl(BlockS390XBRC, v0)
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CGRJ {c} (MOVDconst [x]) y yes no)
+ // cond: !is8Bit(x) && is32Bit(x)
+ // result: (BRC {c.ReverseComparison()} (CMPconst y [int32(x)]) yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(!is8Bit(x) && is32Bit(x)) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpS390XCMPconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(x))
+ v0.AddArg(y)
+ b.resetWithControl(BlockS390XBRC, v0)
+ b.Aux = s390xCCMaskToAux(c.ReverseComparison())
+ return true
+ }
+ // match: (CGRJ {c} x y yes no)
+ // cond: x == y && c&s390x.Equal != 0
+ // result: (First yes no)
+ for {
+ x := b.Controls[0]
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(x == y && c&s390x.Equal != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CGRJ {c} x y yes no)
+ // cond: x == y && c&s390x.Equal == 0
+ // result: (First no yes)
+ for {
+ x := b.Controls[0]
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(x == y && c&s390x.Equal == 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockS390XCIJ:
+ // match: (CIJ {c} (MOVWreg x) [y] yes no)
+ // result: (CIJ {c} x [y] yes no)
+ for b.Controls[0].Op == OpS390XMOVWreg {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ b.resetWithControl(BlockS390XCIJ, x)
+ b.AuxInt = int8ToAuxInt(y)
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CIJ {c} (MOVWZreg x) [y] yes no)
+ // result: (CIJ {c} x [y] yes no)
+ for b.Controls[0].Op == OpS390XMOVWZreg {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ b.resetWithControl(BlockS390XCIJ, x)
+ b.AuxInt = int8ToAuxInt(y)
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Equal != 0 && int32(x) == int32(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Equal != 0 && int32(x) == int32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Less != 0 && int32(x) < int32(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Less != 0 && int32(x) < int32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Greater != 0 && int32(x) > int32(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Greater != 0 && int32(x) > int32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Equal == 0 && int32(x) == int32(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Equal == 0 && int32(x) == int32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Less == 0 && int32(x) < int32(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Less == 0 && int32(x) < int32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Greater == 0 && int32(x) > int32(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToInt8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Greater == 0 && int32(x) > int32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockS390XCLGIJ:
+ // match: (CLGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Equal != 0 && uint64(x) == uint64(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Equal != 0 && uint64(x) == uint64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CLGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Less != 0 && uint64(x) < uint64(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Less != 0 && uint64(x) < uint64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CLGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Greater != 0 && uint64(x) > uint64(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Greater != 0 && uint64(x) > uint64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CLGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Equal == 0 && uint64(x) == uint64(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Equal == 0 && uint64(x) == uint64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CLGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Less == 0 && uint64(x) < uint64(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Less == 0 && uint64(x) < uint64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CLGIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Greater == 0 && uint64(x) > uint64(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Greater == 0 && uint64(x) > uint64(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CLGIJ {s390x.GreaterOrEqual} _ [0] yes no)
+ // result: (First yes no)
+ for {
+ if auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.GreaterOrEqual {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CLGIJ {s390x.Less} _ [0] yes no)
+ // result: (First no yes)
+ for {
+ if auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.Less {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CLGIJ {s390x.Equal} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [0])
+ // result: (BRC {s390x.NoCarry} carry)
+ for b.Controls[0].Op == OpSelect0 {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XADDE {
+ break
+ }
+ carry := v_0_0.Args[2]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_1.AuxInt) != 0 || auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.Equal {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, carry)
+ b.Aux = s390xCCMaskToAux(s390x.NoCarry)
+ return true
+ }
+ // match: (CLGIJ {s390x.Equal} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [1])
+ // result: (BRC {s390x.Carry} carry)
+ for b.Controls[0].Op == OpSelect0 {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XADDE {
+ break
+ }
+ carry := v_0_0.Args[2]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_1.AuxInt) != 0 || auxIntToUint8(b.AuxInt) != 1 || auxToS390xCCMask(b.Aux) != s390x.Equal {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, carry)
+ b.Aux = s390xCCMaskToAux(s390x.Carry)
+ return true
+ }
+ // match: (CLGIJ {s390x.LessOrGreater} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [0])
+ // result: (BRC {s390x.Carry} carry)
+ for b.Controls[0].Op == OpSelect0 {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XADDE {
+ break
+ }
+ carry := v_0_0.Args[2]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_1.AuxInt) != 0 || auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.LessOrGreater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, carry)
+ b.Aux = s390xCCMaskToAux(s390x.Carry)
+ return true
+ }
+ // match: (CLGIJ {s390x.LessOrGreater} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [1])
+ // result: (BRC {s390x.NoCarry} carry)
+ for b.Controls[0].Op == OpSelect0 {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XADDE {
+ break
+ }
+ carry := v_0_0.Args[2]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_1.AuxInt) != 0 || auxIntToUint8(b.AuxInt) != 1 || auxToS390xCCMask(b.Aux) != s390x.LessOrGreater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, carry)
+ b.Aux = s390xCCMaskToAux(s390x.NoCarry)
+ return true
+ }
+ // match: (CLGIJ {s390x.Greater} (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) carry)) [0])
+ // result: (BRC {s390x.Carry} carry)
+ for b.Controls[0].Op == OpSelect0 {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XADDE {
+ break
+ }
+ carry := v_0_0.Args[2]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_1.AuxInt) != 0 || auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.Greater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, carry)
+ b.Aux = s390xCCMaskToAux(s390x.Carry)
+ return true
+ }
+ // match: (CLGIJ {s390x.Equal} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [0])
+ // result: (BRC {s390x.NoBorrow} borrow)
+ for b.Controls[0].Op == OpS390XNEG {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelect0 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XSUBE {
+ break
+ }
+ borrow := v_0_0_0.Args[2]
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_0_1 := v_0_0_0.Args[1]
+ if v_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_1.AuxInt) != 0 || auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.Equal {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, borrow)
+ b.Aux = s390xCCMaskToAux(s390x.NoBorrow)
+ return true
+ }
+ // match: (CLGIJ {s390x.Equal} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [1])
+ // result: (BRC {s390x.Borrow} borrow)
+ for b.Controls[0].Op == OpS390XNEG {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelect0 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XSUBE {
+ break
+ }
+ borrow := v_0_0_0.Args[2]
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_0_1 := v_0_0_0.Args[1]
+ if v_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_1.AuxInt) != 0 || auxIntToUint8(b.AuxInt) != 1 || auxToS390xCCMask(b.Aux) != s390x.Equal {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, borrow)
+ b.Aux = s390xCCMaskToAux(s390x.Borrow)
+ return true
+ }
+ // match: (CLGIJ {s390x.LessOrGreater} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [0])
+ // result: (BRC {s390x.Borrow} borrow)
+ for b.Controls[0].Op == OpS390XNEG {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelect0 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XSUBE {
+ break
+ }
+ borrow := v_0_0_0.Args[2]
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_0_1 := v_0_0_0.Args[1]
+ if v_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_1.AuxInt) != 0 || auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.LessOrGreater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, borrow)
+ b.Aux = s390xCCMaskToAux(s390x.Borrow)
+ return true
+ }
+ // match: (CLGIJ {s390x.LessOrGreater} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [1])
+ // result: (BRC {s390x.NoBorrow} borrow)
+ for b.Controls[0].Op == OpS390XNEG {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelect0 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XSUBE {
+ break
+ }
+ borrow := v_0_0_0.Args[2]
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_0_1 := v_0_0_0.Args[1]
+ if v_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_1.AuxInt) != 0 || auxIntToUint8(b.AuxInt) != 1 || auxToS390xCCMask(b.Aux) != s390x.LessOrGreater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, borrow)
+ b.Aux = s390xCCMaskToAux(s390x.NoBorrow)
+ return true
+ }
+ // match: (CLGIJ {s390x.Greater} (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) borrow))) [0])
+ // result: (BRC {s390x.Borrow} borrow)
+ for b.Controls[0].Op == OpS390XNEG {
+ v_0 := b.Controls[0]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelect0 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpS390XSUBE {
+ break
+ }
+ borrow := v_0_0_0.Args[2]
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0_0_1 := v_0_0_0.Args[1]
+ if v_0_0_0_1.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0_0_1.AuxInt) != 0 || auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.Greater {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, borrow)
+ b.Aux = s390xCCMaskToAux(s390x.Borrow)
+ return true
+ }
+ case BlockS390XCLGRJ:
+ // match: (CLGRJ {c} x (MOVDconst [y]) yes no)
+ // cond: isU8Bit(y)
+ // result: (CLGIJ {c} x [uint8(y)] yes no)
+ for b.Controls[1].Op == OpS390XMOVDconst {
+ x := b.Controls[0]
+ v_1 := b.Controls[1]
+ y := auxIntToInt64(v_1.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(isU8Bit(y)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCLGIJ, x)
+ b.AuxInt = uint8ToAuxInt(uint8(y))
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CLGRJ {c} (MOVDconst [x]) y yes no)
+ // cond: isU8Bit(x)
+ // result: (CLGIJ {c.ReverseComparison()} y [uint8(x)] yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(isU8Bit(x)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCLGIJ, y)
+ b.AuxInt = uint8ToAuxInt(uint8(x))
+ b.Aux = s390xCCMaskToAux(c.ReverseComparison())
+ return true
+ }
+ // match: (CLGRJ {c} x (MOVDconst [y]) yes no)
+ // cond: !isU8Bit(y) && isU32Bit(y)
+ // result: (BRC {c} (CMPUconst x [int32(y)]) yes no)
+ for b.Controls[1].Op == OpS390XMOVDconst {
+ x := b.Controls[0]
+ v_1 := b.Controls[1]
+ y := auxIntToInt64(v_1.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(!isU8Bit(y) && isU32Bit(y)) {
+ break
+ }
+ v0 := b.NewValue0(x.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(y))
+ v0.AddArg(x)
+ b.resetWithControl(BlockS390XBRC, v0)
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CLGRJ {c} (MOVDconst [x]) y yes no)
+ // cond: !isU8Bit(x) && isU32Bit(x)
+ // result: (BRC {c.ReverseComparison()} (CMPUconst y [int32(x)]) yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(!isU8Bit(x) && isU32Bit(x)) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpS390XCMPUconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(x))
+ v0.AddArg(y)
+ b.resetWithControl(BlockS390XBRC, v0)
+ b.Aux = s390xCCMaskToAux(c.ReverseComparison())
+ return true
+ }
+ // match: (CLGRJ {c} x y yes no)
+ // cond: x == y && c&s390x.Equal != 0
+ // result: (First yes no)
+ for {
+ x := b.Controls[0]
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(x == y && c&s390x.Equal != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CLGRJ {c} x y yes no)
+ // cond: x == y && c&s390x.Equal == 0
+ // result: (First no yes)
+ for {
+ x := b.Controls[0]
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(x == y && c&s390x.Equal == 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockS390XCLIJ:
+ // match: (CLIJ {s390x.LessOrGreater} (LOCGR {d} (MOVDconst [0]) (MOVDconst [x]) cmp) [0] yes no)
+ // cond: int32(x) != 0
+ // result: (BRC {d} cmp yes no)
+ for b.Controls[0].Op == OpS390XLOCGR {
+ v_0 := b.Controls[0]
+ d := auxToS390xCCMask(v_0.Aux)
+ cmp := v_0.Args[2]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0.AuxInt) != 0 {
+ break
+ }
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpS390XMOVDconst {
+ break
+ }
+ x := auxIntToInt64(v_0_1.AuxInt)
+ if auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.LessOrGreater || !(int32(x) != 0) {
+ break
+ }
+ b.resetWithControl(BlockS390XBRC, cmp)
+ b.Aux = s390xCCMaskToAux(d)
+ return true
+ }
+ // match: (CLIJ {c} (MOVWreg x) [y] yes no)
+ // result: (CLIJ {c} x [y] yes no)
+ for b.Controls[0].Op == OpS390XMOVWreg {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ b.resetWithControl(BlockS390XCLIJ, x)
+ b.AuxInt = uint8ToAuxInt(y)
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CLIJ {c} (MOVWZreg x) [y] yes no)
+ // result: (CLIJ {c} x [y] yes no)
+ for b.Controls[0].Op == OpS390XMOVWZreg {
+ v_0 := b.Controls[0]
+ x := v_0.Args[0]
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ b.resetWithControl(BlockS390XCLIJ, x)
+ b.AuxInt = uint8ToAuxInt(y)
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CLIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Equal != 0 && uint32(x) == uint32(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Equal != 0 && uint32(x) == uint32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CLIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Less != 0 && uint32(x) < uint32(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Less != 0 && uint32(x) < uint32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CLIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Greater != 0 && uint32(x) > uint32(y)
+ // result: (First yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Greater != 0 && uint32(x) > uint32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CLIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Equal == 0 && uint32(x) == uint32(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Equal == 0 && uint32(x) == uint32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CLIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Less == 0 && uint32(x) < uint32(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Less == 0 && uint32(x) < uint32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CLIJ {c} (MOVDconst [x]) [y] yes no)
+ // cond: c&s390x.Greater == 0 && uint32(x) > uint32(y)
+ // result: (First no yes)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := auxIntToUint8(b.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(c&s390x.Greater == 0 && uint32(x) > uint32(y)) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (CLIJ {s390x.GreaterOrEqual} _ [0] yes no)
+ // result: (First yes no)
+ for {
+ if auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.GreaterOrEqual {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CLIJ {s390x.Less} _ [0] yes no)
+ // result: (First no yes)
+ for {
+ if auxIntToUint8(b.AuxInt) != 0 || auxToS390xCCMask(b.Aux) != s390x.Less {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockS390XCLRJ:
+ // match: (CLRJ {c} x (MOVDconst [y]) yes no)
+ // cond: isU8Bit(y)
+ // result: (CLIJ {c} x [uint8(y)] yes no)
+ for b.Controls[1].Op == OpS390XMOVDconst {
+ x := b.Controls[0]
+ v_1 := b.Controls[1]
+ y := auxIntToInt64(v_1.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(isU8Bit(y)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCLIJ, x)
+ b.AuxInt = uint8ToAuxInt(uint8(y))
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CLRJ {c} (MOVDconst [x]) y yes no)
+ // cond: isU8Bit(x)
+ // result: (CLIJ {c.ReverseComparison()} y [uint8(x)] yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(isU8Bit(x)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCLIJ, y)
+ b.AuxInt = uint8ToAuxInt(uint8(x))
+ b.Aux = s390xCCMaskToAux(c.ReverseComparison())
+ return true
+ }
+ // match: (CLRJ {c} x (MOVDconst [y]) yes no)
+ // cond: !isU8Bit(y) && isU32Bit(y)
+ // result: (BRC {c} (CMPWUconst x [int32(y)]) yes no)
+ for b.Controls[1].Op == OpS390XMOVDconst {
+ x := b.Controls[0]
+ v_1 := b.Controls[1]
+ y := auxIntToInt64(v_1.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(!isU8Bit(y) && isU32Bit(y)) {
+ break
+ }
+ v0 := b.NewValue0(x.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(y))
+ v0.AddArg(x)
+ b.resetWithControl(BlockS390XBRC, v0)
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CLRJ {c} (MOVDconst [x]) y yes no)
+ // cond: !isU8Bit(x) && isU32Bit(x)
+ // result: (BRC {c.ReverseComparison()} (CMPWUconst y [int32(x)]) yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(!isU8Bit(x) && isU32Bit(x)) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpS390XCMPWUconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(x))
+ v0.AddArg(y)
+ b.resetWithControl(BlockS390XBRC, v0)
+ b.Aux = s390xCCMaskToAux(c.ReverseComparison())
+ return true
+ }
+ // match: (CLRJ {c} x y yes no)
+ // cond: x == y && c&s390x.Equal != 0
+ // result: (First yes no)
+ for {
+ x := b.Controls[0]
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(x == y && c&s390x.Equal != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CLRJ {c} x y yes no)
+ // cond: x == y && c&s390x.Equal == 0
+ // result: (First no yes)
+ for {
+ x := b.Controls[0]
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(x == y && c&s390x.Equal == 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockS390XCRJ:
+ // match: (CRJ {c} x (MOVDconst [y]) yes no)
+ // cond: is8Bit(y)
+ // result: (CIJ {c} x [ int8(y)] yes no)
+ for b.Controls[1].Op == OpS390XMOVDconst {
+ x := b.Controls[0]
+ v_1 := b.Controls[1]
+ y := auxIntToInt64(v_1.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(is8Bit(y)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCIJ, x)
+ b.AuxInt = int8ToAuxInt(int8(y))
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CRJ {c} (MOVDconst [x]) y yes no)
+ // cond: is8Bit(x)
+ // result: (CIJ {c.ReverseComparison()} y [ int8(x)] yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(is8Bit(x)) {
+ break
+ }
+ b.resetWithControl(BlockS390XCIJ, y)
+ b.AuxInt = int8ToAuxInt(int8(x))
+ b.Aux = s390xCCMaskToAux(c.ReverseComparison())
+ return true
+ }
+ // match: (CRJ {c} x (MOVDconst [y]) yes no)
+ // cond: !is8Bit(y) && is32Bit(y)
+ // result: (BRC {c} (CMPWconst x [int32(y)]) yes no)
+ for b.Controls[1].Op == OpS390XMOVDconst {
+ x := b.Controls[0]
+ v_1 := b.Controls[1]
+ y := auxIntToInt64(v_1.AuxInt)
+ c := auxToS390xCCMask(b.Aux)
+ if !(!is8Bit(y) && is32Bit(y)) {
+ break
+ }
+ v0 := b.NewValue0(x.Pos, OpS390XCMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(y))
+ v0.AddArg(x)
+ b.resetWithControl(BlockS390XBRC, v0)
+ b.Aux = s390xCCMaskToAux(c)
+ return true
+ }
+ // match: (CRJ {c} (MOVDconst [x]) y yes no)
+ // cond: !is8Bit(x) && is32Bit(x)
+ // result: (BRC {c.ReverseComparison()} (CMPWconst y [int32(x)]) yes no)
+ for b.Controls[0].Op == OpS390XMOVDconst {
+ v_0 := b.Controls[0]
+ x := auxIntToInt64(v_0.AuxInt)
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(!is8Bit(x) && is32Bit(x)) {
+ break
+ }
+ v0 := b.NewValue0(v_0.Pos, OpS390XCMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(x))
+ v0.AddArg(y)
+ b.resetWithControl(BlockS390XBRC, v0)
+ b.Aux = s390xCCMaskToAux(c.ReverseComparison())
+ return true
+ }
+ // match: (CRJ {c} x y yes no)
+ // cond: x == y && c&s390x.Equal != 0
+ // result: (First yes no)
+ for {
+ x := b.Controls[0]
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(x == y && c&s390x.Equal != 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (CRJ {c} x y yes no)
+ // cond: x == y && c&s390x.Equal == 0
+ // result: (First no yes)
+ for {
+ x := b.Controls[0]
+ y := b.Controls[1]
+ c := auxToS390xCCMask(b.Aux)
+ if !(x == y && c&s390x.Equal == 0) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ case BlockIf:
+ // match: (If cond yes no)
+ // result: (CLIJ {s390x.LessOrGreater} (MOVBZreg <typ.Bool> cond) [0] yes no)
+ for {
+ cond := b.Controls[0]
+ v0 := b.NewValue0(cond.Pos, OpS390XMOVBZreg, typ.Bool)
+ v0.AddArg(cond)
+ b.resetWithControl(BlockS390XCLIJ, v0)
+ b.AuxInt = uint8ToAuxInt(0)
+ b.Aux = s390xCCMaskToAux(s390x.LessOrGreater)
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteWasm.go b/src/cmd/compile/internal/ssa/rewriteWasm.go
new file mode 100644
index 0000000..c8ecefc
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewriteWasm.go
@@ -0,0 +1,4905 @@
+// Code generated from gen/Wasm.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "math"
+import "cmd/internal/objabi"
+import "cmd/compile/internal/types"
+
+func rewriteValueWasm(v *Value) bool {
+ switch v.Op {
+ case OpAbs:
+ v.Op = OpWasmF64Abs
+ return true
+ case OpAdd16:
+ v.Op = OpWasmI64Add
+ return true
+ case OpAdd32:
+ v.Op = OpWasmI64Add
+ return true
+ case OpAdd32F:
+ v.Op = OpWasmF32Add
+ return true
+ case OpAdd64:
+ v.Op = OpWasmI64Add
+ return true
+ case OpAdd64F:
+ v.Op = OpWasmF64Add
+ return true
+ case OpAdd8:
+ v.Op = OpWasmI64Add
+ return true
+ case OpAddPtr:
+ v.Op = OpWasmI64Add
+ return true
+ case OpAddr:
+ return rewriteValueWasm_OpAddr(v)
+ case OpAnd16:
+ v.Op = OpWasmI64And
+ return true
+ case OpAnd32:
+ v.Op = OpWasmI64And
+ return true
+ case OpAnd64:
+ v.Op = OpWasmI64And
+ return true
+ case OpAnd8:
+ v.Op = OpWasmI64And
+ return true
+ case OpAndB:
+ v.Op = OpWasmI64And
+ return true
+ case OpBitLen64:
+ return rewriteValueWasm_OpBitLen64(v)
+ case OpCeil:
+ v.Op = OpWasmF64Ceil
+ return true
+ case OpClosureCall:
+ v.Op = OpWasmLoweredClosureCall
+ return true
+ case OpCom16:
+ return rewriteValueWasm_OpCom16(v)
+ case OpCom32:
+ return rewriteValueWasm_OpCom32(v)
+ case OpCom64:
+ return rewriteValueWasm_OpCom64(v)
+ case OpCom8:
+ return rewriteValueWasm_OpCom8(v)
+ case OpCondSelect:
+ v.Op = OpWasmSelect
+ return true
+ case OpConst16:
+ return rewriteValueWasm_OpConst16(v)
+ case OpConst32:
+ return rewriteValueWasm_OpConst32(v)
+ case OpConst32F:
+ v.Op = OpWasmF32Const
+ return true
+ case OpConst64:
+ v.Op = OpWasmI64Const
+ return true
+ case OpConst64F:
+ v.Op = OpWasmF64Const
+ return true
+ case OpConst8:
+ return rewriteValueWasm_OpConst8(v)
+ case OpConstBool:
+ return rewriteValueWasm_OpConstBool(v)
+ case OpConstNil:
+ return rewriteValueWasm_OpConstNil(v)
+ case OpConvert:
+ v.Op = OpWasmLoweredConvert
+ return true
+ case OpCopysign:
+ v.Op = OpWasmF64Copysign
+ return true
+ case OpCtz16:
+ return rewriteValueWasm_OpCtz16(v)
+ case OpCtz16NonZero:
+ v.Op = OpWasmI64Ctz
+ return true
+ case OpCtz32:
+ return rewriteValueWasm_OpCtz32(v)
+ case OpCtz32NonZero:
+ v.Op = OpWasmI64Ctz
+ return true
+ case OpCtz64:
+ v.Op = OpWasmI64Ctz
+ return true
+ case OpCtz64NonZero:
+ v.Op = OpWasmI64Ctz
+ return true
+ case OpCtz8:
+ return rewriteValueWasm_OpCtz8(v)
+ case OpCtz8NonZero:
+ v.Op = OpWasmI64Ctz
+ return true
+ case OpCvt32Fto32:
+ v.Op = OpWasmI64TruncSatF32S
+ return true
+ case OpCvt32Fto32U:
+ v.Op = OpWasmI64TruncSatF32U
+ return true
+ case OpCvt32Fto64:
+ v.Op = OpWasmI64TruncSatF32S
+ return true
+ case OpCvt32Fto64F:
+ v.Op = OpWasmF64PromoteF32
+ return true
+ case OpCvt32Fto64U:
+ v.Op = OpWasmI64TruncSatF32U
+ return true
+ case OpCvt32Uto32F:
+ return rewriteValueWasm_OpCvt32Uto32F(v)
+ case OpCvt32Uto64F:
+ return rewriteValueWasm_OpCvt32Uto64F(v)
+ case OpCvt32to32F:
+ return rewriteValueWasm_OpCvt32to32F(v)
+ case OpCvt32to64F:
+ return rewriteValueWasm_OpCvt32to64F(v)
+ case OpCvt64Fto32:
+ v.Op = OpWasmI64TruncSatF64S
+ return true
+ case OpCvt64Fto32F:
+ v.Op = OpWasmF32DemoteF64
+ return true
+ case OpCvt64Fto32U:
+ v.Op = OpWasmI64TruncSatF64U
+ return true
+ case OpCvt64Fto64:
+ v.Op = OpWasmI64TruncSatF64S
+ return true
+ case OpCvt64Fto64U:
+ v.Op = OpWasmI64TruncSatF64U
+ return true
+ case OpCvt64Uto32F:
+ v.Op = OpWasmF32ConvertI64U
+ return true
+ case OpCvt64Uto64F:
+ v.Op = OpWasmF64ConvertI64U
+ return true
+ case OpCvt64to32F:
+ v.Op = OpWasmF32ConvertI64S
+ return true
+ case OpCvt64to64F:
+ v.Op = OpWasmF64ConvertI64S
+ return true
+ case OpCvtBoolToUint8:
+ v.Op = OpCopy
+ return true
+ case OpDiv16:
+ return rewriteValueWasm_OpDiv16(v)
+ case OpDiv16u:
+ return rewriteValueWasm_OpDiv16u(v)
+ case OpDiv32:
+ return rewriteValueWasm_OpDiv32(v)
+ case OpDiv32F:
+ v.Op = OpWasmF32Div
+ return true
+ case OpDiv32u:
+ return rewriteValueWasm_OpDiv32u(v)
+ case OpDiv64:
+ return rewriteValueWasm_OpDiv64(v)
+ case OpDiv64F:
+ v.Op = OpWasmF64Div
+ return true
+ case OpDiv64u:
+ v.Op = OpWasmI64DivU
+ return true
+ case OpDiv8:
+ return rewriteValueWasm_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValueWasm_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValueWasm_OpEq16(v)
+ case OpEq32:
+ return rewriteValueWasm_OpEq32(v)
+ case OpEq32F:
+ v.Op = OpWasmF32Eq
+ return true
+ case OpEq64:
+ v.Op = OpWasmI64Eq
+ return true
+ case OpEq64F:
+ v.Op = OpWasmF64Eq
+ return true
+ case OpEq8:
+ return rewriteValueWasm_OpEq8(v)
+ case OpEqB:
+ v.Op = OpWasmI64Eq
+ return true
+ case OpEqPtr:
+ v.Op = OpWasmI64Eq
+ return true
+ case OpFloor:
+ v.Op = OpWasmF64Floor
+ return true
+ case OpGetCallerPC:
+ v.Op = OpWasmLoweredGetCallerPC
+ return true
+ case OpGetCallerSP:
+ v.Op = OpWasmLoweredGetCallerSP
+ return true
+ case OpGetClosurePtr:
+ v.Op = OpWasmLoweredGetClosurePtr
+ return true
+ case OpInterCall:
+ v.Op = OpWasmLoweredInterCall
+ return true
+ case OpIsInBounds:
+ v.Op = OpWasmI64LtU
+ return true
+ case OpIsNonNil:
+ return rewriteValueWasm_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ v.Op = OpWasmI64LeU
+ return true
+ case OpLeq16:
+ return rewriteValueWasm_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValueWasm_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValueWasm_OpLeq32(v)
+ case OpLeq32F:
+ v.Op = OpWasmF32Le
+ return true
+ case OpLeq32U:
+ return rewriteValueWasm_OpLeq32U(v)
+ case OpLeq64:
+ v.Op = OpWasmI64LeS
+ return true
+ case OpLeq64F:
+ v.Op = OpWasmF64Le
+ return true
+ case OpLeq64U:
+ v.Op = OpWasmI64LeU
+ return true
+ case OpLeq8:
+ return rewriteValueWasm_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValueWasm_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValueWasm_OpLess16(v)
+ case OpLess16U:
+ return rewriteValueWasm_OpLess16U(v)
+ case OpLess32:
+ return rewriteValueWasm_OpLess32(v)
+ case OpLess32F:
+ v.Op = OpWasmF32Lt
+ return true
+ case OpLess32U:
+ return rewriteValueWasm_OpLess32U(v)
+ case OpLess64:
+ v.Op = OpWasmI64LtS
+ return true
+ case OpLess64F:
+ v.Op = OpWasmF64Lt
+ return true
+ case OpLess64U:
+ v.Op = OpWasmI64LtU
+ return true
+ case OpLess8:
+ return rewriteValueWasm_OpLess8(v)
+ case OpLess8U:
+ return rewriteValueWasm_OpLess8U(v)
+ case OpLoad:
+ return rewriteValueWasm_OpLoad(v)
+ case OpLocalAddr:
+ return rewriteValueWasm_OpLocalAddr(v)
+ case OpLsh16x16:
+ return rewriteValueWasm_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValueWasm_OpLsh16x32(v)
+ case OpLsh16x64:
+ v.Op = OpLsh64x64
+ return true
+ case OpLsh16x8:
+ return rewriteValueWasm_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValueWasm_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValueWasm_OpLsh32x32(v)
+ case OpLsh32x64:
+ v.Op = OpLsh64x64
+ return true
+ case OpLsh32x8:
+ return rewriteValueWasm_OpLsh32x8(v)
+ case OpLsh64x16:
+ return rewriteValueWasm_OpLsh64x16(v)
+ case OpLsh64x32:
+ return rewriteValueWasm_OpLsh64x32(v)
+ case OpLsh64x64:
+ return rewriteValueWasm_OpLsh64x64(v)
+ case OpLsh64x8:
+ return rewriteValueWasm_OpLsh64x8(v)
+ case OpLsh8x16:
+ return rewriteValueWasm_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValueWasm_OpLsh8x32(v)
+ case OpLsh8x64:
+ v.Op = OpLsh64x64
+ return true
+ case OpLsh8x8:
+ return rewriteValueWasm_OpLsh8x8(v)
+ case OpMod16:
+ return rewriteValueWasm_OpMod16(v)
+ case OpMod16u:
+ return rewriteValueWasm_OpMod16u(v)
+ case OpMod32:
+ return rewriteValueWasm_OpMod32(v)
+ case OpMod32u:
+ return rewriteValueWasm_OpMod32u(v)
+ case OpMod64:
+ return rewriteValueWasm_OpMod64(v)
+ case OpMod64u:
+ v.Op = OpWasmI64RemU
+ return true
+ case OpMod8:
+ return rewriteValueWasm_OpMod8(v)
+ case OpMod8u:
+ return rewriteValueWasm_OpMod8u(v)
+ case OpMove:
+ return rewriteValueWasm_OpMove(v)
+ case OpMul16:
+ v.Op = OpWasmI64Mul
+ return true
+ case OpMul32:
+ v.Op = OpWasmI64Mul
+ return true
+ case OpMul32F:
+ v.Op = OpWasmF32Mul
+ return true
+ case OpMul64:
+ v.Op = OpWasmI64Mul
+ return true
+ case OpMul64F:
+ v.Op = OpWasmF64Mul
+ return true
+ case OpMul8:
+ v.Op = OpWasmI64Mul
+ return true
+ case OpNeg16:
+ return rewriteValueWasm_OpNeg16(v)
+ case OpNeg32:
+ return rewriteValueWasm_OpNeg32(v)
+ case OpNeg32F:
+ v.Op = OpWasmF32Neg
+ return true
+ case OpNeg64:
+ return rewriteValueWasm_OpNeg64(v)
+ case OpNeg64F:
+ v.Op = OpWasmF64Neg
+ return true
+ case OpNeg8:
+ return rewriteValueWasm_OpNeg8(v)
+ case OpNeq16:
+ return rewriteValueWasm_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValueWasm_OpNeq32(v)
+ case OpNeq32F:
+ v.Op = OpWasmF32Ne
+ return true
+ case OpNeq64:
+ v.Op = OpWasmI64Ne
+ return true
+ case OpNeq64F:
+ v.Op = OpWasmF64Ne
+ return true
+ case OpNeq8:
+ return rewriteValueWasm_OpNeq8(v)
+ case OpNeqB:
+ v.Op = OpWasmI64Ne
+ return true
+ case OpNeqPtr:
+ v.Op = OpWasmI64Ne
+ return true
+ case OpNilCheck:
+ v.Op = OpWasmLoweredNilCheck
+ return true
+ case OpNot:
+ v.Op = OpWasmI64Eqz
+ return true
+ case OpOffPtr:
+ v.Op = OpWasmI64AddConst
+ return true
+ case OpOr16:
+ v.Op = OpWasmI64Or
+ return true
+ case OpOr32:
+ v.Op = OpWasmI64Or
+ return true
+ case OpOr64:
+ v.Op = OpWasmI64Or
+ return true
+ case OpOr8:
+ v.Op = OpWasmI64Or
+ return true
+ case OpOrB:
+ v.Op = OpWasmI64Or
+ return true
+ case OpPopCount16:
+ return rewriteValueWasm_OpPopCount16(v)
+ case OpPopCount32:
+ return rewriteValueWasm_OpPopCount32(v)
+ case OpPopCount64:
+ v.Op = OpWasmI64Popcnt
+ return true
+ case OpPopCount8:
+ return rewriteValueWasm_OpPopCount8(v)
+ case OpRotateLeft16:
+ return rewriteValueWasm_OpRotateLeft16(v)
+ case OpRotateLeft32:
+ v.Op = OpWasmI32Rotl
+ return true
+ case OpRotateLeft64:
+ v.Op = OpWasmI64Rotl
+ return true
+ case OpRotateLeft8:
+ return rewriteValueWasm_OpRotateLeft8(v)
+ case OpRound32F:
+ v.Op = OpCopy
+ return true
+ case OpRound64F:
+ v.Op = OpCopy
+ return true
+ case OpRoundToEven:
+ v.Op = OpWasmF64Nearest
+ return true
+ case OpRsh16Ux16:
+ return rewriteValueWasm_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValueWasm_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValueWasm_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValueWasm_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValueWasm_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValueWasm_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValueWasm_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValueWasm_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValueWasm_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValueWasm_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValueWasm_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValueWasm_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValueWasm_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValueWasm_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValueWasm_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValueWasm_OpRsh32x8(v)
+ case OpRsh64Ux16:
+ return rewriteValueWasm_OpRsh64Ux16(v)
+ case OpRsh64Ux32:
+ return rewriteValueWasm_OpRsh64Ux32(v)
+ case OpRsh64Ux64:
+ return rewriteValueWasm_OpRsh64Ux64(v)
+ case OpRsh64Ux8:
+ return rewriteValueWasm_OpRsh64Ux8(v)
+ case OpRsh64x16:
+ return rewriteValueWasm_OpRsh64x16(v)
+ case OpRsh64x32:
+ return rewriteValueWasm_OpRsh64x32(v)
+ case OpRsh64x64:
+ return rewriteValueWasm_OpRsh64x64(v)
+ case OpRsh64x8:
+ return rewriteValueWasm_OpRsh64x8(v)
+ case OpRsh8Ux16:
+ return rewriteValueWasm_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValueWasm_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValueWasm_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValueWasm_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValueWasm_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValueWasm_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValueWasm_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValueWasm_OpRsh8x8(v)
+ case OpSignExt16to32:
+ return rewriteValueWasm_OpSignExt16to32(v)
+ case OpSignExt16to64:
+ return rewriteValueWasm_OpSignExt16to64(v)
+ case OpSignExt32to64:
+ return rewriteValueWasm_OpSignExt32to64(v)
+ case OpSignExt8to16:
+ return rewriteValueWasm_OpSignExt8to16(v)
+ case OpSignExt8to32:
+ return rewriteValueWasm_OpSignExt8to32(v)
+ case OpSignExt8to64:
+ return rewriteValueWasm_OpSignExt8to64(v)
+ case OpSlicemask:
+ return rewriteValueWasm_OpSlicemask(v)
+ case OpSqrt:
+ v.Op = OpWasmF64Sqrt
+ return true
+ case OpStaticCall:
+ v.Op = OpWasmLoweredStaticCall
+ return true
+ case OpStore:
+ return rewriteValueWasm_OpStore(v)
+ case OpSub16:
+ v.Op = OpWasmI64Sub
+ return true
+ case OpSub32:
+ v.Op = OpWasmI64Sub
+ return true
+ case OpSub32F:
+ v.Op = OpWasmF32Sub
+ return true
+ case OpSub64:
+ v.Op = OpWasmI64Sub
+ return true
+ case OpSub64F:
+ v.Op = OpWasmF64Sub
+ return true
+ case OpSub8:
+ v.Op = OpWasmI64Sub
+ return true
+ case OpSubPtr:
+ v.Op = OpWasmI64Sub
+ return true
+ case OpTrunc:
+ v.Op = OpWasmF64Trunc
+ return true
+ case OpTrunc16to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc32to8:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to16:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to32:
+ v.Op = OpCopy
+ return true
+ case OpTrunc64to8:
+ v.Op = OpCopy
+ return true
+ case OpWB:
+ v.Op = OpWasmLoweredWB
+ return true
+ case OpWasmF64Add:
+ return rewriteValueWasm_OpWasmF64Add(v)
+ case OpWasmF64Mul:
+ return rewriteValueWasm_OpWasmF64Mul(v)
+ case OpWasmI64Add:
+ return rewriteValueWasm_OpWasmI64Add(v)
+ case OpWasmI64AddConst:
+ return rewriteValueWasm_OpWasmI64AddConst(v)
+ case OpWasmI64And:
+ return rewriteValueWasm_OpWasmI64And(v)
+ case OpWasmI64Eq:
+ return rewriteValueWasm_OpWasmI64Eq(v)
+ case OpWasmI64Eqz:
+ return rewriteValueWasm_OpWasmI64Eqz(v)
+ case OpWasmI64LeU:
+ return rewriteValueWasm_OpWasmI64LeU(v)
+ case OpWasmI64Load:
+ return rewriteValueWasm_OpWasmI64Load(v)
+ case OpWasmI64Load16S:
+ return rewriteValueWasm_OpWasmI64Load16S(v)
+ case OpWasmI64Load16U:
+ return rewriteValueWasm_OpWasmI64Load16U(v)
+ case OpWasmI64Load32S:
+ return rewriteValueWasm_OpWasmI64Load32S(v)
+ case OpWasmI64Load32U:
+ return rewriteValueWasm_OpWasmI64Load32U(v)
+ case OpWasmI64Load8S:
+ return rewriteValueWasm_OpWasmI64Load8S(v)
+ case OpWasmI64Load8U:
+ return rewriteValueWasm_OpWasmI64Load8U(v)
+ case OpWasmI64LtU:
+ return rewriteValueWasm_OpWasmI64LtU(v)
+ case OpWasmI64Mul:
+ return rewriteValueWasm_OpWasmI64Mul(v)
+ case OpWasmI64Ne:
+ return rewriteValueWasm_OpWasmI64Ne(v)
+ case OpWasmI64Or:
+ return rewriteValueWasm_OpWasmI64Or(v)
+ case OpWasmI64Shl:
+ return rewriteValueWasm_OpWasmI64Shl(v)
+ case OpWasmI64ShrS:
+ return rewriteValueWasm_OpWasmI64ShrS(v)
+ case OpWasmI64ShrU:
+ return rewriteValueWasm_OpWasmI64ShrU(v)
+ case OpWasmI64Store:
+ return rewriteValueWasm_OpWasmI64Store(v)
+ case OpWasmI64Store16:
+ return rewriteValueWasm_OpWasmI64Store16(v)
+ case OpWasmI64Store32:
+ return rewriteValueWasm_OpWasmI64Store32(v)
+ case OpWasmI64Store8:
+ return rewriteValueWasm_OpWasmI64Store8(v)
+ case OpWasmI64Xor:
+ return rewriteValueWasm_OpWasmI64Xor(v)
+ case OpXor16:
+ v.Op = OpWasmI64Xor
+ return true
+ case OpXor32:
+ v.Op = OpWasmI64Xor
+ return true
+ case OpXor64:
+ v.Op = OpWasmI64Xor
+ return true
+ case OpXor8:
+ v.Op = OpWasmI64Xor
+ return true
+ case OpZero:
+ return rewriteValueWasm_OpZero(v)
+ case OpZeroExt16to32:
+ return rewriteValueWasm_OpZeroExt16to32(v)
+ case OpZeroExt16to64:
+ return rewriteValueWasm_OpZeroExt16to64(v)
+ case OpZeroExt32to64:
+ return rewriteValueWasm_OpZeroExt32to64(v)
+ case OpZeroExt8to16:
+ return rewriteValueWasm_OpZeroExt8to16(v)
+ case OpZeroExt8to32:
+ return rewriteValueWasm_OpZeroExt8to32(v)
+ case OpZeroExt8to64:
+ return rewriteValueWasm_OpZeroExt8to64(v)
+ }
+ return false
+}
+func rewriteValueWasm_OpAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Addr {sym} base)
+ // result: (LoweredAddr {sym} [0] base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpWasmLoweredAddr)
+ v.AuxInt = int32ToAuxInt(0)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueWasm_OpBitLen64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen64 x)
+ // result: (I64Sub (I64Const [64]) (I64Clz x))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Sub)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Clz, typ.Int64)
+ v1.AddArg(x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpCom16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Com16 x)
+ // result: (I64Xor x (I64Const [-1]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Xor)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(-1)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpCom32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Com32 x)
+ // result: (I64Xor x (I64Const [-1]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Xor)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(-1)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpCom64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Com64 x)
+ // result: (I64Xor x (I64Const [-1]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Xor)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(-1)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpCom8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Com8 x)
+ // result: (I64Xor x (I64Const [-1]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Xor)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(-1)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpConst16(v *Value) bool {
+ // match: (Const16 [c])
+ // result: (I64Const [int64(c)])
+ for {
+ c := auxIntToInt16(v.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+}
+func rewriteValueWasm_OpConst32(v *Value) bool {
+ // match: (Const32 [c])
+ // result: (I64Const [int64(c)])
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+}
+func rewriteValueWasm_OpConst8(v *Value) bool {
+ // match: (Const8 [c])
+ // result: (I64Const [int64(c)])
+ for {
+ c := auxIntToInt8(v.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+}
+func rewriteValueWasm_OpConstBool(v *Value) bool {
+ // match: (ConstBool [c])
+ // result: (I64Const [b2i(c)])
+ for {
+ c := auxIntToBool(v.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(b2i(c))
+ return true
+ }
+}
+func rewriteValueWasm_OpConstNil(v *Value) bool {
+ // match: (ConstNil)
+ // result: (I64Const [0])
+ for {
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+}
+func rewriteValueWasm_OpCtz16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz16 x)
+ // result: (I64Ctz (I64Or x (I64Const [0x10000])))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Ctz)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Or, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(0x10000)
+ v0.AddArg2(x, v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpCtz32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz32 x)
+ // result: (I64Ctz (I64Or x (I64Const [0x100000000])))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Ctz)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Or, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(0x100000000)
+ v0.AddArg2(x, v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpCtz8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz8 x)
+ // result: (I64Ctz (I64Or x (I64Const [0x100])))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Ctz)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Or, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(0x100)
+ v0.AddArg2(x, v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpCvt32Uto32F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt32Uto32F x)
+ // result: (F32ConvertI64U (ZeroExt32to64 x))
+ for {
+ x := v_0
+ v.reset(OpWasmF32ConvertI64U)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpCvt32Uto64F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt32Uto64F x)
+ // result: (F64ConvertI64U (ZeroExt32to64 x))
+ for {
+ x := v_0
+ v.reset(OpWasmF64ConvertI64U)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpCvt32to32F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt32to32F x)
+ // result: (F32ConvertI64S (SignExt32to64 x))
+ for {
+ x := v_0
+ v.reset(OpWasmF32ConvertI64S)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpCvt32to64F(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Cvt32to64F x)
+ // result: (F64ConvertI64S (SignExt32to64 x))
+ for {
+ x := v_0
+ v.reset(OpWasmF64ConvertI64S)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpDiv16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16 [false] x y)
+ // result: (I64DivS (SignExt16to64 x) (SignExt16to64 y))
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64DivS)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpDiv16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16u x y)
+ // result: (I64DivU (ZeroExt16to64 x) (ZeroExt16to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64DivU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpDiv32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32 [false] x y)
+ // result: (I64DivS (SignExt32to64 x) (SignExt32to64 y))
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64DivS)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpDiv32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div32u x y)
+ // result: (I64DivU (ZeroExt32to64 x) (ZeroExt32to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64DivU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpDiv64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Div64 [false] x y)
+ // result: (I64DivS x y)
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64DivS)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 x y)
+ // result: (I64DivS (SignExt8to64 x) (SignExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64DivS)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u x y)
+ // result: (I64DivU (ZeroExt8to64 x) (ZeroExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64DivU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq16 x y)
+ // result: (I64Eq (ZeroExt16to64 x) (ZeroExt16to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64Eq)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq32 x y)
+ // result: (I64Eq (ZeroExt32to64 x) (ZeroExt32to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64Eq)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq8 x y)
+ // result: (I64Eq (ZeroExt8to64 x) (ZeroExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64Eq)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (IsNonNil p)
+ // result: (I64Eqz (I64Eqz p))
+ for {
+ p := v_0
+ v.reset(OpWasmI64Eqz)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Eqz, typ.Bool)
+ v0.AddArg(p)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16 x y)
+ // result: (I64LeS (SignExt16to64 x) (SignExt16to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LeS)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq16U x y)
+ // result: (I64LeU (ZeroExt16to64 x) (ZeroExt16to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LeU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32 x y)
+ // result: (I64LeS (SignExt32to64 x) (SignExt32to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LeS)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq32U x y)
+ // result: (I64LeU (ZeroExt32to64 x) (ZeroExt32to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LeU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8 x y)
+ // result: (I64LeS (SignExt8to64 x) (SignExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LeS)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq8U x y)
+ // result: (I64LeU (ZeroExt8to64 x) (ZeroExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LeU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16 x y)
+ // result: (I64LtS (SignExt16to64 x) (SignExt16to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LtS)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less16U x y)
+ // result: (I64LtU (ZeroExt16to64 x) (ZeroExt16to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LtU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less32 x y)
+ // result: (I64LtS (SignExt32to64 x) (SignExt32to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LtS)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less32U x y)
+ // result: (I64LtU (ZeroExt32to64 x) (ZeroExt32to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LtU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8 x y)
+ // result: (I64LtS (SignExt8to64 x) (SignExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LtS)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less8U x y)
+ // result: (I64LtU (ZeroExt8to64 x) (ZeroExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64LtU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Load <t> ptr mem)
+ // cond: is32BitFloat(t)
+ // result: (F32Load ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(OpWasmF32Load)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitFloat(t)
+ // result: (F64Load ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(OpWasmF64Load)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.Size() == 8
+ // result: (I64Load ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.Size() == 8) {
+ break
+ }
+ v.reset(OpWasmI64Load)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.Size() == 4 && !t.IsSigned()
+ // result: (I64Load32U ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.Size() == 4 && !t.IsSigned()) {
+ break
+ }
+ v.reset(OpWasmI64Load32U)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.Size() == 4 && t.IsSigned()
+ // result: (I64Load32S ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.Size() == 4 && t.IsSigned()) {
+ break
+ }
+ v.reset(OpWasmI64Load32S)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.Size() == 2 && !t.IsSigned()
+ // result: (I64Load16U ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.Size() == 2 && !t.IsSigned()) {
+ break
+ }
+ v.reset(OpWasmI64Load16U)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.Size() == 2 && t.IsSigned()
+ // result: (I64Load16S ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.Size() == 2 && t.IsSigned()) {
+ break
+ }
+ v.reset(OpWasmI64Load16S)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.Size() == 1 && !t.IsSigned()
+ // result: (I64Load8U ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.Size() == 1 && !t.IsSigned()) {
+ break
+ }
+ v.reset(OpWasmI64Load8U)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.Size() == 1 && t.IsSigned()
+ // result: (I64Load8S ptr mem)
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.Size() == 1 && t.IsSigned()) {
+ break
+ }
+ v.reset(OpWasmI64Load8S)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpLocalAddr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (LocalAddr {sym} base _)
+ // result: (LoweredAddr {sym} base)
+ for {
+ sym := auxToSym(v.Aux)
+ base := v_0
+ v.reset(OpWasmLoweredAddr)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x16 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x32 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x8 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x16 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x32 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x8 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x16 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x32 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (I64Shl x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpWasmI64Shl)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Lsh64x64 x (I64Const [c]))
+ // cond: uint64(c) < 64
+ // result: (I64Shl x (I64Const [c]))
+ for {
+ x := v_0
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 64) {
+ break
+ }
+ v.reset(OpWasmI64Shl)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh64x64 x (I64Const [c]))
+ // cond: uint64(c) >= 64
+ // result: (I64Const [0])
+ for {
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh64x64 x y)
+ // result: (Select (I64Shl x y) (I64Const [0]) (I64LtU y (I64Const [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmSelect)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpWasmI64LtU, typ.Bool)
+ v3 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(y, v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x8 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x16 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x32 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x8 [c] x y)
+ // result: (Lsh64x64 [c] x (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpMod16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16 [false] x y)
+ // result: (I64RemS (SignExt16to64 x) (SignExt16to64 y))
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64RemS)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpMod16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod16u x y)
+ // result: (I64RemU (ZeroExt16to64 x) (ZeroExt16to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64RemU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpMod32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32 [false] x y)
+ // result: (I64RemS (SignExt32to64 x) (SignExt32to64 y))
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64RemS)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpMod32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod32u x y)
+ // result: (I64RemU (ZeroExt32to64 x) (ZeroExt32to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64RemU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpMod64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Mod64 [false] x y)
+ // result: (I64RemS x y)
+ for {
+ if auxIntToBool(v.AuxInt) != false {
+ break
+ }
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64RemS)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8 x y)
+ // result: (I64RemS (SignExt8to64 x) (SignExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64RemS)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mod8u x y)
+ // result: (I64RemU (ZeroExt8to64 x) (ZeroExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64RemU)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Move [0] _ _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Move [1] dst src mem)
+ // result: (I64Store8 dst (I64Load8U src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpWasmI64Store8)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Load8U, typ.UInt8)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [2] dst src mem)
+ // result: (I64Store16 dst (I64Load16U src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpWasmI64Store16)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Load16U, typ.UInt16)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [4] dst src mem)
+ // result: (I64Store32 dst (I64Load32U src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpWasmI64Store32)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Load32U, typ.UInt32)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [8] dst src mem)
+ // result: (I64Store dst (I64Load src mem) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpWasmI64Store)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Load, typ.UInt64)
+ v0.AddArg2(src, mem)
+ v.AddArg3(dst, v0, mem)
+ return true
+ }
+ // match: (Move [16] dst src mem)
+ // result: (I64Store [8] dst (I64Load [8] src mem) (I64Store dst (I64Load src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpWasmI64Store)
+ v.AuxInt = int64ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Load, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Load, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [3] dst src mem)
+ // result: (I64Store8 [2] dst (I64Load8U [2] src mem) (I64Store16 dst (I64Load16U src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpWasmI64Store8)
+ v.AuxInt = int64ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Load8U, typ.UInt8)
+ v0.AuxInt = int64ToAuxInt(2)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store16, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Load16U, typ.UInt16)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [5] dst src mem)
+ // result: (I64Store8 [4] dst (I64Load8U [4] src mem) (I64Store32 dst (I64Load32U src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpWasmI64Store8)
+ v.AuxInt = int64ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Load8U, typ.UInt8)
+ v0.AuxInt = int64ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store32, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Load32U, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [6] dst src mem)
+ // result: (I64Store16 [4] dst (I64Load16U [4] src mem) (I64Store32 dst (I64Load32U src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpWasmI64Store16)
+ v.AuxInt = int64ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Load16U, typ.UInt16)
+ v0.AuxInt = int64ToAuxInt(4)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store32, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Load32U, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [7] dst src mem)
+ // result: (I64Store32 [3] dst (I64Load32U [3] src mem) (I64Store32 dst (I64Load32U src mem) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ dst := v_0
+ src := v_1
+ mem := v_2
+ v.reset(OpWasmI64Store32)
+ v.AuxInt = int64ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Load32U, typ.UInt32)
+ v0.AuxInt = int64ToAuxInt(3)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store32, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Load32U, typ.UInt32)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 8 && s < 16
+ // result: (I64Store [s-8] dst (I64Load [s-8] src mem) (I64Store dst (I64Load src mem) mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 8 && s < 16) {
+ break
+ }
+ v.reset(OpWasmI64Store)
+ v.AuxInt = int64ToAuxInt(s - 8)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Load, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(s - 8)
+ v0.AddArg2(src, mem)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Load, typ.UInt64)
+ v2.AddArg2(src, mem)
+ v1.AddArg3(dst, v2, mem)
+ v.AddArg3(dst, v0, v1)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 16 && s%16 != 0 && s%16 <= 8
+ // result: (Move [s-s%16] (OffPtr <dst.Type> dst [s%16]) (OffPtr <src.Type> src [s%16]) (I64Store dst (I64Load src mem) mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 16 && s%16 != 0 && s%16 <= 8) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(s - s%16)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
+ v0.AuxInt = int64ToAuxInt(s % 16)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
+ v1.AuxInt = int64ToAuxInt(s % 16)
+ v1.AddArg(src)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v3 := b.NewValue0(v.Pos, OpWasmI64Load, typ.UInt64)
+ v3.AddArg2(src, mem)
+ v2.AddArg3(dst, v3, mem)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s > 16 && s%16 != 0 && s%16 > 8
+ // result: (Move [s-s%16] (OffPtr <dst.Type> dst [s%16]) (OffPtr <src.Type> src [s%16]) (I64Store [8] dst (I64Load [8] src mem) (I64Store dst (I64Load src mem) mem)))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s > 16 && s%16 != 0 && s%16 > 8) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(s - s%16)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
+ v0.AuxInt = int64ToAuxInt(s % 16)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
+ v1.AuxInt = int64ToAuxInt(s % 16)
+ v1.AddArg(src)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v2.AuxInt = int64ToAuxInt(8)
+ v3 := b.NewValue0(v.Pos, OpWasmI64Load, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(8)
+ v3.AddArg2(src, mem)
+ v4 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v5 := b.NewValue0(v.Pos, OpWasmI64Load, typ.UInt64)
+ v5.AddArg2(src, mem)
+ v4.AddArg3(dst, v5, mem)
+ v2.AddArg3(dst, v3, v4)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Move [s] dst src mem)
+ // cond: s%8 == 0 && logLargeCopy(v, s)
+ // result: (LoweredMove [s/8] dst src mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(s%8 == 0 && logLargeCopy(v, s)) {
+ break
+ }
+ v.reset(OpWasmLoweredMove)
+ v.AuxInt = int64ToAuxInt(s / 8)
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpNeg16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neg16 x)
+ // result: (I64Sub (I64Const [0]) x)
+ for {
+ x := v_0
+ v.reset(OpWasmI64Sub)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueWasm_OpNeg32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neg32 x)
+ // result: (I64Sub (I64Const [0]) x)
+ for {
+ x := v_0
+ v.reset(OpWasmI64Sub)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueWasm_OpNeg64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neg64 x)
+ // result: (I64Sub (I64Const [0]) x)
+ for {
+ x := v_0
+ v.reset(OpWasmI64Sub)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueWasm_OpNeg8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neg8 x)
+ // result: (I64Sub (I64Const [0]) x)
+ for {
+ x := v_0
+ v.reset(OpWasmI64Sub)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValueWasm_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq16 x y)
+ // result: (I64Ne (ZeroExt16to64 x) (ZeroExt16to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64Ne)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq32 x y)
+ // result: (I64Ne (ZeroExt32to64 x) (ZeroExt32to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64Ne)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq8 x y)
+ // result: (I64Ne (ZeroExt8to64 x) (ZeroExt8to64 y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64Ne)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpPopCount16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount16 x)
+ // result: (I64Popcnt (ZeroExt16to64 x))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Popcnt)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpPopCount32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount32 x)
+ // result: (I64Popcnt (ZeroExt32to64 x))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Popcnt)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpPopCount8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (PopCount8 x)
+ // result: (I64Popcnt (ZeroExt8to64 x))
+ for {
+ x := v_0
+ v.reset(OpWasmI64Popcnt)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpRotateLeft16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft16 <t> x (I64Const [c]))
+ // result: (Or16 (Lsh16x64 <t> x (I64Const [c&15])) (Rsh16Ux64 <t> x (I64Const [-c&15])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpLsh16x64, t)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(c & 15)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh16Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(-c & 15)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpRotateLeft8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (RotateLeft8 <t> x (I64Const [c]))
+ // result: (Or8 (Lsh8x64 <t> x (I64Const [c&7])) (Rsh8Ux64 <t> x (I64Const [-c&7])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpLsh8x64, t)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(c & 7)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpRsh8Ux64, t)
+ v3 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(-c & 7)
+ v2.AddArg2(x, v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux16 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt16to64 x) (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux32 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt16to64 x) (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux64 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt16to64 x) y)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux8 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt16to64 x) (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x16 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt16to64 x) (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x32 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt16to64 x) (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x64 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt16to64 x) y)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x8 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt16to64 x) (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux16 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt32to64 x) (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux32 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt32to64 x) (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux64 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt32to64 x) y)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux8 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt32to64 x) (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x16 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt32to64 x) (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x32 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt32to64 x) (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x64 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt32to64 x) y)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x8 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt32to64 x) (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh64Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux16 [c] x y)
+ // result: (Rsh64Ux64 [c] x (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh64Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux32 [c] x y)
+ // result: (Rsh64Ux64 [c] x (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh64Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (I64ShrU x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpWasmI64ShrU)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64Ux64 x (I64Const [c]))
+ // cond: uint64(c) < 64
+ // result: (I64ShrU x (I64Const [c]))
+ for {
+ x := v_0
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 64) {
+ break
+ }
+ v.reset(OpWasmI64ShrU)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux64 x (I64Const [c]))
+ // cond: uint64(c) >= 64
+ // result: (I64Const [0])
+ for {
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh64Ux64 x y)
+ // result: (Select (I64ShrU x y) (I64Const [0]) (I64LtU y (I64Const [64])))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmSelect)
+ v0 := b.NewValue0(v.Pos, OpWasmI64ShrU, typ.Int64)
+ v0.AddArg2(x, y)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v2 := b.NewValue0(v.Pos, OpWasmI64LtU, typ.Bool)
+ v3 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(y, v3)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh64Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux8 [c] x y)
+ // result: (Rsh64Ux64 [c] x (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x16 [c] x y)
+ // result: (Rsh64x64 [c] x (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x32 [c] x y)
+ // result: (Rsh64x64 [c] x (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (I64ShrS x y)
+ for {
+ x := v_0
+ y := v_1
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpWasmI64ShrS)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Rsh64x64 x (I64Const [c]))
+ // cond: uint64(c) < 64
+ // result: (I64ShrS x (I64Const [c]))
+ for {
+ x := v_0
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) < 64) {
+ break
+ }
+ v.reset(OpWasmI64ShrS)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(c)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x64 x (I64Const [c]))
+ // cond: uint64(c) >= 64
+ // result: (I64ShrS x (I64Const [63]))
+ for {
+ x := v_0
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpWasmI64ShrS)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(63)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x64 x y)
+ // result: (I64ShrS x (Select <typ.Int64> y (I64Const [63]) (I64LtU y (I64Const [64]))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpWasmI64ShrS)
+ v0 := b.NewValue0(v.Pos, OpWasmSelect, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(63)
+ v2 := b.NewValue0(v.Pos, OpWasmI64LtU, typ.Bool)
+ v3 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v3.AuxInt = int64ToAuxInt(64)
+ v2.AddArg2(y, v3)
+ v0.AddArg3(y, v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x8 [c] x y)
+ // result: (Rsh64x64 [c] x (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux16 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt8to64 x) (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux32 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt8to64 x) (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux64 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt8to64 x) y)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux8 [c] x y)
+ // result: (Rsh64Ux64 [c] (ZeroExt8to64 x) (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x16 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt8to64 x) (ZeroExt16to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x32 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt8to64 x) (ZeroExt32to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x64 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt8to64 x) y)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg2(v0, y)
+ return true
+ }
+}
+func rewriteValueWasm_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x8 [c] x y)
+ // result: (Rsh64x64 [c] (SignExt8to64 x) (ZeroExt8to64 y))
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x64)
+ v.AuxInt = boolToAuxInt(c)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpSignExt16to32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SignExt16to32 x:(I64Load16S _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load16S {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SignExt16to32 x)
+ // cond: objabi.GOWASM.SignExt
+ // result: (I64Extend16S x)
+ for {
+ x := v_0
+ if !(objabi.GOWASM.SignExt) {
+ break
+ }
+ v.reset(OpWasmI64Extend16S)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SignExt16to32 x)
+ // result: (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64ShrS)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(48)
+ v0.AddArg2(x, v1)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpSignExt16to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SignExt16to64 x:(I64Load16S _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load16S {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SignExt16to64 x)
+ // cond: objabi.GOWASM.SignExt
+ // result: (I64Extend16S x)
+ for {
+ x := v_0
+ if !(objabi.GOWASM.SignExt) {
+ break
+ }
+ v.reset(OpWasmI64Extend16S)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SignExt16to64 x)
+ // result: (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64ShrS)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(48)
+ v0.AddArg2(x, v1)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpSignExt32to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SignExt32to64 x:(I64Load32S _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load32S {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SignExt32to64 x)
+ // cond: objabi.GOWASM.SignExt
+ // result: (I64Extend32S x)
+ for {
+ x := v_0
+ if !(objabi.GOWASM.SignExt) {
+ break
+ }
+ v.reset(OpWasmI64Extend32S)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SignExt32to64 x)
+ // result: (I64ShrS (I64Shl x (I64Const [32])) (I64Const [32]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64ShrS)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(32)
+ v0.AddArg2(x, v1)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpSignExt8to16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SignExt8to16 x:(I64Load8S _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load8S {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SignExt8to16 x)
+ // cond: objabi.GOWASM.SignExt
+ // result: (I64Extend8S x)
+ for {
+ x := v_0
+ if !(objabi.GOWASM.SignExt) {
+ break
+ }
+ v.reset(OpWasmI64Extend8S)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SignExt8to16 x)
+ // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64ShrS)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(56)
+ v0.AddArg2(x, v1)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpSignExt8to32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SignExt8to32 x:(I64Load8S _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load8S {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SignExt8to32 x)
+ // cond: objabi.GOWASM.SignExt
+ // result: (I64Extend8S x)
+ for {
+ x := v_0
+ if !(objabi.GOWASM.SignExt) {
+ break
+ }
+ v.reset(OpWasmI64Extend8S)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SignExt8to32 x)
+ // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64ShrS)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(56)
+ v0.AddArg2(x, v1)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpSignExt8to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SignExt8to64 x:(I64Load8S _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load8S {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (SignExt8to64 x)
+ // cond: objabi.GOWASM.SignExt
+ // result: (I64Extend8S x)
+ for {
+ x := v_0
+ if !(objabi.GOWASM.SignExt) {
+ break
+ }
+ v.reset(OpWasmI64Extend8S)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SignExt8to64 x)
+ // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64ShrS)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(56)
+ v0.AddArg2(x, v1)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValueWasm_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Slicemask x)
+ // result: (I64ShrS (I64Sub (I64Const [0]) x) (I64Const [63]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64ShrS)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Sub, typ.Int64)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v1.AuxInt = int64ToAuxInt(0)
+ v0.AddArg2(v1, x)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(63)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValueWasm_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Store {t} ptr val mem)
+ // cond: is64BitFloat(t)
+ // result: (F64Store ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(is64BitFloat(t)) {
+ break
+ }
+ v.reset(OpWasmF64Store)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: is32BitFloat(t)
+ // result: (F32Store ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(is32BitFloat(t)) {
+ break
+ }
+ v.reset(OpWasmF32Store)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 8
+ // result: (I64Store ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 8) {
+ break
+ }
+ v.reset(OpWasmI64Store)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 4
+ // result: (I64Store32 ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 4) {
+ break
+ }
+ v.reset(OpWasmI64Store32)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 2
+ // result: (I64Store16 ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 2) {
+ break
+ }
+ v.reset(OpWasmI64Store16)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ // match: (Store {t} ptr val mem)
+ // cond: t.Size() == 1
+ // result: (I64Store8 ptr val mem)
+ for {
+ t := auxToType(v.Aux)
+ ptr := v_0
+ val := v_1
+ mem := v_2
+ if !(t.Size() == 1) {
+ break
+ }
+ v.reset(OpWasmI64Store8)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmF64Add(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (F64Add (F64Const [x]) (F64Const [y]))
+ // result: (F64Const [x + y])
+ for {
+ if v_0.Op != OpWasmF64Const {
+ break
+ }
+ x := auxIntToFloat64(v_0.AuxInt)
+ if v_1.Op != OpWasmF64Const {
+ break
+ }
+ y := auxIntToFloat64(v_1.AuxInt)
+ v.reset(OpWasmF64Const)
+ v.AuxInt = float64ToAuxInt(x + y)
+ return true
+ }
+ // match: (F64Add (F64Const [x]) y)
+ // cond: y.Op != OpWasmF64Const
+ // result: (F64Add y (F64Const [x]))
+ for {
+ if v_0.Op != OpWasmF64Const {
+ break
+ }
+ x := auxIntToFloat64(v_0.AuxInt)
+ y := v_1
+ if !(y.Op != OpWasmF64Const) {
+ break
+ }
+ v.reset(OpWasmF64Add)
+ v0 := b.NewValue0(v.Pos, OpWasmF64Const, typ.Float64)
+ v0.AuxInt = float64ToAuxInt(x)
+ v.AddArg2(y, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmF64Mul(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (F64Mul (F64Const [x]) (F64Const [y]))
+ // cond: !math.IsNaN(x * y)
+ // result: (F64Const [x * y])
+ for {
+ if v_0.Op != OpWasmF64Const {
+ break
+ }
+ x := auxIntToFloat64(v_0.AuxInt)
+ if v_1.Op != OpWasmF64Const {
+ break
+ }
+ y := auxIntToFloat64(v_1.AuxInt)
+ if !(!math.IsNaN(x * y)) {
+ break
+ }
+ v.reset(OpWasmF64Const)
+ v.AuxInt = float64ToAuxInt(x * y)
+ return true
+ }
+ // match: (F64Mul (F64Const [x]) y)
+ // cond: y.Op != OpWasmF64Const
+ // result: (F64Mul y (F64Const [x]))
+ for {
+ if v_0.Op != OpWasmF64Const {
+ break
+ }
+ x := auxIntToFloat64(v_0.AuxInt)
+ y := v_1
+ if !(y.Op != OpWasmF64Const) {
+ break
+ }
+ v.reset(OpWasmF64Mul)
+ v0 := b.NewValue0(v.Pos, OpWasmF64Const, typ.Float64)
+ v0.AuxInt = float64ToAuxInt(x)
+ v.AddArg2(y, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Add(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (I64Add (I64Const [x]) (I64Const [y]))
+ // result: (I64Const [x + y])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(x + y)
+ return true
+ }
+ // match: (I64Add (I64Const [x]) y)
+ // cond: y.Op != OpWasmI64Const
+ // result: (I64Add y (I64Const [x]))
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(y.Op != OpWasmI64Const) {
+ break
+ }
+ v.reset(OpWasmI64Add)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(x)
+ v.AddArg2(y, v0)
+ return true
+ }
+ // match: (I64Add x (I64Const [y]))
+ // result: (I64AddConst [y] x)
+ for {
+ x := v_0
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpWasmI64AddConst)
+ v.AuxInt = int64ToAuxInt(y)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64AddConst(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (I64AddConst [0] x)
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ x := v_0
+ v.copyOf(x)
+ return true
+ }
+ // match: (I64AddConst [off] (LoweredAddr {sym} [off2] base))
+ // cond: isU32Bit(off+int64(off2))
+ // result: (LoweredAddr {sym} [int32(off)+off2] base)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmLoweredAddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ base := v_0.Args[0]
+ if !(isU32Bit(off + int64(off2))) {
+ break
+ }
+ v.reset(OpWasmLoweredAddr)
+ v.AuxInt = int32ToAuxInt(int32(off) + off2)
+ v.Aux = symToAux(sym)
+ v.AddArg(base)
+ return true
+ }
+ // match: (I64AddConst [off] x:(SP))
+ // cond: isU32Bit(off)
+ // result: (LoweredAddr [int32(off)] x)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if x.Op != OpSP || !(isU32Bit(off)) {
+ break
+ }
+ v.reset(OpWasmLoweredAddr)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64And(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (I64And (I64Const [x]) (I64Const [y]))
+ // result: (I64Const [x & y])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(x & y)
+ return true
+ }
+ // match: (I64And (I64Const [x]) y)
+ // cond: y.Op != OpWasmI64Const
+ // result: (I64And y (I64Const [x]))
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(y.Op != OpWasmI64Const) {
+ break
+ }
+ v.reset(OpWasmI64And)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(x)
+ v.AddArg2(y, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Eq(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (I64Eq (I64Const [x]) (I64Const [y]))
+ // cond: x == y
+ // result: (I64Const [1])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ if !(x == y) {
+ break
+ }
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (I64Eq (I64Const [x]) (I64Const [y]))
+ // cond: x != y
+ // result: (I64Const [0])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ if !(x != y) {
+ break
+ }
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (I64Eq (I64Const [x]) y)
+ // cond: y.Op != OpWasmI64Const
+ // result: (I64Eq y (I64Const [x]))
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(y.Op != OpWasmI64Const) {
+ break
+ }
+ v.reset(OpWasmI64Eq)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(x)
+ v.AddArg2(y, v0)
+ return true
+ }
+ // match: (I64Eq x (I64Const [0]))
+ // result: (I64Eqz x)
+ for {
+ x := v_0
+ if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpWasmI64Eqz)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Eqz(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (I64Eqz (I64Eqz (I64Eqz x)))
+ // result: (I64Eqz x)
+ for {
+ if v_0.Op != OpWasmI64Eqz {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpWasmI64Eqz {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpWasmI64Eqz)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64LeU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (I64LeU x (I64Const [0]))
+ // result: (I64Eqz x)
+ for {
+ x := v_0
+ if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpWasmI64Eqz)
+ v.AddArg(x)
+ return true
+ }
+ // match: (I64LeU (I64Const [1]) x)
+ // result: (I64Eqz (I64Eqz x))
+ for {
+ if v_0.Op != OpWasmI64Const || auxIntToInt64(v_0.AuxInt) != 1 {
+ break
+ }
+ x := v_1
+ v.reset(OpWasmI64Eqz)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Eqz, typ.Bool)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Load(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (I64Load [off] (I64AddConst [off2] ptr) mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Load [off+off2] ptr mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Load)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (I64Load [off] (LoweredAddr {sym} [off2] (SB)) _)
+ // cond: symIsRO(sym) && isU32Bit(off+int64(off2))
+ // result: (I64Const [int64(read64(sym, off+int64(off2), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmLoweredAddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSB || !(symIsRO(sym) && isU32Bit(off+int64(off2))) {
+ break
+ }
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(int64(read64(sym, off+int64(off2), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Load16S(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64Load16S [off] (I64AddConst [off2] ptr) mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Load16S [off+off2] ptr mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Load16S)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Load16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (I64Load16U [off] (I64AddConst [off2] ptr) mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Load16U [off+off2] ptr mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Load16U)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (I64Load16U [off] (LoweredAddr {sym} [off2] (SB)) _)
+ // cond: symIsRO(sym) && isU32Bit(off+int64(off2))
+ // result: (I64Const [int64(read16(sym, off+int64(off2), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmLoweredAddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSB || !(symIsRO(sym) && isU32Bit(off+int64(off2))) {
+ break
+ }
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(int64(read16(sym, off+int64(off2), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Load32S(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64Load32S [off] (I64AddConst [off2] ptr) mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Load32S [off+off2] ptr mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Load32S)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Load32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (I64Load32U [off] (I64AddConst [off2] ptr) mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Load32U [off+off2] ptr mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Load32U)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (I64Load32U [off] (LoweredAddr {sym} [off2] (SB)) _)
+ // cond: symIsRO(sym) && isU32Bit(off+int64(off2))
+ // result: (I64Const [int64(read32(sym, off+int64(off2), config.ctxt.Arch.ByteOrder))])
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmLoweredAddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSB || !(symIsRO(sym) && isU32Bit(off+int64(off2))) {
+ break
+ }
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(int64(read32(sym, off+int64(off2), config.ctxt.Arch.ByteOrder)))
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Load8S(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64Load8S [off] (I64AddConst [off2] ptr) mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Load8S [off+off2] ptr mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Load8S)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Load8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64Load8U [off] (I64AddConst [off2] ptr) mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Load8U [off+off2] ptr mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ mem := v_1
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Load8U)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg2(ptr, mem)
+ return true
+ }
+ // match: (I64Load8U [off] (LoweredAddr {sym} [off2] (SB)) _)
+ // cond: symIsRO(sym) && isU32Bit(off+int64(off2))
+ // result: (I64Const [int64(read8(sym, off+int64(off2)))])
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmLoweredAddr {
+ break
+ }
+ off2 := auxIntToInt32(v_0.AuxInt)
+ sym := auxToSym(v_0.Aux)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSB || !(symIsRO(sym) && isU32Bit(off+int64(off2))) {
+ break
+ }
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(int64(read8(sym, off+int64(off2))))
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64LtU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (I64LtU (I64Const [0]) x)
+ // result: (I64Eqz (I64Eqz x))
+ for {
+ if v_0.Op != OpWasmI64Const || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_1
+ v.reset(OpWasmI64Eqz)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Eqz, typ.Bool)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (I64LtU x (I64Const [1]))
+ // result: (I64Eqz x)
+ for {
+ x := v_0
+ if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 1 {
+ break
+ }
+ v.reset(OpWasmI64Eqz)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Mul(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (I64Mul (I64Const [x]) (I64Const [y]))
+ // result: (I64Const [x * y])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(x * y)
+ return true
+ }
+ // match: (I64Mul (I64Const [x]) y)
+ // cond: y.Op != OpWasmI64Const
+ // result: (I64Mul y (I64Const [x]))
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(y.Op != OpWasmI64Const) {
+ break
+ }
+ v.reset(OpWasmI64Mul)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(x)
+ v.AddArg2(y, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Ne(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (I64Ne (I64Const [x]) (I64Const [y]))
+ // cond: x == y
+ // result: (I64Const [0])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ if !(x == y) {
+ break
+ }
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (I64Ne (I64Const [x]) (I64Const [y]))
+ // cond: x != y
+ // result: (I64Const [1])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ if !(x != y) {
+ break
+ }
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(1)
+ return true
+ }
+ // match: (I64Ne (I64Const [x]) y)
+ // cond: y.Op != OpWasmI64Const
+ // result: (I64Ne y (I64Const [x]))
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(y.Op != OpWasmI64Const) {
+ break
+ }
+ v.reset(OpWasmI64Ne)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(x)
+ v.AddArg2(y, v0)
+ return true
+ }
+ // match: (I64Ne x (I64Const [0]))
+ // result: (I64Eqz (I64Eqz x))
+ for {
+ x := v_0
+ if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpWasmI64Eqz)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Eqz, typ.Bool)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Or(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (I64Or (I64Const [x]) (I64Const [y]))
+ // result: (I64Const [x | y])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(x | y)
+ return true
+ }
+ // match: (I64Or (I64Const [x]) y)
+ // cond: y.Op != OpWasmI64Const
+ // result: (I64Or y (I64Const [x]))
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(y.Op != OpWasmI64Const) {
+ break
+ }
+ v.reset(OpWasmI64Or)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(x)
+ v.AddArg2(y, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Shl(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64Shl (I64Const [x]) (I64Const [y]))
+ // result: (I64Const [x << uint64(y)])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(x << uint64(y))
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64ShrS(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64ShrS (I64Const [x]) (I64Const [y]))
+ // result: (I64Const [x >> uint64(y)])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(x >> uint64(y))
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64ShrU(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64ShrU (I64Const [x]) (I64Const [y]))
+ // result: (I64Const [int64(uint64(x) >> uint64(y))])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(int64(uint64(x) >> uint64(y)))
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Store(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64Store [off] (I64AddConst [off2] ptr) val mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Store [off+off2] ptr val mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Store)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Store16(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64Store16 [off] (I64AddConst [off2] ptr) val mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Store16 [off+off2] ptr val mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Store16)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Store32(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64Store32 [off] (I64AddConst [off2] ptr) val mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Store32 [off+off2] ptr val mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Store32)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Store8(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (I64Store8 [off] (I64AddConst [off2] ptr) val mem)
+ // cond: isU32Bit(off+off2)
+ // result: (I64Store8 [off+off2] ptr val mem)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpWasmI64AddConst {
+ break
+ }
+ off2 := auxIntToInt64(v_0.AuxInt)
+ ptr := v_0.Args[0]
+ val := v_1
+ mem := v_2
+ if !(isU32Bit(off + off2)) {
+ break
+ }
+ v.reset(OpWasmI64Store8)
+ v.AuxInt = int64ToAuxInt(off + off2)
+ v.AddArg3(ptr, val, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpWasmI64Xor(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (I64Xor (I64Const [x]) (I64Const [y]))
+ // result: (I64Const [x ^ y])
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpWasmI64Const {
+ break
+ }
+ y := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpWasmI64Const)
+ v.AuxInt = int64ToAuxInt(x ^ y)
+ return true
+ }
+ // match: (I64Xor (I64Const [x]) y)
+ // cond: y.Op != OpWasmI64Const
+ // result: (I64Xor y (I64Const [x]))
+ for {
+ if v_0.Op != OpWasmI64Const {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ y := v_1
+ if !(y.Op != OpWasmI64Const) {
+ break
+ }
+ v.reset(OpWasmI64Xor)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(x)
+ v.AddArg2(y, v0)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Zero [0] _ mem)
+ // result: mem
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ mem := v_1
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero [1] destptr mem)
+ // result: (I64Store8 destptr (I64Const [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store8)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(destptr, v0, mem)
+ return true
+ }
+ // match: (Zero [2] destptr mem)
+ // result: (I64Store16 destptr (I64Const [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store16)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(destptr, v0, mem)
+ return true
+ }
+ // match: (Zero [4] destptr mem)
+ // result: (I64Store32 destptr (I64Const [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 4 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store32)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(destptr, v0, mem)
+ return true
+ }
+ // match: (Zero [8] destptr mem)
+ // result: (I64Store destptr (I64Const [0]) mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 8 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(destptr, v0, mem)
+ return true
+ }
+ // match: (Zero [3] destptr mem)
+ // result: (I64Store8 [2] destptr (I64Const [0]) (I64Store16 destptr (I64Const [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store8)
+ v.AuxInt = int64ToAuxInt(2)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store16, types.TypeMem)
+ v1.AddArg3(destptr, v0, mem)
+ v.AddArg3(destptr, v0, v1)
+ return true
+ }
+ // match: (Zero [5] destptr mem)
+ // result: (I64Store8 [4] destptr (I64Const [0]) (I64Store32 destptr (I64Const [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 5 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store8)
+ v.AuxInt = int64ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store32, types.TypeMem)
+ v1.AddArg3(destptr, v0, mem)
+ v.AddArg3(destptr, v0, v1)
+ return true
+ }
+ // match: (Zero [6] destptr mem)
+ // result: (I64Store16 [4] destptr (I64Const [0]) (I64Store32 destptr (I64Const [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 6 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store16)
+ v.AuxInt = int64ToAuxInt(4)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store32, types.TypeMem)
+ v1.AddArg3(destptr, v0, mem)
+ v.AddArg3(destptr, v0, v1)
+ return true
+ }
+ // match: (Zero [7] destptr mem)
+ // result: (I64Store32 [3] destptr (I64Const [0]) (I64Store32 destptr (I64Const [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 7 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store32)
+ v.AuxInt = int64ToAuxInt(3)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store32, types.TypeMem)
+ v1.AddArg3(destptr, v0, mem)
+ v.AddArg3(destptr, v0, v1)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s%8 != 0 && s > 8
+ // result: (Zero [s-s%8] (OffPtr <destptr.Type> destptr [s%8]) (I64Store destptr (I64Const [0]) mem))
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s%8 != 0 && s > 8) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(s - s%8)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type)
+ v0.AuxInt = int64ToAuxInt(s % 8)
+ v0.AddArg(destptr)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v2.AuxInt = int64ToAuxInt(0)
+ v1.AddArg3(destptr, v2, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Zero [16] destptr mem)
+ // result: (I64Store [8] destptr (I64Const [0]) (I64Store destptr (I64Const [0]) mem))
+ for {
+ if auxIntToInt64(v.AuxInt) != 16 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store)
+ v.AuxInt = int64ToAuxInt(8)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v1.AddArg3(destptr, v0, mem)
+ v.AddArg3(destptr, v0, v1)
+ return true
+ }
+ // match: (Zero [24] destptr mem)
+ // result: (I64Store [16] destptr (I64Const [0]) (I64Store [8] destptr (I64Const [0]) (I64Store destptr (I64Const [0]) mem)))
+ for {
+ if auxIntToInt64(v.AuxInt) != 24 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store)
+ v.AuxInt = int64ToAuxInt(16)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v1.AuxInt = int64ToAuxInt(8)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v2.AddArg3(destptr, v0, mem)
+ v1.AddArg3(destptr, v0, v2)
+ v.AddArg3(destptr, v0, v1)
+ return true
+ }
+ // match: (Zero [32] destptr mem)
+ // result: (I64Store [24] destptr (I64Const [0]) (I64Store [16] destptr (I64Const [0]) (I64Store [8] destptr (I64Const [0]) (I64Store destptr (I64Const [0]) mem))))
+ for {
+ if auxIntToInt64(v.AuxInt) != 32 {
+ break
+ }
+ destptr := v_0
+ mem := v_1
+ v.reset(OpWasmI64Store)
+ v.AuxInt = int64ToAuxInt(24)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0)
+ v1 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v1.AuxInt = int64ToAuxInt(16)
+ v2 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v2.AuxInt = int64ToAuxInt(8)
+ v3 := b.NewValue0(v.Pos, OpWasmI64Store, types.TypeMem)
+ v3.AddArg3(destptr, v0, mem)
+ v2.AddArg3(destptr, v0, v3)
+ v1.AddArg3(destptr, v0, v2)
+ v.AddArg3(destptr, v0, v1)
+ return true
+ }
+ // match: (Zero [s] destptr mem)
+ // cond: s%8 == 0 && s > 32
+ // result: (LoweredZero [s/8] destptr mem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ destptr := v_0
+ mem := v_1
+ if !(s%8 == 0 && s > 32) {
+ break
+ }
+ v.reset(OpWasmLoweredZero)
+ v.AuxInt = int64ToAuxInt(s / 8)
+ v.AddArg2(destptr, mem)
+ return true
+ }
+ return false
+}
+func rewriteValueWasm_OpZeroExt16to32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ZeroExt16to32 x:(I64Load16U _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load16U {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ZeroExt16to32 x)
+ // result: (I64And x (I64Const [0xffff]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64And)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0xffff)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpZeroExt16to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ZeroExt16to64 x:(I64Load16U _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load16U {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ZeroExt16to64 x)
+ // result: (I64And x (I64Const [0xffff]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64And)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0xffff)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpZeroExt32to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ZeroExt32to64 x:(I64Load32U _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load32U {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ZeroExt32to64 x)
+ // result: (I64And x (I64Const [0xffffffff]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64And)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0xffffffff)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpZeroExt8to16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ZeroExt8to16 x:(I64Load8U _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load8U {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ZeroExt8to16 x)
+ // result: (I64And x (I64Const [0xff]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64And)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0xff)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpZeroExt8to32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ZeroExt8to32 x:(I64Load8U _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load8U {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ZeroExt8to32 x)
+ // result: (I64And x (I64Const [0xff]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64And)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0xff)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValueWasm_OpZeroExt8to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ZeroExt8to64 x:(I64Load8U _ _))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpWasmI64Load8U {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (ZeroExt8to64 x)
+ // result: (I64And x (I64Const [0xff]))
+ for {
+ x := v_0
+ v.reset(OpWasmI64And)
+ v0 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
+ v0.AuxInt = int64ToAuxInt(0xff)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteBlockWasm(b *Block) bool {
+ switch b.Kind {
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewrite_test.go b/src/cmd/compile/internal/ssa/rewrite_test.go
new file mode 100644
index 0000000..64d128b
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewrite_test.go
@@ -0,0 +1,220 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import "testing"
+
+// We generate memmove for copy(x[1:], x[:]), however we may change it to OpMove,
+// because size is known. Check that OpMove is alias-safe, or we did call memmove.
+func TestMove(t *testing.T) {
+ x := [...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}
+ copy(x[1:], x[:])
+ for i := 1; i < len(x); i++ {
+ if int(x[i]) != i {
+ t.Errorf("Memmove got converted to OpMove in alias-unsafe way. Got %d insted of %d in position %d", int(x[i]), i, i+1)
+ }
+ }
+}
+
+func TestMoveSmall(t *testing.T) {
+ x := [...]byte{1, 2, 3, 4, 5, 6, 7}
+ copy(x[1:], x[:])
+ for i := 1; i < len(x); i++ {
+ if int(x[i]) != i {
+ t.Errorf("Memmove got converted to OpMove in alias-unsafe way. Got %d instead of %d in position %d", int(x[i]), i, i+1)
+ }
+ }
+}
+
+func TestSubFlags(t *testing.T) {
+ if !subFlags32(0, 1).lt() {
+ t.Errorf("subFlags32(0,1).lt() returned false")
+ }
+ if !subFlags32(0, 1).ult() {
+ t.Errorf("subFlags32(0,1).ult() returned false")
+ }
+}
+
+func TestIsPPC64WordRotateMask(t *testing.T) {
+ tests := []struct {
+ input int64
+ expected bool
+ }{
+ {0x00000001, true},
+ {0x80000001, true},
+ {0x80010001, false},
+ {0xFFFFFFFA, false},
+ {0xF0F0F0F0, false},
+ {0xFFFFFFFD, true},
+ {0x80000000, true},
+ {0x00000000, false},
+ {0xFFFFFFFF, true},
+ {0x0000FFFF, true},
+ {0xFF0000FF, true},
+ {0x00FFFF00, true},
+ }
+
+ for _, v := range tests {
+ if v.expected != isPPC64WordRotateMask(v.input) {
+ t.Errorf("isPPC64WordRotateMask(0x%x) failed", v.input)
+ }
+ }
+}
+
+func TestEncodeDecodePPC64WordRotateMask(t *testing.T) {
+ tests := []struct {
+ rotate int64
+ mask uint64
+ nbits,
+ mb,
+ me,
+ encoded int64
+ }{
+ {1, 0x00000001, 32, 31, 31, 0x20011f20},
+ {2, 0x80000001, 32, 31, 0, 0x20021f01},
+ {3, 0xFFFFFFFD, 32, 31, 29, 0x20031f1e},
+ {4, 0x80000000, 32, 0, 0, 0x20040001},
+ {5, 0xFFFFFFFF, 32, 0, 31, 0x20050020},
+ {6, 0x0000FFFF, 32, 16, 31, 0x20061020},
+ {7, 0xFF0000FF, 32, 24, 7, 0x20071808},
+ {8, 0x00FFFF00, 32, 8, 23, 0x20080818},
+
+ {9, 0x0000000000FFFF00, 64, 40, 55, 0x40092838},
+ {10, 0xFFFF000000000000, 64, 0, 15, 0x400A0010},
+ {10, 0xFFFF000000000001, 64, 63, 15, 0x400A3f10},
+ }
+
+ for i, v := range tests {
+ result := encodePPC64RotateMask(v.rotate, int64(v.mask), v.nbits)
+ if result != v.encoded {
+ t.Errorf("encodePPC64RotateMask(%d,0x%x,%d) = 0x%x, expected 0x%x", v.rotate, v.mask, v.nbits, result, v.encoded)
+ }
+ rotate, mb, me, mask := DecodePPC64RotateMask(result)
+ if rotate != v.rotate || mb != v.mb || me != v.me || mask != v.mask {
+ t.Errorf("DecodePPC64Failure(Test %d) got (%d, %d, %d, %x) expected (%d, %d, %d, %x)", i, rotate, mb, me, mask, v.rotate, v.mb, v.me, v.mask)
+ }
+ }
+}
+
+func TestMergePPC64ClrlsldiSrw(t *testing.T) {
+ tests := []struct {
+ clrlsldi int32
+ srw int64
+ valid bool
+ rotate int64
+ mask uint64
+ }{
+ // ((x>>4)&0xFF)<<4
+ {newPPC64ShiftAuxInt(4, 56, 63, 64), 4, true, 0, 0xFF0},
+ // ((x>>4)&0xFFFF)<<4
+ {newPPC64ShiftAuxInt(4, 48, 63, 64), 4, true, 0, 0xFFFF0},
+ // ((x>>4)&0xFFFF)<<17
+ {newPPC64ShiftAuxInt(17, 48, 63, 64), 4, false, 0, 0},
+ // ((x>>4)&0xFFFF)<<16
+ {newPPC64ShiftAuxInt(16, 48, 63, 64), 4, true, 12, 0xFFFF0000},
+ // ((x>>32)&0xFFFF)<<17
+ {newPPC64ShiftAuxInt(17, 48, 63, 64), 32, false, 0, 0},
+ }
+ for i, v := range tests {
+ result := mergePPC64ClrlsldiSrw(int64(v.clrlsldi), v.srw)
+ if v.valid && result == 0 {
+ t.Errorf("mergePPC64ClrlsldiSrw(Test %d) did not merge", i)
+ } else if !v.valid && result != 0 {
+ t.Errorf("mergePPC64ClrlsldiSrw(Test %d) should return 0", i)
+ } else if r, _, _, m := DecodePPC64RotateMask(result); v.rotate != r || v.mask != m {
+ t.Errorf("mergePPC64ClrlsldiSrw(Test %d) got (%d,0x%x) expected (%d,0x%x)", i, r, m, v.rotate, v.mask)
+ }
+ }
+}
+
+func TestMergePPC64ClrlsldiRlwinm(t *testing.T) {
+ tests := []struct {
+ clrlsldi int32
+ rlwinm int64
+ valid bool
+ rotate int64
+ mask uint64
+ }{
+ // ((x<<4)&0xFF00)<<4
+ {newPPC64ShiftAuxInt(4, 56, 63, 64), encodePPC64RotateMask(4, 0xFF00, 32), false, 0, 0},
+ // ((x>>4)&0xFF)<<4
+ {newPPC64ShiftAuxInt(4, 56, 63, 64), encodePPC64RotateMask(28, 0x0FFFFFFF, 32), true, 0, 0xFF0},
+ // ((x>>4)&0xFFFF)<<4
+ {newPPC64ShiftAuxInt(4, 48, 63, 64), encodePPC64RotateMask(28, 0xFFFF, 32), true, 0, 0xFFFF0},
+ // ((x>>4)&0xFFFF)<<17
+ {newPPC64ShiftAuxInt(17, 48, 63, 64), encodePPC64RotateMask(28, 0xFFFF, 32), false, 0, 0},
+ // ((x>>4)&0xFFFF)<<16
+ {newPPC64ShiftAuxInt(16, 48, 63, 64), encodePPC64RotateMask(28, 0xFFFF, 32), true, 12, 0xFFFF0000},
+ // ((x>>4)&0xF000FFFF)<<16
+ {newPPC64ShiftAuxInt(16, 48, 63, 64), encodePPC64RotateMask(28, 0xF000FFFF, 32), true, 12, 0xFFFF0000},
+ }
+ for i, v := range tests {
+ result := mergePPC64ClrlsldiRlwinm(v.clrlsldi, v.rlwinm)
+ if v.valid && result == 0 {
+ t.Errorf("mergePPC64ClrlsldiRlwinm(Test %d) did not merge", i)
+ } else if !v.valid && result != 0 {
+ t.Errorf("mergePPC64ClrlsldiRlwinm(Test %d) should return 0", i)
+ } else if r, _, _, m := DecodePPC64RotateMask(result); v.rotate != r || v.mask != m {
+ t.Errorf("mergePPC64ClrlsldiRlwinm(Test %d) got (%d,0x%x) expected (%d,0x%x)", i, r, m, v.rotate, v.mask)
+ }
+ }
+}
+
+func TestMergePPC64SldiSrw(t *testing.T) {
+ tests := []struct {
+ sld int64
+ srw int64
+ valid bool
+ rotate int64
+ mask uint64
+ }{
+ {4, 4, true, 0, 0xFFFFFFF0},
+ {4, 8, true, 28, 0x0FFFFFF0},
+ {0, 0, true, 0, 0xFFFFFFFF},
+ {8, 4, false, 0, 0},
+ {0, 32, false, 0, 0},
+ {0, 31, true, 1, 0x1},
+ {31, 31, true, 0, 0x80000000},
+ {32, 32, false, 0, 0},
+ }
+ for i, v := range tests {
+ result := mergePPC64SldiSrw(v.sld, v.srw)
+ if v.valid && result == 0 {
+ t.Errorf("mergePPC64SldiSrw(Test %d) did not merge", i)
+ } else if !v.valid && result != 0 {
+ t.Errorf("mergePPC64SldiSrw(Test %d) should return 0", i)
+ } else if r, _, _, m := DecodePPC64RotateMask(result); v.rotate != r || v.mask != m {
+ t.Errorf("mergePPC64SldiSrw(Test %d) got (%d,0x%x) expected (%d,0x%x)", i, r, m, v.rotate, v.mask)
+ }
+ }
+}
+
+func TestMergePPC64AndSrwi(t *testing.T) {
+ tests := []struct {
+ and int64
+ srw int64
+ valid bool
+ rotate int64
+ mask uint64
+ }{
+ {0x000000FF, 8, true, 24, 0xFF},
+ {0xF00000FF, 8, true, 24, 0xFF},
+ {0x0F0000FF, 4, false, 0, 0},
+ {0x00000000, 4, false, 0, 0},
+ {0xF0000000, 4, false, 0, 0},
+ {0xF0000000, 32, false, 0, 0},
+ {0xFFFFFFFF, 0, true, 0, 0xFFFFFFFF},
+ }
+ for i, v := range tests {
+ result := mergePPC64AndSrwi(v.and, v.srw)
+ if v.valid && result == 0 {
+ t.Errorf("mergePPC64AndSrwi(Test %d) did not merge", i)
+ } else if !v.valid && result != 0 {
+ t.Errorf("mergePPC64AndSrwi(Test %d) should return 0", i)
+ } else if r, _, _, m := DecodePPC64RotateMask(result); v.rotate != r || v.mask != m {
+ t.Errorf("mergePPC64AndSrwi(Test %d) got (%d,0x%x) expected (%d,0x%x)", i, r, m, v.rotate, v.mask)
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/rewritedec.go b/src/cmd/compile/internal/ssa/rewritedec.go
new file mode 100644
index 0000000..e0fa976
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewritedec.go
@@ -0,0 +1,415 @@
+// Code generated from gen/dec.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "cmd/compile/internal/types"
+
+func rewriteValuedec(v *Value) bool {
+ switch v.Op {
+ case OpComplexImag:
+ return rewriteValuedec_OpComplexImag(v)
+ case OpComplexReal:
+ return rewriteValuedec_OpComplexReal(v)
+ case OpIData:
+ return rewriteValuedec_OpIData(v)
+ case OpITab:
+ return rewriteValuedec_OpITab(v)
+ case OpLoad:
+ return rewriteValuedec_OpLoad(v)
+ case OpSliceCap:
+ return rewriteValuedec_OpSliceCap(v)
+ case OpSliceLen:
+ return rewriteValuedec_OpSliceLen(v)
+ case OpSlicePtr:
+ return rewriteValuedec_OpSlicePtr(v)
+ case OpStore:
+ return rewriteValuedec_OpStore(v)
+ case OpStringLen:
+ return rewriteValuedec_OpStringLen(v)
+ case OpStringPtr:
+ return rewriteValuedec_OpStringPtr(v)
+ }
+ return false
+}
+func rewriteValuedec_OpComplexImag(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ComplexImag (ComplexMake _ imag ))
+ // result: imag
+ for {
+ if v_0.Op != OpComplexMake {
+ break
+ }
+ imag := v_0.Args[1]
+ v.copyOf(imag)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpComplexReal(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ComplexReal (ComplexMake real _ ))
+ // result: real
+ for {
+ if v_0.Op != OpComplexMake {
+ break
+ }
+ real := v_0.Args[0]
+ v.copyOf(real)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpIData(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (IData (IMake _ data))
+ // result: data
+ for {
+ if v_0.Op != OpIMake {
+ break
+ }
+ data := v_0.Args[1]
+ v.copyOf(data)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpITab(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ITab (IMake itab _))
+ // result: itab
+ for {
+ if v_0.Op != OpIMake {
+ break
+ }
+ itab := v_0.Args[0]
+ v.copyOf(itab)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Load <t> ptr mem)
+ // cond: t.IsComplex() && t.Size() == 8
+ // result: (ComplexMake (Load <typ.Float32> ptr mem) (Load <typ.Float32> (OffPtr <typ.Float32Ptr> [4] ptr) mem) )
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsComplex() && t.Size() == 8) {
+ break
+ }
+ v.reset(OpComplexMake)
+ v0 := b.NewValue0(v.Pos, OpLoad, typ.Float32)
+ v0.AddArg2(ptr, mem)
+ v1 := b.NewValue0(v.Pos, OpLoad, typ.Float32)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, typ.Float32Ptr)
+ v2.AuxInt = int64ToAuxInt(4)
+ v2.AddArg(ptr)
+ v1.AddArg2(v2, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.IsComplex() && t.Size() == 16
+ // result: (ComplexMake (Load <typ.Float64> ptr mem) (Load <typ.Float64> (OffPtr <typ.Float64Ptr> [8] ptr) mem) )
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsComplex() && t.Size() == 16) {
+ break
+ }
+ v.reset(OpComplexMake)
+ v0 := b.NewValue0(v.Pos, OpLoad, typ.Float64)
+ v0.AddArg2(ptr, mem)
+ v1 := b.NewValue0(v.Pos, OpLoad, typ.Float64)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, typ.Float64Ptr)
+ v2.AuxInt = int64ToAuxInt(8)
+ v2.AddArg(ptr)
+ v1.AddArg2(v2, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.IsString()
+ // result: (StringMake (Load <typ.BytePtr> ptr mem) (Load <typ.Int> (OffPtr <typ.IntPtr> [config.PtrSize] ptr) mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsString()) {
+ break
+ }
+ v.reset(OpStringMake)
+ v0 := b.NewValue0(v.Pos, OpLoad, typ.BytePtr)
+ v0.AddArg2(ptr, mem)
+ v1 := b.NewValue0(v.Pos, OpLoad, typ.Int)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, typ.IntPtr)
+ v2.AuxInt = int64ToAuxInt(config.PtrSize)
+ v2.AddArg(ptr)
+ v1.AddArg2(v2, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.IsSlice()
+ // result: (SliceMake (Load <t.Elem().PtrTo()> ptr mem) (Load <typ.Int> (OffPtr <typ.IntPtr> [config.PtrSize] ptr) mem) (Load <typ.Int> (OffPtr <typ.IntPtr> [2*config.PtrSize] ptr) mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsSlice()) {
+ break
+ }
+ v.reset(OpSliceMake)
+ v0 := b.NewValue0(v.Pos, OpLoad, t.Elem().PtrTo())
+ v0.AddArg2(ptr, mem)
+ v1 := b.NewValue0(v.Pos, OpLoad, typ.Int)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, typ.IntPtr)
+ v2.AuxInt = int64ToAuxInt(config.PtrSize)
+ v2.AddArg(ptr)
+ v1.AddArg2(v2, mem)
+ v3 := b.NewValue0(v.Pos, OpLoad, typ.Int)
+ v4 := b.NewValue0(v.Pos, OpOffPtr, typ.IntPtr)
+ v4.AuxInt = int64ToAuxInt(2 * config.PtrSize)
+ v4.AddArg(ptr)
+ v3.AddArg2(v4, mem)
+ v.AddArg3(v0, v1, v3)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.IsInterface()
+ // result: (IMake (Load <typ.Uintptr> ptr mem) (Load <typ.BytePtr> (OffPtr <typ.BytePtrPtr> [config.PtrSize] ptr) mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsInterface()) {
+ break
+ }
+ v.reset(OpIMake)
+ v0 := b.NewValue0(v.Pos, OpLoad, typ.Uintptr)
+ v0.AddArg2(ptr, mem)
+ v1 := b.NewValue0(v.Pos, OpLoad, typ.BytePtr)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, typ.BytePtrPtr)
+ v2.AuxInt = int64ToAuxInt(config.PtrSize)
+ v2.AddArg(ptr)
+ v1.AddArg2(v2, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpSliceCap(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SliceCap (SliceMake _ _ cap))
+ // result: cap
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ cap := v_0.Args[2]
+ v.copyOf(cap)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpSliceLen(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SliceLen (SliceMake _ len _))
+ // result: len
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ len := v_0.Args[1]
+ v.copyOf(len)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpSlicePtr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SlicePtr (SliceMake ptr _ _ ))
+ // result: ptr
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ ptr := v_0.Args[0]
+ v.copyOf(ptr)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Store {t} dst (ComplexMake real imag) mem)
+ // cond: t.Size() == 8
+ // result: (Store {typ.Float32} (OffPtr <typ.Float32Ptr> [4] dst) imag (Store {typ.Float32} dst real mem))
+ for {
+ t := auxToType(v.Aux)
+ dst := v_0
+ if v_1.Op != OpComplexMake {
+ break
+ }
+ imag := v_1.Args[1]
+ real := v_1.Args[0]
+ mem := v_2
+ if !(t.Size() == 8) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(typ.Float32)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, typ.Float32Ptr)
+ v0.AuxInt = int64ToAuxInt(4)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(typ.Float32)
+ v1.AddArg3(dst, real, mem)
+ v.AddArg3(v0, imag, v1)
+ return true
+ }
+ // match: (Store {t} dst (ComplexMake real imag) mem)
+ // cond: t.Size() == 16
+ // result: (Store {typ.Float64} (OffPtr <typ.Float64Ptr> [8] dst) imag (Store {typ.Float64} dst real mem))
+ for {
+ t := auxToType(v.Aux)
+ dst := v_0
+ if v_1.Op != OpComplexMake {
+ break
+ }
+ imag := v_1.Args[1]
+ real := v_1.Args[0]
+ mem := v_2
+ if !(t.Size() == 16) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(typ.Float64)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, typ.Float64Ptr)
+ v0.AuxInt = int64ToAuxInt(8)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(typ.Float64)
+ v1.AddArg3(dst, real, mem)
+ v.AddArg3(v0, imag, v1)
+ return true
+ }
+ // match: (Store dst (StringMake ptr len) mem)
+ // result: (Store {typ.Int} (OffPtr <typ.IntPtr> [config.PtrSize] dst) len (Store {typ.BytePtr} dst ptr mem))
+ for {
+ dst := v_0
+ if v_1.Op != OpStringMake {
+ break
+ }
+ len := v_1.Args[1]
+ ptr := v_1.Args[0]
+ mem := v_2
+ v.reset(OpStore)
+ v.Aux = typeToAux(typ.Int)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, typ.IntPtr)
+ v0.AuxInt = int64ToAuxInt(config.PtrSize)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(typ.BytePtr)
+ v1.AddArg3(dst, ptr, mem)
+ v.AddArg3(v0, len, v1)
+ return true
+ }
+ // match: (Store {t} dst (SliceMake ptr len cap) mem)
+ // result: (Store {typ.Int} (OffPtr <typ.IntPtr> [2*config.PtrSize] dst) cap (Store {typ.Int} (OffPtr <typ.IntPtr> [config.PtrSize] dst) len (Store {t.Elem().PtrTo()} dst ptr mem)))
+ for {
+ t := auxToType(v.Aux)
+ dst := v_0
+ if v_1.Op != OpSliceMake {
+ break
+ }
+ cap := v_1.Args[2]
+ ptr := v_1.Args[0]
+ len := v_1.Args[1]
+ mem := v_2
+ v.reset(OpStore)
+ v.Aux = typeToAux(typ.Int)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, typ.IntPtr)
+ v0.AuxInt = int64ToAuxInt(2 * config.PtrSize)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(typ.Int)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, typ.IntPtr)
+ v2.AuxInt = int64ToAuxInt(config.PtrSize)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t.Elem().PtrTo())
+ v3.AddArg3(dst, ptr, mem)
+ v1.AddArg3(v2, len, v3)
+ v.AddArg3(v0, cap, v1)
+ return true
+ }
+ // match: (Store dst (IMake itab data) mem)
+ // result: (Store {typ.BytePtr} (OffPtr <typ.BytePtrPtr> [config.PtrSize] dst) data (Store {typ.Uintptr} dst itab mem))
+ for {
+ dst := v_0
+ if v_1.Op != OpIMake {
+ break
+ }
+ data := v_1.Args[1]
+ itab := v_1.Args[0]
+ mem := v_2
+ v.reset(OpStore)
+ v.Aux = typeToAux(typ.BytePtr)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, typ.BytePtrPtr)
+ v0.AuxInt = int64ToAuxInt(config.PtrSize)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(typ.Uintptr)
+ v1.AddArg3(dst, itab, mem)
+ v.AddArg3(v0, data, v1)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpStringLen(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (StringLen (StringMake _ len))
+ // result: len
+ for {
+ if v_0.Op != OpStringMake {
+ break
+ }
+ len := v_0.Args[1]
+ v.copyOf(len)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpStringPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (StringPtr (StringMake ptr _))
+ // result: ptr
+ for {
+ if v_0.Op != OpStringMake {
+ break
+ }
+ ptr := v_0.Args[0]
+ v.copyOf(ptr)
+ return true
+ }
+ return false
+}
+func rewriteBlockdec(b *Block) bool {
+ switch b.Kind {
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewritedec64.go b/src/cmd/compile/internal/ssa/rewritedec64.go
new file mode 100644
index 0000000..c49bc80
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewritedec64.go
@@ -0,0 +1,2464 @@
+// Code generated from gen/dec64.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "cmd/compile/internal/types"
+
+func rewriteValuedec64(v *Value) bool {
+ switch v.Op {
+ case OpAdd64:
+ return rewriteValuedec64_OpAdd64(v)
+ case OpAnd64:
+ return rewriteValuedec64_OpAnd64(v)
+ case OpArg:
+ return rewriteValuedec64_OpArg(v)
+ case OpBitLen64:
+ return rewriteValuedec64_OpBitLen64(v)
+ case OpBswap64:
+ return rewriteValuedec64_OpBswap64(v)
+ case OpCom64:
+ return rewriteValuedec64_OpCom64(v)
+ case OpConst64:
+ return rewriteValuedec64_OpConst64(v)
+ case OpCtz64:
+ return rewriteValuedec64_OpCtz64(v)
+ case OpCtz64NonZero:
+ v.Op = OpCtz64
+ return true
+ case OpEq64:
+ return rewriteValuedec64_OpEq64(v)
+ case OpInt64Hi:
+ return rewriteValuedec64_OpInt64Hi(v)
+ case OpInt64Lo:
+ return rewriteValuedec64_OpInt64Lo(v)
+ case OpLeq64:
+ return rewriteValuedec64_OpLeq64(v)
+ case OpLeq64U:
+ return rewriteValuedec64_OpLeq64U(v)
+ case OpLess64:
+ return rewriteValuedec64_OpLess64(v)
+ case OpLess64U:
+ return rewriteValuedec64_OpLess64U(v)
+ case OpLoad:
+ return rewriteValuedec64_OpLoad(v)
+ case OpLsh16x64:
+ return rewriteValuedec64_OpLsh16x64(v)
+ case OpLsh32x64:
+ return rewriteValuedec64_OpLsh32x64(v)
+ case OpLsh64x16:
+ return rewriteValuedec64_OpLsh64x16(v)
+ case OpLsh64x32:
+ return rewriteValuedec64_OpLsh64x32(v)
+ case OpLsh64x64:
+ return rewriteValuedec64_OpLsh64x64(v)
+ case OpLsh64x8:
+ return rewriteValuedec64_OpLsh64x8(v)
+ case OpLsh8x64:
+ return rewriteValuedec64_OpLsh8x64(v)
+ case OpMul64:
+ return rewriteValuedec64_OpMul64(v)
+ case OpNeg64:
+ return rewriteValuedec64_OpNeg64(v)
+ case OpNeq64:
+ return rewriteValuedec64_OpNeq64(v)
+ case OpOr32:
+ return rewriteValuedec64_OpOr32(v)
+ case OpOr64:
+ return rewriteValuedec64_OpOr64(v)
+ case OpRsh16Ux64:
+ return rewriteValuedec64_OpRsh16Ux64(v)
+ case OpRsh16x64:
+ return rewriteValuedec64_OpRsh16x64(v)
+ case OpRsh32Ux64:
+ return rewriteValuedec64_OpRsh32Ux64(v)
+ case OpRsh32x64:
+ return rewriteValuedec64_OpRsh32x64(v)
+ case OpRsh64Ux16:
+ return rewriteValuedec64_OpRsh64Ux16(v)
+ case OpRsh64Ux32:
+ return rewriteValuedec64_OpRsh64Ux32(v)
+ case OpRsh64Ux64:
+ return rewriteValuedec64_OpRsh64Ux64(v)
+ case OpRsh64Ux8:
+ return rewriteValuedec64_OpRsh64Ux8(v)
+ case OpRsh64x16:
+ return rewriteValuedec64_OpRsh64x16(v)
+ case OpRsh64x32:
+ return rewriteValuedec64_OpRsh64x32(v)
+ case OpRsh64x64:
+ return rewriteValuedec64_OpRsh64x64(v)
+ case OpRsh64x8:
+ return rewriteValuedec64_OpRsh64x8(v)
+ case OpRsh8Ux64:
+ return rewriteValuedec64_OpRsh8Ux64(v)
+ case OpRsh8x64:
+ return rewriteValuedec64_OpRsh8x64(v)
+ case OpSignExt16to64:
+ return rewriteValuedec64_OpSignExt16to64(v)
+ case OpSignExt32to64:
+ return rewriteValuedec64_OpSignExt32to64(v)
+ case OpSignExt8to64:
+ return rewriteValuedec64_OpSignExt8to64(v)
+ case OpStore:
+ return rewriteValuedec64_OpStore(v)
+ case OpSub64:
+ return rewriteValuedec64_OpSub64(v)
+ case OpTrunc64to16:
+ return rewriteValuedec64_OpTrunc64to16(v)
+ case OpTrunc64to32:
+ return rewriteValuedec64_OpTrunc64to32(v)
+ case OpTrunc64to8:
+ return rewriteValuedec64_OpTrunc64to8(v)
+ case OpXor64:
+ return rewriteValuedec64_OpXor64(v)
+ case OpZeroExt16to64:
+ return rewriteValuedec64_OpZeroExt16to64(v)
+ case OpZeroExt32to64:
+ return rewriteValuedec64_OpZeroExt32to64(v)
+ case OpZeroExt8to64:
+ return rewriteValuedec64_OpZeroExt8to64(v)
+ }
+ return false
+}
+func rewriteValuedec64_OpAdd64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Add64 x y)
+ // result: (Int64Make (Add32withcarry <typ.Int32> (Int64Hi x) (Int64Hi y) (Select1 <types.TypeFlags> (Add32carry (Int64Lo x) (Int64Lo y)))) (Select0 <typ.UInt32> (Add32carry (Int64Lo x) (Int64Lo y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpAdd32withcarry, typ.Int32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpAdd32carry, types.NewTuple(typ.UInt32, types.TypeFlags))
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v6 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v6.AddArg(y)
+ v4.AddArg2(v5, v6)
+ v3.AddArg(v4)
+ v0.AddArg3(v1, v2, v3)
+ v7 := b.NewValue0(v.Pos, OpSelect0, typ.UInt32)
+ v7.AddArg(v4)
+ v.AddArg2(v0, v7)
+ return true
+ }
+}
+func rewriteValuedec64_OpAnd64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (And64 x y)
+ // result: (Int64Make (And32 <typ.UInt32> (Int64Hi x) (Int64Hi y)) (And32 <typ.UInt32> (Int64Lo x) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpAnd32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpAnd32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v4.AddArg(x)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(y)
+ v3.AddArg2(v4, v5)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValuedec64_OpArg(v *Value) bool {
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Arg {n} [off])
+ // cond: is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")
+ // result: (Int64Make (Arg <typ.Int32> {n} [off+4]) (Arg <typ.UInt32> {n} [off]))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpArg, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(off + 4)
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(off)
+ v1.Aux = symToAux(n)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Arg {n} [off])
+ // cond: is64BitInt(v.Type) && !config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")
+ // result: (Int64Make (Arg <typ.UInt32> {n} [off+4]) (Arg <typ.UInt32> {n} [off]))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(is64BitInt(v.Type) && !config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpArg, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(off + 4)
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(off)
+ v1.Aux = symToAux(n)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Arg {n} [off])
+ // cond: is64BitInt(v.Type) && config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")
+ // result: (Int64Make (Arg <typ.Int32> {n} [off]) (Arg <typ.UInt32> {n} [off+4]))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(is64BitInt(v.Type) && config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpArg, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(off + 4)
+ v1.Aux = symToAux(n)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Arg {n} [off])
+ // cond: is64BitInt(v.Type) && config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")
+ // result: (Int64Make (Arg <typ.UInt32> {n} [off]) (Arg <typ.UInt32> {n} [off+4]))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(is64BitInt(v.Type) && config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpArg, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(off + 4)
+ v1.Aux = symToAux(n)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValuedec64_OpBitLen64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (BitLen64 x)
+ // result: (Add32 <typ.Int> (BitLen32 <typ.Int> (Int64Hi x)) (BitLen32 <typ.Int> (Or32 <typ.UInt32> (Int64Lo x) (Zeromask (Int64Hi x)))))
+ for {
+ x := v_0
+ v.reset(OpAdd32)
+ v.Type = typ.Int
+ v0 := b.NewValue0(v.Pos, OpBitLen32, typ.Int)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v2 := b.NewValue0(v.Pos, OpBitLen32, typ.Int)
+ v3 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v4.AddArg(x)
+ v5 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v5.AddArg(v1)
+ v3.AddArg2(v4, v5)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValuedec64_OpBswap64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Bswap64 x)
+ // result: (Int64Make (Bswap32 <typ.UInt32> (Int64Lo x)) (Bswap32 <typ.UInt32> (Int64Hi x)))
+ for {
+ x := v_0
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpBswap32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v2 := b.NewValue0(v.Pos, OpBswap32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v3.AddArg(x)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValuedec64_OpCom64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Com64 x)
+ // result: (Int64Make (Com32 <typ.UInt32> (Int64Hi x)) (Com32 <typ.UInt32> (Int64Lo x)))
+ for {
+ x := v_0
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpCom32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v2 := b.NewValue0(v.Pos, OpCom32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(x)
+ v2.AddArg(v3)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValuedec64_OpConst64(v *Value) bool {
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Const64 <t> [c])
+ // cond: t.IsSigned()
+ // result: (Int64Make (Const32 <typ.Int32> [int32(c>>32)]) (Const32 <typ.UInt32> [int32(c)]))
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if !(t.IsSigned()) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpConst32, typ.Int32)
+ v0.AuxInt = int32ToAuxInt(int32(c >> 32))
+ v1 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Const64 <t> [c])
+ // cond: !t.IsSigned()
+ // result: (Int64Make (Const32 <typ.UInt32> [int32(c>>32)]) (Const32 <typ.UInt32> [int32(c)]))
+ for {
+ t := v.Type
+ c := auxIntToInt64(v.AuxInt)
+ if !(!t.IsSigned()) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(int32(c >> 32))
+ v1 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValuedec64_OpCtz64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Ctz64 x)
+ // result: (Add32 <typ.UInt32> (Ctz32 <typ.UInt32> (Int64Lo x)) (And32 <typ.UInt32> (Com32 <typ.UInt32> (Zeromask (Int64Lo x))) (Ctz32 <typ.UInt32> (Int64Hi x))))
+ for {
+ x := v_0
+ v.reset(OpAdd32)
+ v.Type = typ.UInt32
+ v0 := b.NewValue0(v.Pos, OpCtz32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v2 := b.NewValue0(v.Pos, OpAnd32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpCom32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v4.AddArg(v1)
+ v3.AddArg(v4)
+ v5 := b.NewValue0(v.Pos, OpCtz32, typ.UInt32)
+ v6 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v6.AddArg(x)
+ v5.AddArg(v6)
+ v2.AddArg2(v3, v5)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValuedec64_OpEq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq64 x y)
+ // result: (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Eq32 (Int64Lo x) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpAndB)
+ v0 := b.NewValue0(v.Pos, OpEq32, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpEq32, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v4.AddArg(x)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(y)
+ v3.AddArg2(v4, v5)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValuedec64_OpInt64Hi(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Int64Hi (Int64Make hi _))
+ // result: hi
+ for {
+ if v_0.Op != OpInt64Make {
+ break
+ }
+ hi := v_0.Args[0]
+ v.copyOf(hi)
+ return true
+ }
+ return false
+}
+func rewriteValuedec64_OpInt64Lo(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Int64Lo (Int64Make _ lo))
+ // result: lo
+ for {
+ if v_0.Op != OpInt64Make {
+ break
+ }
+ lo := v_0.Args[1]
+ v.copyOf(lo)
+ return true
+ }
+ return false
+}
+func rewriteValuedec64_OpLeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq64 x y)
+ // result: (OrB (Less32 (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Leq32U (Int64Lo x) (Int64Lo y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpOrB)
+ v0 := b.NewValue0(v.Pos, OpLess32, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpAndB, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpEq32, typ.Bool)
+ v4.AddArg2(v1, v2)
+ v5 := b.NewValue0(v.Pos, OpLeq32U, typ.Bool)
+ v6 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v6.AddArg(x)
+ v7 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v7.AddArg(y)
+ v5.AddArg2(v6, v7)
+ v3.AddArg2(v4, v5)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValuedec64_OpLeq64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Leq64U x y)
+ // result: (OrB (Less32U (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Leq32U (Int64Lo x) (Int64Lo y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpOrB)
+ v0 := b.NewValue0(v.Pos, OpLess32U, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpAndB, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpEq32, typ.Bool)
+ v4.AddArg2(v1, v2)
+ v5 := b.NewValue0(v.Pos, OpLeq32U, typ.Bool)
+ v6 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v6.AddArg(x)
+ v7 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v7.AddArg(y)
+ v5.AddArg2(v6, v7)
+ v3.AddArg2(v4, v5)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValuedec64_OpLess64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less64 x y)
+ // result: (OrB (Less32 (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Less32U (Int64Lo x) (Int64Lo y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpOrB)
+ v0 := b.NewValue0(v.Pos, OpLess32, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpAndB, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpEq32, typ.Bool)
+ v4.AddArg2(v1, v2)
+ v5 := b.NewValue0(v.Pos, OpLess32U, typ.Bool)
+ v6 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v6.AddArg(x)
+ v7 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v7.AddArg(y)
+ v5.AddArg2(v6, v7)
+ v3.AddArg2(v4, v5)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValuedec64_OpLess64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Less64U x y)
+ // result: (OrB (Less32U (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Less32U (Int64Lo x) (Int64Lo y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpOrB)
+ v0 := b.NewValue0(v.Pos, OpLess32U, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpAndB, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpEq32, typ.Bool)
+ v4.AddArg2(v1, v2)
+ v5 := b.NewValue0(v.Pos, OpLess32U, typ.Bool)
+ v6 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v6.AddArg(x)
+ v7 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v7.AddArg(y)
+ v5.AddArg2(v6, v7)
+ v3.AddArg2(v4, v5)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValuedec64_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Load <t> ptr mem)
+ // cond: is64BitInt(t) && !config.BigEndian && t.IsSigned()
+ // result: (Int64Make (Load <typ.Int32> (OffPtr <typ.Int32Ptr> [4] ptr) mem) (Load <typ.UInt32> ptr mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitInt(t) && !config.BigEndian && t.IsSigned()) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpLoad, typ.Int32)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, typ.Int32Ptr)
+ v1.AuxInt = int64ToAuxInt(4)
+ v1.AddArg(ptr)
+ v0.AddArg2(v1, mem)
+ v2 := b.NewValue0(v.Pos, OpLoad, typ.UInt32)
+ v2.AddArg2(ptr, mem)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitInt(t) && !config.BigEndian && !t.IsSigned()
+ // result: (Int64Make (Load <typ.UInt32> (OffPtr <typ.UInt32Ptr> [4] ptr) mem) (Load <typ.UInt32> ptr mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitInt(t) && !config.BigEndian && !t.IsSigned()) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpLoad, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, typ.UInt32Ptr)
+ v1.AuxInt = int64ToAuxInt(4)
+ v1.AddArg(ptr)
+ v0.AddArg2(v1, mem)
+ v2 := b.NewValue0(v.Pos, OpLoad, typ.UInt32)
+ v2.AddArg2(ptr, mem)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitInt(t) && config.BigEndian && t.IsSigned()
+ // result: (Int64Make (Load <typ.Int32> ptr mem) (Load <typ.UInt32> (OffPtr <typ.UInt32Ptr> [4] ptr) mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitInt(t) && config.BigEndian && t.IsSigned()) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpLoad, typ.Int32)
+ v0.AddArg2(ptr, mem)
+ v1 := b.NewValue0(v.Pos, OpLoad, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, typ.UInt32Ptr)
+ v2.AuxInt = int64ToAuxInt(4)
+ v2.AddArg(ptr)
+ v1.AddArg2(v2, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: is64BitInt(t) && config.BigEndian && !t.IsSigned()
+ // result: (Int64Make (Load <typ.UInt32> ptr mem) (Load <typ.UInt32> (OffPtr <typ.UInt32Ptr> [4] ptr) mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(is64BitInt(t) && config.BigEndian && !t.IsSigned()) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpLoad, typ.UInt32)
+ v0.AddArg2(ptr, mem)
+ v1 := b.NewValue0(v.Pos, OpLoad, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, typ.UInt32Ptr)
+ v2.AuxInt = int64ToAuxInt(4)
+ v2.AddArg(ptr)
+ v1.AddArg2(v2, mem)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ return false
+}
+func rewriteValuedec64_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x64 _ (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh16x64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Lsh16x32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpLsh16x32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Lsh16x64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Lsh16x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpLsh16x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh16x64 x y)
+ // result: (Lsh16x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpLsh16x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x64 _ (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh32x64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Lsh32x32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpLsh32x32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Lsh32x64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Lsh32x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpLsh32x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh32x64 x y)
+ // result: (Lsh32x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpLsh32x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpLsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x16 x s)
+ // result: (Int64Make (Or32 <typ.UInt32> (Or32 <typ.UInt32> (Lsh32x16 <typ.UInt32> (Int64Hi x) s) (Rsh32Ux16 <typ.UInt32> (Int64Lo x) (Sub16 <typ.UInt16> (Const16 <typ.UInt16> [32]) s))) (Lsh32x16 <typ.UInt32> (Int64Lo x) (Sub16 <typ.UInt16> s (Const16 <typ.UInt16> [32])))) (Lsh32x16 <typ.UInt32> (Int64Lo x) s))
+ for {
+ x := v_0
+ s := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpLsh32x16, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v3.AddArg(x)
+ v2.AddArg2(v3, s)
+ v4 := b.NewValue0(v.Pos, OpRsh32Ux16, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v6 := b.NewValue0(v.Pos, OpSub16, typ.UInt16)
+ v7 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v7.AuxInt = int16ToAuxInt(32)
+ v6.AddArg2(v7, s)
+ v4.AddArg2(v5, v6)
+ v1.AddArg2(v2, v4)
+ v8 := b.NewValue0(v.Pos, OpLsh32x16, typ.UInt32)
+ v9 := b.NewValue0(v.Pos, OpSub16, typ.UInt16)
+ v9.AddArg2(s, v7)
+ v8.AddArg2(v5, v9)
+ v0.AddArg2(v1, v8)
+ v10 := b.NewValue0(v.Pos, OpLsh32x16, typ.UInt32)
+ v10.AddArg2(v5, s)
+ v.AddArg2(v0, v10)
+ return true
+ }
+}
+func rewriteValuedec64_OpLsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x32 x s)
+ // result: (Int64Make (Or32 <typ.UInt32> (Or32 <typ.UInt32> (Lsh32x32 <typ.UInt32> (Int64Hi x) s) (Rsh32Ux32 <typ.UInt32> (Int64Lo x) (Sub32 <typ.UInt32> (Const32 <typ.UInt32> [32]) s))) (Lsh32x32 <typ.UInt32> (Int64Lo x) (Sub32 <typ.UInt32> s (Const32 <typ.UInt32> [32])))) (Lsh32x32 <typ.UInt32> (Int64Lo x) s))
+ for {
+ x := v_0
+ s := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpLsh32x32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v3.AddArg(x)
+ v2.AddArg2(v3, s)
+ v4 := b.NewValue0(v.Pos, OpRsh32Ux32, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v6 := b.NewValue0(v.Pos, OpSub32, typ.UInt32)
+ v7 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v7.AuxInt = int32ToAuxInt(32)
+ v6.AddArg2(v7, s)
+ v4.AddArg2(v5, v6)
+ v1.AddArg2(v2, v4)
+ v8 := b.NewValue0(v.Pos, OpLsh32x32, typ.UInt32)
+ v9 := b.NewValue0(v.Pos, OpSub32, typ.UInt32)
+ v9.AddArg2(s, v7)
+ v8.AddArg2(v5, v9)
+ v0.AddArg2(v1, v8)
+ v10 := b.NewValue0(v.Pos, OpLsh32x32, typ.UInt32)
+ v10.AddArg2(v5, s)
+ v.AddArg2(v0, v10)
+ return true
+ }
+}
+func rewriteValuedec64_OpLsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x64 _ (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Const64 [0])
+ for {
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh64x64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Lsh64x32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpLsh64x32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Lsh64x64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Lsh64x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpLsh64x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh64x64 x y)
+ // result: (Lsh64x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpLsh64x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpLsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x8 x s)
+ // result: (Int64Make (Or32 <typ.UInt32> (Or32 <typ.UInt32> (Lsh32x8 <typ.UInt32> (Int64Hi x) s) (Rsh32Ux8 <typ.UInt32> (Int64Lo x) (Sub8 <typ.UInt8> (Const8 <typ.UInt8> [32]) s))) (Lsh32x8 <typ.UInt32> (Int64Lo x) (Sub8 <typ.UInt8> s (Const8 <typ.UInt8> [32])))) (Lsh32x8 <typ.UInt32> (Int64Lo x) s))
+ for {
+ x := v_0
+ s := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpLsh32x8, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v3.AddArg(x)
+ v2.AddArg2(v3, s)
+ v4 := b.NewValue0(v.Pos, OpRsh32Ux8, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v6 := b.NewValue0(v.Pos, OpSub8, typ.UInt8)
+ v7 := b.NewValue0(v.Pos, OpConst8, typ.UInt8)
+ v7.AuxInt = int8ToAuxInt(32)
+ v6.AddArg2(v7, s)
+ v4.AddArg2(v5, v6)
+ v1.AddArg2(v2, v4)
+ v8 := b.NewValue0(v.Pos, OpLsh32x8, typ.UInt32)
+ v9 := b.NewValue0(v.Pos, OpSub8, typ.UInt8)
+ v9.AddArg2(s, v7)
+ v8.AddArg2(v5, v9)
+ v0.AddArg2(v1, v8)
+ v10 := b.NewValue0(v.Pos, OpLsh32x8, typ.UInt32)
+ v10.AddArg2(v5, s)
+ v.AddArg2(v0, v10)
+ return true
+ }
+}
+func rewriteValuedec64_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x64 _ (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh8x64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Lsh8x32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpLsh8x32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Lsh8x64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Lsh8x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpLsh8x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh8x64 x y)
+ // result: (Lsh8x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpLsh8x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpMul64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul64 x y)
+ // result: (Int64Make (Add32 <typ.UInt32> (Mul32 <typ.UInt32> (Int64Lo x) (Int64Hi y)) (Add32 <typ.UInt32> (Mul32 <typ.UInt32> (Int64Hi x) (Int64Lo y)) (Select0 <typ.UInt32> (Mul32uhilo (Int64Lo x) (Int64Lo y))))) (Select1 <typ.UInt32> (Mul32uhilo (Int64Lo x) (Int64Lo y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpAdd32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v2.AddArg(x)
+ v3 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v3.AddArg(y)
+ v1.AddArg2(v2, v3)
+ v4 := b.NewValue0(v.Pos, OpAdd32, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v6 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v6.AddArg(x)
+ v7 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v7.AddArg(y)
+ v5.AddArg2(v6, v7)
+ v8 := b.NewValue0(v.Pos, OpSelect0, typ.UInt32)
+ v9 := b.NewValue0(v.Pos, OpMul32uhilo, types.NewTuple(typ.UInt32, typ.UInt32))
+ v9.AddArg2(v2, v7)
+ v8.AddArg(v9)
+ v4.AddArg2(v5, v8)
+ v0.AddArg2(v1, v4)
+ v10 := b.NewValue0(v.Pos, OpSelect1, typ.UInt32)
+ v10.AddArg(v9)
+ v.AddArg2(v0, v10)
+ return true
+ }
+}
+func rewriteValuedec64_OpNeg64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neg64 <t> x)
+ // result: (Sub64 (Const64 <t> [0]) x)
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpSub64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValuedec64_OpNeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq64 x y)
+ // result: (OrB (Neq32 (Int64Hi x) (Int64Hi y)) (Neq32 (Int64Lo x) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpOrB)
+ v0 := b.NewValue0(v.Pos, OpNeq32, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpNeq32, typ.Bool)
+ v4 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v4.AddArg(x)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(y)
+ v3.AddArg2(v4, v5)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValuedec64_OpOr32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Or32 <typ.UInt32> (Zeromask (Const32 [c])) y)
+ // cond: c == 0
+ // result: y
+ for {
+ if v.Type != typ.UInt32 {
+ break
+ }
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpZeromask {
+ continue
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ y := v_1
+ if !(c == 0) {
+ continue
+ }
+ v.copyOf(y)
+ return true
+ }
+ break
+ }
+ // match: (Or32 <typ.UInt32> (Zeromask (Const32 [c])) y)
+ // cond: c != 0
+ // result: (Const32 <typ.UInt32> [-1])
+ for {
+ if v.Type != typ.UInt32 {
+ break
+ }
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpZeromask {
+ continue
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if !(c != 0) {
+ continue
+ }
+ v.reset(OpConst32)
+ v.Type = typ.UInt32
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuedec64_OpOr64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Or64 x y)
+ // result: (Int64Make (Or32 <typ.UInt32> (Int64Hi x) (Int64Hi y)) (Or32 <typ.UInt32> (Int64Lo x) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v4.AddArg(x)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(y)
+ v3.AddArg2(v4, v5)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux64 _ (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh16Ux64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Rsh16Ux32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpRsh16Ux32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Rsh16Ux64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Rsh16Ux32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpRsh16Ux32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16Ux64 x y)
+ // result: (Rsh16Ux32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRsh16Ux32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x64 x (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Signmask (SignExt16to32 x))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpSignmask)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh16x64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Rsh16x32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpRsh16x32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Rsh16x64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Rsh16x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpRsh16x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x64 x y)
+ // result: (Rsh16x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRsh16x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux64 _ (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh32Ux64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Rsh32Ux32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpRsh32Ux32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Rsh32Ux64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Rsh32Ux32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpRsh32Ux32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32Ux64 x y)
+ // result: (Rsh32Ux32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRsh32Ux32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x64 x (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Signmask x)
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpSignmask)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Rsh32x64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Rsh32x32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpRsh32x32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Rsh32x64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Rsh32x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpRsh32x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x64 x y)
+ // result: (Rsh32x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRsh32x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh64Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux16 x s)
+ // result: (Int64Make (Rsh32Ux16 <typ.UInt32> (Int64Hi x) s) (Or32 <typ.UInt32> (Or32 <typ.UInt32> (Rsh32Ux16 <typ.UInt32> (Int64Lo x) s) (Lsh32x16 <typ.UInt32> (Int64Hi x) (Sub16 <typ.UInt16> (Const16 <typ.UInt16> [32]) s))) (Rsh32Ux16 <typ.UInt32> (Int64Hi x) (Sub16 <typ.UInt16> s (Const16 <typ.UInt16> [32])))))
+ for {
+ x := v_0
+ s := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpRsh32Ux16, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, s)
+ v2 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpRsh32Ux16, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v4.AddArg2(v5, s)
+ v6 := b.NewValue0(v.Pos, OpLsh32x16, typ.UInt32)
+ v7 := b.NewValue0(v.Pos, OpSub16, typ.UInt16)
+ v8 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v8.AuxInt = int16ToAuxInt(32)
+ v7.AddArg2(v8, s)
+ v6.AddArg2(v1, v7)
+ v3.AddArg2(v4, v6)
+ v9 := b.NewValue0(v.Pos, OpRsh32Ux16, typ.UInt32)
+ v10 := b.NewValue0(v.Pos, OpSub16, typ.UInt16)
+ v10.AddArg2(s, v8)
+ v9.AddArg2(v1, v10)
+ v2.AddArg2(v3, v9)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh64Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux32 x s)
+ // result: (Int64Make (Rsh32Ux32 <typ.UInt32> (Int64Hi x) s) (Or32 <typ.UInt32> (Or32 <typ.UInt32> (Rsh32Ux32 <typ.UInt32> (Int64Lo x) s) (Lsh32x32 <typ.UInt32> (Int64Hi x) (Sub32 <typ.UInt32> (Const32 <typ.UInt32> [32]) s))) (Rsh32Ux32 <typ.UInt32> (Int64Hi x) (Sub32 <typ.UInt32> s (Const32 <typ.UInt32> [32])))))
+ for {
+ x := v_0
+ s := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpRsh32Ux32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, s)
+ v2 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpRsh32Ux32, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v4.AddArg2(v5, s)
+ v6 := b.NewValue0(v.Pos, OpLsh32x32, typ.UInt32)
+ v7 := b.NewValue0(v.Pos, OpSub32, typ.UInt32)
+ v8 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v8.AuxInt = int32ToAuxInt(32)
+ v7.AddArg2(v8, s)
+ v6.AddArg2(v1, v7)
+ v3.AddArg2(v4, v6)
+ v9 := b.NewValue0(v.Pos, OpRsh32Ux32, typ.UInt32)
+ v10 := b.NewValue0(v.Pos, OpSub32, typ.UInt32)
+ v10.AddArg2(s, v8)
+ v9.AddArg2(v1, v10)
+ v2.AddArg2(v3, v9)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh64Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux64 _ (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Const64 [0])
+ for {
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh64Ux64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Rsh64Ux32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpRsh64Ux32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Rsh64Ux64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Rsh64Ux32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpRsh64Ux32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux64 x y)
+ // result: (Rsh64Ux32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64Ux32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh64Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux8 x s)
+ // result: (Int64Make (Rsh32Ux8 <typ.UInt32> (Int64Hi x) s) (Or32 <typ.UInt32> (Or32 <typ.UInt32> (Rsh32Ux8 <typ.UInt32> (Int64Lo x) s) (Lsh32x8 <typ.UInt32> (Int64Hi x) (Sub8 <typ.UInt8> (Const8 <typ.UInt8> [32]) s))) (Rsh32Ux8 <typ.UInt32> (Int64Hi x) (Sub8 <typ.UInt8> s (Const8 <typ.UInt8> [32])))))
+ for {
+ x := v_0
+ s := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpRsh32Ux8, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, s)
+ v2 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpRsh32Ux8, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v4.AddArg2(v5, s)
+ v6 := b.NewValue0(v.Pos, OpLsh32x8, typ.UInt32)
+ v7 := b.NewValue0(v.Pos, OpSub8, typ.UInt8)
+ v8 := b.NewValue0(v.Pos, OpConst8, typ.UInt8)
+ v8.AuxInt = int8ToAuxInt(32)
+ v7.AddArg2(v8, s)
+ v6.AddArg2(v1, v7)
+ v3.AddArg2(v4, v6)
+ v9 := b.NewValue0(v.Pos, OpRsh32Ux8, typ.UInt32)
+ v10 := b.NewValue0(v.Pos, OpSub8, typ.UInt8)
+ v10.AddArg2(s, v8)
+ v9.AddArg2(v1, v10)
+ v2.AddArg2(v3, v9)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x16 x s)
+ // result: (Int64Make (Rsh32x16 <typ.UInt32> (Int64Hi x) s) (Or32 <typ.UInt32> (Or32 <typ.UInt32> (Rsh32Ux16 <typ.UInt32> (Int64Lo x) s) (Lsh32x16 <typ.UInt32> (Int64Hi x) (Sub16 <typ.UInt16> (Const16 <typ.UInt16> [32]) s))) (And32 <typ.UInt32> (Rsh32x16 <typ.UInt32> (Int64Hi x) (Sub16 <typ.UInt16> s (Const16 <typ.UInt16> [32]))) (Zeromask (ZeroExt16to32 (Rsh16Ux32 <typ.UInt16> s (Const32 <typ.UInt32> [5])))))))
+ for {
+ x := v_0
+ s := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpRsh32x16, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, s)
+ v2 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpRsh32Ux16, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v4.AddArg2(v5, s)
+ v6 := b.NewValue0(v.Pos, OpLsh32x16, typ.UInt32)
+ v7 := b.NewValue0(v.Pos, OpSub16, typ.UInt16)
+ v8 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v8.AuxInt = int16ToAuxInt(32)
+ v7.AddArg2(v8, s)
+ v6.AddArg2(v1, v7)
+ v3.AddArg2(v4, v6)
+ v9 := b.NewValue0(v.Pos, OpAnd32, typ.UInt32)
+ v10 := b.NewValue0(v.Pos, OpRsh32x16, typ.UInt32)
+ v11 := b.NewValue0(v.Pos, OpSub16, typ.UInt16)
+ v11.AddArg2(s, v8)
+ v10.AddArg2(v1, v11)
+ v12 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v13 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v14 := b.NewValue0(v.Pos, OpRsh16Ux32, typ.UInt16)
+ v15 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v15.AuxInt = int32ToAuxInt(5)
+ v14.AddArg2(s, v15)
+ v13.AddArg(v14)
+ v12.AddArg(v13)
+ v9.AddArg2(v10, v12)
+ v2.AddArg2(v3, v9)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x32 x s)
+ // result: (Int64Make (Rsh32x32 <typ.UInt32> (Int64Hi x) s) (Or32 <typ.UInt32> (Or32 <typ.UInt32> (Rsh32Ux32 <typ.UInt32> (Int64Lo x) s) (Lsh32x32 <typ.UInt32> (Int64Hi x) (Sub32 <typ.UInt32> (Const32 <typ.UInt32> [32]) s))) (And32 <typ.UInt32> (Rsh32x32 <typ.UInt32> (Int64Hi x) (Sub32 <typ.UInt32> s (Const32 <typ.UInt32> [32]))) (Zeromask (Rsh32Ux32 <typ.UInt32> s (Const32 <typ.UInt32> [5]))))))
+ for {
+ x := v_0
+ s := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpRsh32x32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, s)
+ v2 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpRsh32Ux32, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v4.AddArg2(v5, s)
+ v6 := b.NewValue0(v.Pos, OpLsh32x32, typ.UInt32)
+ v7 := b.NewValue0(v.Pos, OpSub32, typ.UInt32)
+ v8 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v8.AuxInt = int32ToAuxInt(32)
+ v7.AddArg2(v8, s)
+ v6.AddArg2(v1, v7)
+ v3.AddArg2(v4, v6)
+ v9 := b.NewValue0(v.Pos, OpAnd32, typ.UInt32)
+ v10 := b.NewValue0(v.Pos, OpRsh32x32, typ.UInt32)
+ v11 := b.NewValue0(v.Pos, OpSub32, typ.UInt32)
+ v11.AddArg2(s, v8)
+ v10.AddArg2(v1, v11)
+ v12 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v13 := b.NewValue0(v.Pos, OpRsh32Ux32, typ.UInt32)
+ v14 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v14.AuxInt = int32ToAuxInt(5)
+ v13.AddArg2(s, v14)
+ v12.AddArg(v13)
+ v9.AddArg2(v10, v12)
+ v2.AddArg2(v3, v9)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x64 x (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Int64Make (Signmask (Int64Hi x)) (Signmask (Int64Hi x)))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpSignmask, typ.Int32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg2(v0, v0)
+ return true
+ }
+ // match: (Rsh64x64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Rsh64x32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpRsh64x32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Rsh64x64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Rsh64x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpRsh64x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x64 x y)
+ // result: (Rsh64x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRsh64x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x8 x s)
+ // result: (Int64Make (Rsh32x8 <typ.UInt32> (Int64Hi x) s) (Or32 <typ.UInt32> (Or32 <typ.UInt32> (Rsh32Ux8 <typ.UInt32> (Int64Lo x) s) (Lsh32x8 <typ.UInt32> (Int64Hi x) (Sub8 <typ.UInt8> (Const8 <typ.UInt8> [32]) s))) (And32 <typ.UInt32> (Rsh32x8 <typ.UInt32> (Int64Hi x) (Sub8 <typ.UInt8> s (Const8 <typ.UInt8> [32]))) (Zeromask (ZeroExt8to32 (Rsh8Ux32 <typ.UInt8> s (Const32 <typ.UInt32> [5])))))))
+ for {
+ x := v_0
+ s := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpRsh32x8, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v0.AddArg2(v1, s)
+ v2 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpRsh32Ux8, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v4.AddArg2(v5, s)
+ v6 := b.NewValue0(v.Pos, OpLsh32x8, typ.UInt32)
+ v7 := b.NewValue0(v.Pos, OpSub8, typ.UInt8)
+ v8 := b.NewValue0(v.Pos, OpConst8, typ.UInt8)
+ v8.AuxInt = int8ToAuxInt(32)
+ v7.AddArg2(v8, s)
+ v6.AddArg2(v1, v7)
+ v3.AddArg2(v4, v6)
+ v9 := b.NewValue0(v.Pos, OpAnd32, typ.UInt32)
+ v10 := b.NewValue0(v.Pos, OpRsh32x8, typ.UInt32)
+ v11 := b.NewValue0(v.Pos, OpSub8, typ.UInt8)
+ v11.AddArg2(s, v8)
+ v10.AddArg2(v1, v11)
+ v12 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v13 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v14 := b.NewValue0(v.Pos, OpRsh8Ux32, typ.UInt8)
+ v15 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v15.AuxInt = int32ToAuxInt(5)
+ v14.AddArg2(s, v15)
+ v13.AddArg(v14)
+ v12.AddArg(v13)
+ v9.AddArg2(v10, v12)
+ v2.AddArg2(v3, v9)
+ v.AddArg2(v0, v2)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux64 _ (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh8Ux64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Rsh8Ux32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpRsh8Ux32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Rsh8Ux64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Rsh8Ux32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpRsh8Ux32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8Ux64 x y)
+ // result: (Rsh8Ux32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRsh8Ux32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8x64 x (Int64Make (Const32 [c]) _))
+ // cond: c != 0
+ // result: (Signmask (SignExt8to32 x))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpSignmask)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh8x64 [c] x (Int64Make (Const32 [0]) lo))
+ // result: (Rsh8x32 [c] x lo)
+ for {
+ c := auxIntToBool(v.AuxInt)
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || auxIntToInt32(v_1_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpRsh8x32)
+ v.AuxInt = boolToAuxInt(c)
+ v.AddArg2(x, lo)
+ return true
+ }
+ // match: (Rsh8x64 x (Int64Make hi lo))
+ // cond: hi.Op != OpConst32
+ // result: (Rsh8x32 x (Or32 <typ.UInt32> (Zeromask hi) lo))
+ for {
+ x := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ if !(hi.Op != OpConst32) {
+ break
+ }
+ v.reset(OpRsh8x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v1.AddArg(hi)
+ v0.AddArg2(v1, lo)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x64 x y)
+ // result: (Rsh8x32 x (Or32 <typ.UInt32> (Zeromask (Int64Hi y)) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpRsh8x32)
+ v0 := b.NewValue0(v.Pos, OpOr32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeromask, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v1.AddArg(v2)
+ v3 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v3.AddArg(y)
+ v0.AddArg2(v1, v3)
+ v.AddArg2(x, v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpSignExt16to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SignExt16to64 x)
+ // result: (SignExt32to64 (SignExt16to32 x))
+ for {
+ x := v_0
+ v.reset(OpSignExt32to64)
+ v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpSignExt32to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SignExt32to64 x)
+ // result: (Int64Make (Signmask x) x)
+ for {
+ x := v_0
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpSignmask, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValuedec64_OpSignExt8to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SignExt8to64 x)
+ // result: (SignExt32to64 (SignExt8to32 x))
+ for {
+ x := v_0
+ v.reset(OpSignExt32to64)
+ v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (Store {t} dst (Int64Make hi lo) mem)
+ // cond: t.Size() == 8 && !config.BigEndian
+ // result: (Store {hi.Type} (OffPtr <hi.Type.PtrTo()> [4] dst) hi (Store {lo.Type} dst lo mem))
+ for {
+ t := auxToType(v.Aux)
+ dst := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ mem := v_2
+ if !(t.Size() == 8 && !config.BigEndian) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(hi.Type)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, hi.Type.PtrTo())
+ v0.AuxInt = int64ToAuxInt(4)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(lo.Type)
+ v1.AddArg3(dst, lo, mem)
+ v.AddArg3(v0, hi, v1)
+ return true
+ }
+ // match: (Store {t} dst (Int64Make hi lo) mem)
+ // cond: t.Size() == 8 && config.BigEndian
+ // result: (Store {lo.Type} (OffPtr <lo.Type.PtrTo()> [4] dst) lo (Store {hi.Type} dst hi mem))
+ for {
+ t := auxToType(v.Aux)
+ dst := v_0
+ if v_1.Op != OpInt64Make {
+ break
+ }
+ lo := v_1.Args[1]
+ hi := v_1.Args[0]
+ mem := v_2
+ if !(t.Size() == 8 && config.BigEndian) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(lo.Type)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, lo.Type.PtrTo())
+ v0.AuxInt = int64ToAuxInt(4)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(hi.Type)
+ v1.AddArg3(dst, hi, mem)
+ v.AddArg3(v0, lo, v1)
+ return true
+ }
+ return false
+}
+func rewriteValuedec64_OpSub64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Sub64 x y)
+ // result: (Int64Make (Sub32withcarry <typ.Int32> (Int64Hi x) (Int64Hi y) (Select1 <types.TypeFlags> (Sub32carry (Int64Lo x) (Int64Lo y)))) (Select0 <typ.UInt32> (Sub32carry (Int64Lo x) (Int64Lo y))))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpSub32withcarry, typ.Int32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v3 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
+ v4 := b.NewValue0(v.Pos, OpSub32carry, types.NewTuple(typ.UInt32, types.TypeFlags))
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(x)
+ v6 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v6.AddArg(y)
+ v4.AddArg2(v5, v6)
+ v3.AddArg(v4)
+ v0.AddArg3(v1, v2, v3)
+ v7 := b.NewValue0(v.Pos, OpSelect0, typ.UInt32)
+ v7.AddArg(v4)
+ v.AddArg2(v0, v7)
+ return true
+ }
+}
+func rewriteValuedec64_OpTrunc64to16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Trunc64to16 (Int64Make _ lo))
+ // result: (Trunc32to16 lo)
+ for {
+ if v_0.Op != OpInt64Make {
+ break
+ }
+ lo := v_0.Args[1]
+ v.reset(OpTrunc32to16)
+ v.AddArg(lo)
+ return true
+ }
+ // match: (Trunc64to16 x)
+ // result: (Trunc32to16 (Int64Lo x))
+ for {
+ x := v_0
+ v.reset(OpTrunc32to16)
+ v0 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpTrunc64to32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc64to32 (Int64Make _ lo))
+ // result: lo
+ for {
+ if v_0.Op != OpInt64Make {
+ break
+ }
+ lo := v_0.Args[1]
+ v.copyOf(lo)
+ return true
+ }
+ // match: (Trunc64to32 x)
+ // result: (Int64Lo x)
+ for {
+ x := v_0
+ v.reset(OpInt64Lo)
+ v.AddArg(x)
+ return true
+ }
+}
+func rewriteValuedec64_OpTrunc64to8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Trunc64to8 (Int64Make _ lo))
+ // result: (Trunc32to8 lo)
+ for {
+ if v_0.Op != OpInt64Make {
+ break
+ }
+ lo := v_0.Args[1]
+ v.reset(OpTrunc32to8)
+ v.AddArg(lo)
+ return true
+ }
+ // match: (Trunc64to8 x)
+ // result: (Trunc32to8 (Int64Lo x))
+ for {
+ x := v_0
+ v.reset(OpTrunc32to8)
+ v0 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpXor64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Xor64 x y)
+ // result: (Int64Make (Xor32 <typ.UInt32> (Int64Hi x) (Int64Hi y)) (Xor32 <typ.UInt32> (Int64Lo x) (Int64Lo y)))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpXor32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpInt64Hi, typ.UInt32)
+ v2.AddArg(y)
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpXor32, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v4.AddArg(x)
+ v5 := b.NewValue0(v.Pos, OpInt64Lo, typ.UInt32)
+ v5.AddArg(y)
+ v3.AddArg2(v4, v5)
+ v.AddArg2(v0, v3)
+ return true
+ }
+}
+func rewriteValuedec64_OpZeroExt16to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ZeroExt16to64 x)
+ // result: (ZeroExt32to64 (ZeroExt16to32 x))
+ for {
+ x := v_0
+ v.reset(OpZeroExt32to64)
+ v0 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValuedec64_OpZeroExt32to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ZeroExt32to64 x)
+ // result: (Int64Make (Const32 <typ.UInt32> [0]) x)
+ for {
+ x := v_0
+ v.reset(OpInt64Make)
+ v0 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v0.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, x)
+ return true
+ }
+}
+func rewriteValuedec64_OpZeroExt8to64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ZeroExt8to64 x)
+ // result: (ZeroExt32to64 (ZeroExt8to32 x))
+ for {
+ x := v_0
+ v.reset(OpZeroExt32to64)
+ v0 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteBlockdec64(b *Block) bool {
+ switch b.Kind {
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewritedecArgs.go b/src/cmd/compile/internal/ssa/rewritedecArgs.go
new file mode 100644
index 0000000..23ff417
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewritedecArgs.go
@@ -0,0 +1,247 @@
+// Code generated from gen/decArgs.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+func rewriteValuedecArgs(v *Value) bool {
+ switch v.Op {
+ case OpArg:
+ return rewriteValuedecArgs_OpArg(v)
+ }
+ return false
+}
+func rewriteValuedecArgs_OpArg(v *Value) bool {
+ b := v.Block
+ config := b.Func.Config
+ fe := b.Func.fe
+ typ := &b.Func.Config.Types
+ // match: (Arg {n} [off])
+ // cond: v.Type.IsString()
+ // result: (StringMake (Arg <typ.BytePtr> {n} [off]) (Arg <typ.Int> {n} [off+int32(config.PtrSize)]))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(v.Type.IsString()) {
+ break
+ }
+ v.reset(OpStringMake)
+ v0 := b.NewValue0(v.Pos, OpArg, typ.BytePtr)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, typ.Int)
+ v1.AuxInt = int32ToAuxInt(off + int32(config.PtrSize))
+ v1.Aux = symToAux(n)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Arg {n} [off])
+ // cond: v.Type.IsSlice()
+ // result: (SliceMake (Arg <v.Type.Elem().PtrTo()> {n} [off]) (Arg <typ.Int> {n} [off+int32(config.PtrSize)]) (Arg <typ.Int> {n} [off+2*int32(config.PtrSize)]))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(v.Type.IsSlice()) {
+ break
+ }
+ v.reset(OpSliceMake)
+ v0 := b.NewValue0(v.Pos, OpArg, v.Type.Elem().PtrTo())
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, typ.Int)
+ v1.AuxInt = int32ToAuxInt(off + int32(config.PtrSize))
+ v1.Aux = symToAux(n)
+ v2 := b.NewValue0(v.Pos, OpArg, typ.Int)
+ v2.AuxInt = int32ToAuxInt(off + 2*int32(config.PtrSize))
+ v2.Aux = symToAux(n)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Arg {n} [off])
+ // cond: v.Type.IsInterface()
+ // result: (IMake (Arg <typ.Uintptr> {n} [off]) (Arg <typ.BytePtr> {n} [off+int32(config.PtrSize)]))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(v.Type.IsInterface()) {
+ break
+ }
+ v.reset(OpIMake)
+ v0 := b.NewValue0(v.Pos, OpArg, typ.Uintptr)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, typ.BytePtr)
+ v1.AuxInt = int32ToAuxInt(off + int32(config.PtrSize))
+ v1.Aux = symToAux(n)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Arg {n} [off])
+ // cond: v.Type.IsComplex() && v.Type.Size() == 16
+ // result: (ComplexMake (Arg <typ.Float64> {n} [off]) (Arg <typ.Float64> {n} [off+8]))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(v.Type.IsComplex() && v.Type.Size() == 16) {
+ break
+ }
+ v.reset(OpComplexMake)
+ v0 := b.NewValue0(v.Pos, OpArg, typ.Float64)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, typ.Float64)
+ v1.AuxInt = int32ToAuxInt(off + 8)
+ v1.Aux = symToAux(n)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Arg {n} [off])
+ // cond: v.Type.IsComplex() && v.Type.Size() == 8
+ // result: (ComplexMake (Arg <typ.Float32> {n} [off]) (Arg <typ.Float32> {n} [off+4]))
+ for {
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(v.Type.IsComplex() && v.Type.Size() == 8) {
+ break
+ }
+ v.reset(OpComplexMake)
+ v0 := b.NewValue0(v.Pos, OpArg, typ.Float32)
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, typ.Float32)
+ v1.AuxInt = int32ToAuxInt(off + 4)
+ v1.Aux = symToAux(n)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Arg <t>)
+ // cond: t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t)
+ // result: (StructMake0)
+ for {
+ t := v.Type
+ if !(t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpStructMake0)
+ return true
+ }
+ // match: (Arg <t> {n} [off])
+ // cond: t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t)
+ // result: (StructMake1 (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))]))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpStructMake1)
+ v0 := b.NewValue0(v.Pos, OpArg, t.FieldType(0))
+ v0.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(0)))
+ v0.Aux = symToAux(n)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Arg <t> {n} [off])
+ // cond: t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t)
+ // result: (StructMake2 (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))]) (Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))]))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpStructMake2)
+ v0 := b.NewValue0(v.Pos, OpArg, t.FieldType(0))
+ v0.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(0)))
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, t.FieldType(1))
+ v1.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(1)))
+ v1.Aux = symToAux(n)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (Arg <t> {n} [off])
+ // cond: t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t)
+ // result: (StructMake3 (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))]) (Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))]) (Arg <t.FieldType(2)> {n} [off+int32(t.FieldOff(2))]))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpStructMake3)
+ v0 := b.NewValue0(v.Pos, OpArg, t.FieldType(0))
+ v0.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(0)))
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, t.FieldType(1))
+ v1.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(1)))
+ v1.Aux = symToAux(n)
+ v2 := b.NewValue0(v.Pos, OpArg, t.FieldType(2))
+ v2.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(2)))
+ v2.Aux = symToAux(n)
+ v.AddArg3(v0, v1, v2)
+ return true
+ }
+ // match: (Arg <t> {n} [off])
+ // cond: t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t)
+ // result: (StructMake4 (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))]) (Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))]) (Arg <t.FieldType(2)> {n} [off+int32(t.FieldOff(2))]) (Arg <t.FieldType(3)> {n} [off+int32(t.FieldOff(3))]))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpStructMake4)
+ v0 := b.NewValue0(v.Pos, OpArg, t.FieldType(0))
+ v0.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(0)))
+ v0.Aux = symToAux(n)
+ v1 := b.NewValue0(v.Pos, OpArg, t.FieldType(1))
+ v1.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(1)))
+ v1.Aux = symToAux(n)
+ v2 := b.NewValue0(v.Pos, OpArg, t.FieldType(2))
+ v2.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(2)))
+ v2.Aux = symToAux(n)
+ v3 := b.NewValue0(v.Pos, OpArg, t.FieldType(3))
+ v3.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(3)))
+ v3.Aux = symToAux(n)
+ v.AddArg4(v0, v1, v2, v3)
+ return true
+ }
+ // match: (Arg <t>)
+ // cond: t.IsArray() && t.NumElem() == 0
+ // result: (ArrayMake0)
+ for {
+ t := v.Type
+ if !(t.IsArray() && t.NumElem() == 0) {
+ break
+ }
+ v.reset(OpArrayMake0)
+ return true
+ }
+ // match: (Arg <t> {n} [off])
+ // cond: t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t)
+ // result: (ArrayMake1 (Arg <t.Elem()> {n} [off]))
+ for {
+ t := v.Type
+ off := auxIntToInt32(v.AuxInt)
+ n := auxToSym(v.Aux)
+ if !(t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpArrayMake1)
+ v0 := b.NewValue0(v.Pos, OpArg, t.Elem())
+ v0.AuxInt = int32ToAuxInt(off)
+ v0.Aux = symToAux(n)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteBlockdecArgs(b *Block) bool {
+ switch b.Kind {
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go
new file mode 100644
index 0000000..958e24d
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go
@@ -0,0 +1,25091 @@
+// Code generated from gen/generic.rules; DO NOT EDIT.
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "math"
+import "cmd/compile/internal/types"
+
+func rewriteValuegeneric(v *Value) bool {
+ switch v.Op {
+ case OpAdd16:
+ return rewriteValuegeneric_OpAdd16(v)
+ case OpAdd32:
+ return rewriteValuegeneric_OpAdd32(v)
+ case OpAdd32F:
+ return rewriteValuegeneric_OpAdd32F(v)
+ case OpAdd64:
+ return rewriteValuegeneric_OpAdd64(v)
+ case OpAdd64F:
+ return rewriteValuegeneric_OpAdd64F(v)
+ case OpAdd8:
+ return rewriteValuegeneric_OpAdd8(v)
+ case OpAddPtr:
+ return rewriteValuegeneric_OpAddPtr(v)
+ case OpAnd16:
+ return rewriteValuegeneric_OpAnd16(v)
+ case OpAnd32:
+ return rewriteValuegeneric_OpAnd32(v)
+ case OpAnd64:
+ return rewriteValuegeneric_OpAnd64(v)
+ case OpAnd8:
+ return rewriteValuegeneric_OpAnd8(v)
+ case OpAndB:
+ return rewriteValuegeneric_OpAndB(v)
+ case OpArraySelect:
+ return rewriteValuegeneric_OpArraySelect(v)
+ case OpCom16:
+ return rewriteValuegeneric_OpCom16(v)
+ case OpCom32:
+ return rewriteValuegeneric_OpCom32(v)
+ case OpCom64:
+ return rewriteValuegeneric_OpCom64(v)
+ case OpCom8:
+ return rewriteValuegeneric_OpCom8(v)
+ case OpConstInterface:
+ return rewriteValuegeneric_OpConstInterface(v)
+ case OpConstSlice:
+ return rewriteValuegeneric_OpConstSlice(v)
+ case OpConstString:
+ return rewriteValuegeneric_OpConstString(v)
+ case OpConvert:
+ return rewriteValuegeneric_OpConvert(v)
+ case OpCtz16:
+ return rewriteValuegeneric_OpCtz16(v)
+ case OpCtz32:
+ return rewriteValuegeneric_OpCtz32(v)
+ case OpCtz64:
+ return rewriteValuegeneric_OpCtz64(v)
+ case OpCtz8:
+ return rewriteValuegeneric_OpCtz8(v)
+ case OpCvt32Fto32:
+ return rewriteValuegeneric_OpCvt32Fto32(v)
+ case OpCvt32Fto64:
+ return rewriteValuegeneric_OpCvt32Fto64(v)
+ case OpCvt32Fto64F:
+ return rewriteValuegeneric_OpCvt32Fto64F(v)
+ case OpCvt32to32F:
+ return rewriteValuegeneric_OpCvt32to32F(v)
+ case OpCvt32to64F:
+ return rewriteValuegeneric_OpCvt32to64F(v)
+ case OpCvt64Fto32:
+ return rewriteValuegeneric_OpCvt64Fto32(v)
+ case OpCvt64Fto32F:
+ return rewriteValuegeneric_OpCvt64Fto32F(v)
+ case OpCvt64Fto64:
+ return rewriteValuegeneric_OpCvt64Fto64(v)
+ case OpCvt64to32F:
+ return rewriteValuegeneric_OpCvt64to32F(v)
+ case OpCvt64to64F:
+ return rewriteValuegeneric_OpCvt64to64F(v)
+ case OpCvtBoolToUint8:
+ return rewriteValuegeneric_OpCvtBoolToUint8(v)
+ case OpDiv16:
+ return rewriteValuegeneric_OpDiv16(v)
+ case OpDiv16u:
+ return rewriteValuegeneric_OpDiv16u(v)
+ case OpDiv32:
+ return rewriteValuegeneric_OpDiv32(v)
+ case OpDiv32F:
+ return rewriteValuegeneric_OpDiv32F(v)
+ case OpDiv32u:
+ return rewriteValuegeneric_OpDiv32u(v)
+ case OpDiv64:
+ return rewriteValuegeneric_OpDiv64(v)
+ case OpDiv64F:
+ return rewriteValuegeneric_OpDiv64F(v)
+ case OpDiv64u:
+ return rewriteValuegeneric_OpDiv64u(v)
+ case OpDiv8:
+ return rewriteValuegeneric_OpDiv8(v)
+ case OpDiv8u:
+ return rewriteValuegeneric_OpDiv8u(v)
+ case OpEq16:
+ return rewriteValuegeneric_OpEq16(v)
+ case OpEq32:
+ return rewriteValuegeneric_OpEq32(v)
+ case OpEq32F:
+ return rewriteValuegeneric_OpEq32F(v)
+ case OpEq64:
+ return rewriteValuegeneric_OpEq64(v)
+ case OpEq64F:
+ return rewriteValuegeneric_OpEq64F(v)
+ case OpEq8:
+ return rewriteValuegeneric_OpEq8(v)
+ case OpEqB:
+ return rewriteValuegeneric_OpEqB(v)
+ case OpEqInter:
+ return rewriteValuegeneric_OpEqInter(v)
+ case OpEqPtr:
+ return rewriteValuegeneric_OpEqPtr(v)
+ case OpEqSlice:
+ return rewriteValuegeneric_OpEqSlice(v)
+ case OpIMake:
+ return rewriteValuegeneric_OpIMake(v)
+ case OpInterCall:
+ return rewriteValuegeneric_OpInterCall(v)
+ case OpInterLECall:
+ return rewriteValuegeneric_OpInterLECall(v)
+ case OpIsInBounds:
+ return rewriteValuegeneric_OpIsInBounds(v)
+ case OpIsNonNil:
+ return rewriteValuegeneric_OpIsNonNil(v)
+ case OpIsSliceInBounds:
+ return rewriteValuegeneric_OpIsSliceInBounds(v)
+ case OpLeq16:
+ return rewriteValuegeneric_OpLeq16(v)
+ case OpLeq16U:
+ return rewriteValuegeneric_OpLeq16U(v)
+ case OpLeq32:
+ return rewriteValuegeneric_OpLeq32(v)
+ case OpLeq32F:
+ return rewriteValuegeneric_OpLeq32F(v)
+ case OpLeq32U:
+ return rewriteValuegeneric_OpLeq32U(v)
+ case OpLeq64:
+ return rewriteValuegeneric_OpLeq64(v)
+ case OpLeq64F:
+ return rewriteValuegeneric_OpLeq64F(v)
+ case OpLeq64U:
+ return rewriteValuegeneric_OpLeq64U(v)
+ case OpLeq8:
+ return rewriteValuegeneric_OpLeq8(v)
+ case OpLeq8U:
+ return rewriteValuegeneric_OpLeq8U(v)
+ case OpLess16:
+ return rewriteValuegeneric_OpLess16(v)
+ case OpLess16U:
+ return rewriteValuegeneric_OpLess16U(v)
+ case OpLess32:
+ return rewriteValuegeneric_OpLess32(v)
+ case OpLess32F:
+ return rewriteValuegeneric_OpLess32F(v)
+ case OpLess32U:
+ return rewriteValuegeneric_OpLess32U(v)
+ case OpLess64:
+ return rewriteValuegeneric_OpLess64(v)
+ case OpLess64F:
+ return rewriteValuegeneric_OpLess64F(v)
+ case OpLess64U:
+ return rewriteValuegeneric_OpLess64U(v)
+ case OpLess8:
+ return rewriteValuegeneric_OpLess8(v)
+ case OpLess8U:
+ return rewriteValuegeneric_OpLess8U(v)
+ case OpLoad:
+ return rewriteValuegeneric_OpLoad(v)
+ case OpLsh16x16:
+ return rewriteValuegeneric_OpLsh16x16(v)
+ case OpLsh16x32:
+ return rewriteValuegeneric_OpLsh16x32(v)
+ case OpLsh16x64:
+ return rewriteValuegeneric_OpLsh16x64(v)
+ case OpLsh16x8:
+ return rewriteValuegeneric_OpLsh16x8(v)
+ case OpLsh32x16:
+ return rewriteValuegeneric_OpLsh32x16(v)
+ case OpLsh32x32:
+ return rewriteValuegeneric_OpLsh32x32(v)
+ case OpLsh32x64:
+ return rewriteValuegeneric_OpLsh32x64(v)
+ case OpLsh32x8:
+ return rewriteValuegeneric_OpLsh32x8(v)
+ case OpLsh64x16:
+ return rewriteValuegeneric_OpLsh64x16(v)
+ case OpLsh64x32:
+ return rewriteValuegeneric_OpLsh64x32(v)
+ case OpLsh64x64:
+ return rewriteValuegeneric_OpLsh64x64(v)
+ case OpLsh64x8:
+ return rewriteValuegeneric_OpLsh64x8(v)
+ case OpLsh8x16:
+ return rewriteValuegeneric_OpLsh8x16(v)
+ case OpLsh8x32:
+ return rewriteValuegeneric_OpLsh8x32(v)
+ case OpLsh8x64:
+ return rewriteValuegeneric_OpLsh8x64(v)
+ case OpLsh8x8:
+ return rewriteValuegeneric_OpLsh8x8(v)
+ case OpMod16:
+ return rewriteValuegeneric_OpMod16(v)
+ case OpMod16u:
+ return rewriteValuegeneric_OpMod16u(v)
+ case OpMod32:
+ return rewriteValuegeneric_OpMod32(v)
+ case OpMod32u:
+ return rewriteValuegeneric_OpMod32u(v)
+ case OpMod64:
+ return rewriteValuegeneric_OpMod64(v)
+ case OpMod64u:
+ return rewriteValuegeneric_OpMod64u(v)
+ case OpMod8:
+ return rewriteValuegeneric_OpMod8(v)
+ case OpMod8u:
+ return rewriteValuegeneric_OpMod8u(v)
+ case OpMove:
+ return rewriteValuegeneric_OpMove(v)
+ case OpMul16:
+ return rewriteValuegeneric_OpMul16(v)
+ case OpMul32:
+ return rewriteValuegeneric_OpMul32(v)
+ case OpMul32F:
+ return rewriteValuegeneric_OpMul32F(v)
+ case OpMul64:
+ return rewriteValuegeneric_OpMul64(v)
+ case OpMul64F:
+ return rewriteValuegeneric_OpMul64F(v)
+ case OpMul8:
+ return rewriteValuegeneric_OpMul8(v)
+ case OpNeg16:
+ return rewriteValuegeneric_OpNeg16(v)
+ case OpNeg32:
+ return rewriteValuegeneric_OpNeg32(v)
+ case OpNeg32F:
+ return rewriteValuegeneric_OpNeg32F(v)
+ case OpNeg64:
+ return rewriteValuegeneric_OpNeg64(v)
+ case OpNeg64F:
+ return rewriteValuegeneric_OpNeg64F(v)
+ case OpNeg8:
+ return rewriteValuegeneric_OpNeg8(v)
+ case OpNeq16:
+ return rewriteValuegeneric_OpNeq16(v)
+ case OpNeq32:
+ return rewriteValuegeneric_OpNeq32(v)
+ case OpNeq32F:
+ return rewriteValuegeneric_OpNeq32F(v)
+ case OpNeq64:
+ return rewriteValuegeneric_OpNeq64(v)
+ case OpNeq64F:
+ return rewriteValuegeneric_OpNeq64F(v)
+ case OpNeq8:
+ return rewriteValuegeneric_OpNeq8(v)
+ case OpNeqB:
+ return rewriteValuegeneric_OpNeqB(v)
+ case OpNeqInter:
+ return rewriteValuegeneric_OpNeqInter(v)
+ case OpNeqPtr:
+ return rewriteValuegeneric_OpNeqPtr(v)
+ case OpNeqSlice:
+ return rewriteValuegeneric_OpNeqSlice(v)
+ case OpNilCheck:
+ return rewriteValuegeneric_OpNilCheck(v)
+ case OpNot:
+ return rewriteValuegeneric_OpNot(v)
+ case OpOffPtr:
+ return rewriteValuegeneric_OpOffPtr(v)
+ case OpOr16:
+ return rewriteValuegeneric_OpOr16(v)
+ case OpOr32:
+ return rewriteValuegeneric_OpOr32(v)
+ case OpOr64:
+ return rewriteValuegeneric_OpOr64(v)
+ case OpOr8:
+ return rewriteValuegeneric_OpOr8(v)
+ case OpOrB:
+ return rewriteValuegeneric_OpOrB(v)
+ case OpPhi:
+ return rewriteValuegeneric_OpPhi(v)
+ case OpPtrIndex:
+ return rewriteValuegeneric_OpPtrIndex(v)
+ case OpRotateLeft16:
+ return rewriteValuegeneric_OpRotateLeft16(v)
+ case OpRotateLeft32:
+ return rewriteValuegeneric_OpRotateLeft32(v)
+ case OpRotateLeft64:
+ return rewriteValuegeneric_OpRotateLeft64(v)
+ case OpRotateLeft8:
+ return rewriteValuegeneric_OpRotateLeft8(v)
+ case OpRound32F:
+ return rewriteValuegeneric_OpRound32F(v)
+ case OpRound64F:
+ return rewriteValuegeneric_OpRound64F(v)
+ case OpRsh16Ux16:
+ return rewriteValuegeneric_OpRsh16Ux16(v)
+ case OpRsh16Ux32:
+ return rewriteValuegeneric_OpRsh16Ux32(v)
+ case OpRsh16Ux64:
+ return rewriteValuegeneric_OpRsh16Ux64(v)
+ case OpRsh16Ux8:
+ return rewriteValuegeneric_OpRsh16Ux8(v)
+ case OpRsh16x16:
+ return rewriteValuegeneric_OpRsh16x16(v)
+ case OpRsh16x32:
+ return rewriteValuegeneric_OpRsh16x32(v)
+ case OpRsh16x64:
+ return rewriteValuegeneric_OpRsh16x64(v)
+ case OpRsh16x8:
+ return rewriteValuegeneric_OpRsh16x8(v)
+ case OpRsh32Ux16:
+ return rewriteValuegeneric_OpRsh32Ux16(v)
+ case OpRsh32Ux32:
+ return rewriteValuegeneric_OpRsh32Ux32(v)
+ case OpRsh32Ux64:
+ return rewriteValuegeneric_OpRsh32Ux64(v)
+ case OpRsh32Ux8:
+ return rewriteValuegeneric_OpRsh32Ux8(v)
+ case OpRsh32x16:
+ return rewriteValuegeneric_OpRsh32x16(v)
+ case OpRsh32x32:
+ return rewriteValuegeneric_OpRsh32x32(v)
+ case OpRsh32x64:
+ return rewriteValuegeneric_OpRsh32x64(v)
+ case OpRsh32x8:
+ return rewriteValuegeneric_OpRsh32x8(v)
+ case OpRsh64Ux16:
+ return rewriteValuegeneric_OpRsh64Ux16(v)
+ case OpRsh64Ux32:
+ return rewriteValuegeneric_OpRsh64Ux32(v)
+ case OpRsh64Ux64:
+ return rewriteValuegeneric_OpRsh64Ux64(v)
+ case OpRsh64Ux8:
+ return rewriteValuegeneric_OpRsh64Ux8(v)
+ case OpRsh64x16:
+ return rewriteValuegeneric_OpRsh64x16(v)
+ case OpRsh64x32:
+ return rewriteValuegeneric_OpRsh64x32(v)
+ case OpRsh64x64:
+ return rewriteValuegeneric_OpRsh64x64(v)
+ case OpRsh64x8:
+ return rewriteValuegeneric_OpRsh64x8(v)
+ case OpRsh8Ux16:
+ return rewriteValuegeneric_OpRsh8Ux16(v)
+ case OpRsh8Ux32:
+ return rewriteValuegeneric_OpRsh8Ux32(v)
+ case OpRsh8Ux64:
+ return rewriteValuegeneric_OpRsh8Ux64(v)
+ case OpRsh8Ux8:
+ return rewriteValuegeneric_OpRsh8Ux8(v)
+ case OpRsh8x16:
+ return rewriteValuegeneric_OpRsh8x16(v)
+ case OpRsh8x32:
+ return rewriteValuegeneric_OpRsh8x32(v)
+ case OpRsh8x64:
+ return rewriteValuegeneric_OpRsh8x64(v)
+ case OpRsh8x8:
+ return rewriteValuegeneric_OpRsh8x8(v)
+ case OpSelect0:
+ return rewriteValuegeneric_OpSelect0(v)
+ case OpSelect1:
+ return rewriteValuegeneric_OpSelect1(v)
+ case OpSelectN:
+ return rewriteValuegeneric_OpSelectN(v)
+ case OpSignExt16to32:
+ return rewriteValuegeneric_OpSignExt16to32(v)
+ case OpSignExt16to64:
+ return rewriteValuegeneric_OpSignExt16to64(v)
+ case OpSignExt32to64:
+ return rewriteValuegeneric_OpSignExt32to64(v)
+ case OpSignExt8to16:
+ return rewriteValuegeneric_OpSignExt8to16(v)
+ case OpSignExt8to32:
+ return rewriteValuegeneric_OpSignExt8to32(v)
+ case OpSignExt8to64:
+ return rewriteValuegeneric_OpSignExt8to64(v)
+ case OpSliceCap:
+ return rewriteValuegeneric_OpSliceCap(v)
+ case OpSliceLen:
+ return rewriteValuegeneric_OpSliceLen(v)
+ case OpSlicePtr:
+ return rewriteValuegeneric_OpSlicePtr(v)
+ case OpSlicemask:
+ return rewriteValuegeneric_OpSlicemask(v)
+ case OpSqrt:
+ return rewriteValuegeneric_OpSqrt(v)
+ case OpStaticCall:
+ return rewriteValuegeneric_OpStaticCall(v)
+ case OpStaticLECall:
+ return rewriteValuegeneric_OpStaticLECall(v)
+ case OpStore:
+ return rewriteValuegeneric_OpStore(v)
+ case OpStringLen:
+ return rewriteValuegeneric_OpStringLen(v)
+ case OpStringPtr:
+ return rewriteValuegeneric_OpStringPtr(v)
+ case OpStructSelect:
+ return rewriteValuegeneric_OpStructSelect(v)
+ case OpSub16:
+ return rewriteValuegeneric_OpSub16(v)
+ case OpSub32:
+ return rewriteValuegeneric_OpSub32(v)
+ case OpSub32F:
+ return rewriteValuegeneric_OpSub32F(v)
+ case OpSub64:
+ return rewriteValuegeneric_OpSub64(v)
+ case OpSub64F:
+ return rewriteValuegeneric_OpSub64F(v)
+ case OpSub8:
+ return rewriteValuegeneric_OpSub8(v)
+ case OpTrunc16to8:
+ return rewriteValuegeneric_OpTrunc16to8(v)
+ case OpTrunc32to16:
+ return rewriteValuegeneric_OpTrunc32to16(v)
+ case OpTrunc32to8:
+ return rewriteValuegeneric_OpTrunc32to8(v)
+ case OpTrunc64to16:
+ return rewriteValuegeneric_OpTrunc64to16(v)
+ case OpTrunc64to32:
+ return rewriteValuegeneric_OpTrunc64to32(v)
+ case OpTrunc64to8:
+ return rewriteValuegeneric_OpTrunc64to8(v)
+ case OpXor16:
+ return rewriteValuegeneric_OpXor16(v)
+ case OpXor32:
+ return rewriteValuegeneric_OpXor32(v)
+ case OpXor64:
+ return rewriteValuegeneric_OpXor64(v)
+ case OpXor8:
+ return rewriteValuegeneric_OpXor8(v)
+ case OpZero:
+ return rewriteValuegeneric_OpZero(v)
+ case OpZeroExt16to32:
+ return rewriteValuegeneric_OpZeroExt16to32(v)
+ case OpZeroExt16to64:
+ return rewriteValuegeneric_OpZeroExt16to64(v)
+ case OpZeroExt32to64:
+ return rewriteValuegeneric_OpZeroExt32to64(v)
+ case OpZeroExt8to16:
+ return rewriteValuegeneric_OpZeroExt8to16(v)
+ case OpZeroExt8to32:
+ return rewriteValuegeneric_OpZeroExt8to32(v)
+ case OpZeroExt8to64:
+ return rewriteValuegeneric_OpZeroExt8to64(v)
+ }
+ return false
+}
+func rewriteValuegeneric_OpAdd16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Add16 (Const16 [c]) (Const16 [d]))
+ // result: (Const16 [c+d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c + d)
+ return true
+ }
+ break
+ }
+ // match: (Add16 <t> (Mul16 x y) (Mul16 x z))
+ // result: (Mul16 x (Add16 <t> y z))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMul16 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if v_1.Op != OpMul16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, v_1_0, v_1_1 = _i2+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ z := v_1_1
+ v.reset(OpMul16)
+ v0 := b.NewValue0(v.Pos, OpAdd16, t)
+ v0.AddArg2(y, z)
+ v.AddArg2(x, v0)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Add16 (Const16 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Add16 (Const16 [1]) (Com16 x))
+ // result: (Neg16 x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 1 || v_1.Op != OpCom16 {
+ continue
+ }
+ x := v_1.Args[0]
+ v.reset(OpNeg16)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Add16 (Add16 i:(Const16 <t>) z) x)
+ // cond: (z.Op != OpConst16 && x.Op != OpConst16)
+ // result: (Add16 i (Add16 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAdd16 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst16 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst16 && x.Op != OpConst16) {
+ continue
+ }
+ v.reset(OpAdd16)
+ v0 := b.NewValue0(v.Pos, OpAdd16, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Add16 (Sub16 i:(Const16 <t>) z) x)
+ // cond: (z.Op != OpConst16 && x.Op != OpConst16)
+ // result: (Add16 i (Sub16 <t> x z))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpSub16 {
+ continue
+ }
+ z := v_0.Args[1]
+ i := v_0.Args[0]
+ if i.Op != OpConst16 {
+ continue
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst16 && x.Op != OpConst16) {
+ continue
+ }
+ v.reset(OpAdd16)
+ v0 := b.NewValue0(v.Pos, OpSub16, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(i, v0)
+ return true
+ }
+ break
+ }
+ // match: (Add16 (Const16 <t> [c]) (Add16 (Const16 <t> [d]) x))
+ // result: (Add16 (Const16 <t> [c+d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpAdd16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt16(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpAdd16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c + d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Add16 (Const16 <t> [c]) (Sub16 (Const16 <t> [d]) x))
+ // result: (Sub16 (Const16 <t> [c+d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpSub16 {
+ continue
+ }
+ x := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst16 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt16(v_1_0.AuxInt)
+ v.reset(OpSub16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c + d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpAdd32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Add32 (Const32 [c]) (Const32 [d]))
+ // result: (Const32 [c+d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c + d)
+ return true
+ }
+ break
+ }
+ // match: (Add32 <t> (Mul32 x y) (Mul32 x z))
+ // result: (Mul32 x (Add32 <t> y z))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMul32 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, v_1_0, v_1_1 = _i2+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ z := v_1_1
+ v.reset(OpMul32)
+ v0 := b.NewValue0(v.Pos, OpAdd32, t)
+ v0.AddArg2(y, z)
+ v.AddArg2(x, v0)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Add32 (Const32 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Add32 (Const32 [1]) (Com32 x))
+ // result: (Neg32 x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 1 || v_1.Op != OpCom32 {
+ continue
+ }
+ x := v_1.Args[0]
+ v.reset(OpNeg32)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Add32 (Add32 i:(Const32 <t>) z) x)
+ // cond: (z.Op != OpConst32 && x.Op != OpConst32)
+ // result: (Add32 i (Add32 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAdd32 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst32 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst32 && x.Op != OpConst32) {
+ continue
+ }
+ v.reset(OpAdd32)
+ v0 := b.NewValue0(v.Pos, OpAdd32, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Add32 (Sub32 i:(Const32 <t>) z) x)
+ // cond: (z.Op != OpConst32 && x.Op != OpConst32)
+ // result: (Add32 i (Sub32 <t> x z))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpSub32 {
+ continue
+ }
+ z := v_0.Args[1]
+ i := v_0.Args[0]
+ if i.Op != OpConst32 {
+ continue
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst32 && x.Op != OpConst32) {
+ continue
+ }
+ v.reset(OpAdd32)
+ v0 := b.NewValue0(v.Pos, OpSub32, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(i, v0)
+ return true
+ }
+ break
+ }
+ // match: (Add32 (Const32 <t> [c]) (Add32 (Const32 <t> [d]) x))
+ // result: (Add32 (Const32 <t> [c+d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpAdd32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpAdd32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Add32 (Const32 <t> [c]) (Sub32 (Const32 <t> [d]) x))
+ // result: (Sub32 (Const32 <t> [c+d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpSub32 {
+ continue
+ }
+ x := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ v.reset(OpSub32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c + d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpAdd32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Add32F (Const32F [c]) (Const32F [d]))
+ // cond: c+d == c+d
+ // result: (Const32F [c+d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32F {
+ continue
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ if v_1.Op != OpConst32F {
+ continue
+ }
+ d := auxIntToFloat32(v_1.AuxInt)
+ if !(c+d == c+d) {
+ continue
+ }
+ v.reset(OpConst32F)
+ v.AuxInt = float32ToAuxInt(c + d)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpAdd64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Add64 (Const64 [c]) (Const64 [d]))
+ // result: (Const64 [c+d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c + d)
+ return true
+ }
+ break
+ }
+ // match: (Add64 <t> (Mul64 x y) (Mul64 x z))
+ // result: (Mul64 x (Add64 <t> y z))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMul64 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if v_1.Op != OpMul64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, v_1_0, v_1_1 = _i2+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ z := v_1_1
+ v.reset(OpMul64)
+ v0 := b.NewValue0(v.Pos, OpAdd64, t)
+ v0.AddArg2(y, z)
+ v.AddArg2(x, v0)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Add64 (Const64 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Add64 (Const64 [1]) (Com64 x))
+ // result: (Neg64 x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 1 || v_1.Op != OpCom64 {
+ continue
+ }
+ x := v_1.Args[0]
+ v.reset(OpNeg64)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Add64 (Add64 i:(Const64 <t>) z) x)
+ // cond: (z.Op != OpConst64 && x.Op != OpConst64)
+ // result: (Add64 i (Add64 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAdd64 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst64 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst64 && x.Op != OpConst64) {
+ continue
+ }
+ v.reset(OpAdd64)
+ v0 := b.NewValue0(v.Pos, OpAdd64, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Add64 (Sub64 i:(Const64 <t>) z) x)
+ // cond: (z.Op != OpConst64 && x.Op != OpConst64)
+ // result: (Add64 i (Sub64 <t> x z))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpSub64 {
+ continue
+ }
+ z := v_0.Args[1]
+ i := v_0.Args[0]
+ if i.Op != OpConst64 {
+ continue
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst64 && x.Op != OpConst64) {
+ continue
+ }
+ v.reset(OpAdd64)
+ v0 := b.NewValue0(v.Pos, OpSub64, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(i, v0)
+ return true
+ }
+ break
+ }
+ // match: (Add64 (Const64 <t> [c]) (Add64 (Const64 <t> [d]) x))
+ // result: (Add64 (Const64 <t> [c+d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAdd64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpAdd64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Add64 (Const64 <t> [c]) (Sub64 (Const64 <t> [d]) x))
+ // result: (Sub64 (Const64 <t> [c+d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpSub64 {
+ continue
+ }
+ x := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ v.reset(OpSub64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpAdd64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Add64F (Const64F [c]) (Const64F [d]))
+ // cond: c+d == c+d
+ // result: (Const64F [c+d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64F {
+ continue
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ if v_1.Op != OpConst64F {
+ continue
+ }
+ d := auxIntToFloat64(v_1.AuxInt)
+ if !(c+d == c+d) {
+ continue
+ }
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(c + d)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpAdd8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Add8 (Const8 [c]) (Const8 [d]))
+ // result: (Const8 [c+d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c + d)
+ return true
+ }
+ break
+ }
+ // match: (Add8 <t> (Mul8 x y) (Mul8 x z))
+ // result: (Mul8 x (Add8 <t> y z))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMul8 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if v_1.Op != OpMul8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, v_1_0, v_1_1 = _i2+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ z := v_1_1
+ v.reset(OpMul8)
+ v0 := b.NewValue0(v.Pos, OpAdd8, t)
+ v0.AddArg2(y, z)
+ v.AddArg2(x, v0)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Add8 (Const8 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Add8 (Const8 [1]) (Com8 x))
+ // result: (Neg8 x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 1 || v_1.Op != OpCom8 {
+ continue
+ }
+ x := v_1.Args[0]
+ v.reset(OpNeg8)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Add8 (Add8 i:(Const8 <t>) z) x)
+ // cond: (z.Op != OpConst8 && x.Op != OpConst8)
+ // result: (Add8 i (Add8 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAdd8 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst8 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst8 && x.Op != OpConst8) {
+ continue
+ }
+ v.reset(OpAdd8)
+ v0 := b.NewValue0(v.Pos, OpAdd8, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Add8 (Sub8 i:(Const8 <t>) z) x)
+ // cond: (z.Op != OpConst8 && x.Op != OpConst8)
+ // result: (Add8 i (Sub8 <t> x z))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpSub8 {
+ continue
+ }
+ z := v_0.Args[1]
+ i := v_0.Args[0]
+ if i.Op != OpConst8 {
+ continue
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst8 && x.Op != OpConst8) {
+ continue
+ }
+ v.reset(OpAdd8)
+ v0 := b.NewValue0(v.Pos, OpSub8, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(i, v0)
+ return true
+ }
+ break
+ }
+ // match: (Add8 (Const8 <t> [c]) (Add8 (Const8 <t> [d]) x))
+ // result: (Add8 (Const8 <t> [c+d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpAdd8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst8 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt8(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpAdd8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c + d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Add8 (Const8 <t> [c]) (Sub8 (Const8 <t> [d]) x))
+ // result: (Sub8 (Const8 <t> [c+d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpSub8 {
+ continue
+ }
+ x := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst8 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt8(v_1_0.AuxInt)
+ v.reset(OpSub8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c + d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpAddPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (AddPtr <t> x (Const64 [c]))
+ // result: (OffPtr <t> x [c])
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpOffPtr)
+ v.Type = t
+ v.AuxInt = int64ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (AddPtr <t> x (Const32 [c]))
+ // result: (OffPtr <t> x [int64(c)])
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpOffPtr)
+ v.Type = t
+ v.AuxInt = int64ToAuxInt(int64(c))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpAnd16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (And16 (Const16 [c]) (Const16 [d]))
+ // result: (Const16 [c&d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c & d)
+ return true
+ }
+ break
+ }
+ // match: (And16 (Const16 [m]) (Rsh16Ux64 _ (Const64 [c])))
+ // cond: c >= int64(16-ntz16(m))
+ // result: (Const16 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ m := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpRsh16Ux64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= int64(16-ntz16(m))) {
+ continue
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And16 (Const16 [m]) (Lsh16x64 _ (Const64 [c])))
+ // cond: c >= int64(16-nlz16(m))
+ // result: (Const16 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ m := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpLsh16x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= int64(16-nlz16(m))) {
+ continue
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And16 x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (And16 (Const16 [-1]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (And16 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And16 x (And16 x y))
+ // result: (And16 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAnd16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(OpAnd16)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (And16 (And16 i:(Const16 <t>) z) x)
+ // cond: (z.Op != OpConst16 && x.Op != OpConst16)
+ // result: (And16 i (And16 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd16 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst16 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst16 && x.Op != OpConst16) {
+ continue
+ }
+ v.reset(OpAnd16)
+ v0 := b.NewValue0(v.Pos, OpAnd16, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (And16 (Const16 <t> [c]) (And16 (Const16 <t> [d]) x))
+ // result: (And16 (Const16 <t> [c&d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpAnd16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt16(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpAnd16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c & d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpAnd32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (And32 (Const32 [c]) (Const32 [d]))
+ // result: (Const32 [c&d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c & d)
+ return true
+ }
+ break
+ }
+ // match: (And32 (Const32 [m]) (Rsh32Ux64 _ (Const64 [c])))
+ // cond: c >= int64(32-ntz32(m))
+ // result: (Const32 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpRsh32Ux64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= int64(32-ntz32(m))) {
+ continue
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And32 (Const32 [m]) (Lsh32x64 _ (Const64 [c])))
+ // cond: c >= int64(32-nlz32(m))
+ // result: (Const32 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpLsh32x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= int64(32-nlz32(m))) {
+ continue
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And32 x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (And32 (Const32 [-1]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (And32 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And32 x (And32 x y))
+ // result: (And32 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAnd32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(OpAnd32)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (And32 (And32 i:(Const32 <t>) z) x)
+ // cond: (z.Op != OpConst32 && x.Op != OpConst32)
+ // result: (And32 i (And32 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd32 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst32 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst32 && x.Op != OpConst32) {
+ continue
+ }
+ v.reset(OpAnd32)
+ v0 := b.NewValue0(v.Pos, OpAnd32, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (And32 (Const32 <t> [c]) (And32 (Const32 <t> [d]) x))
+ // result: (And32 (Const32 <t> [c&d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpAnd32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpAnd32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c & d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpAnd64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (And64 (Const64 [c]) (Const64 [d]))
+ // result: (Const64 [c&d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c & d)
+ return true
+ }
+ break
+ }
+ // match: (And64 (Const64 [m]) (Rsh64Ux64 _ (Const64 [c])))
+ // cond: c >= int64(64-ntz64(m))
+ // result: (Const64 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpRsh64Ux64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= int64(64-ntz64(m))) {
+ continue
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And64 (Const64 [m]) (Lsh64x64 _ (Const64 [c])))
+ // cond: c >= int64(64-nlz64(m))
+ // result: (Const64 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpLsh64x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= int64(64-nlz64(m))) {
+ continue
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And64 x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (And64 (Const64 [-1]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (And64 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And64 x (And64 x y))
+ // result: (And64 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAnd64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(OpAnd64)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (And64 (And64 i:(Const64 <t>) z) x)
+ // cond: (z.Op != OpConst64 && x.Op != OpConst64)
+ // result: (And64 i (And64 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd64 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst64 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst64 && x.Op != OpConst64) {
+ continue
+ }
+ v.reset(OpAnd64)
+ v0 := b.NewValue0(v.Pos, OpAnd64, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (And64 (Const64 <t> [c]) (And64 (Const64 <t> [d]) x))
+ // result: (And64 (Const64 <t> [c&d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAnd64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpAnd64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c & d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpAnd8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (And8 (Const8 [c]) (Const8 [d]))
+ // result: (Const8 [c&d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c & d)
+ return true
+ }
+ break
+ }
+ // match: (And8 (Const8 [m]) (Rsh8Ux64 _ (Const64 [c])))
+ // cond: c >= int64(8-ntz8(m))
+ // result: (Const8 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ m := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpRsh8Ux64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= int64(8-ntz8(m))) {
+ continue
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And8 (Const8 [m]) (Lsh8x64 _ (Const64 [c])))
+ // cond: c >= int64(8-nlz8(m))
+ // result: (Const8 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ m := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpLsh8x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= int64(8-nlz8(m))) {
+ continue
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And8 x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (And8 (Const8 [-1]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (And8 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (And8 x (And8 x y))
+ // result: (And8 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpAnd8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(OpAnd8)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (And8 (And8 i:(Const8 <t>) z) x)
+ // cond: (z.Op != OpConst8 && x.Op != OpConst8)
+ // result: (And8 i (And8 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd8 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst8 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst8 && x.Op != OpConst8) {
+ continue
+ }
+ v.reset(OpAnd8)
+ v0 := b.NewValue0(v.Pos, OpAnd8, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (And8 (Const8 <t> [c]) (And8 (Const8 <t> [d]) x))
+ // result: (And8 (Const8 <t> [c&d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpAnd8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst8 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt8(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpAnd8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c & d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpAndB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (AndB (Leq64 (Const64 [c]) x) (Less64 x (Const64 [d])))
+ // cond: d >= c
+ // result: (Less64U (Sub64 <x.Type> x (Const64 <x.Type> [c])) (Const64 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq64 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLess64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(d >= c) {
+ continue
+ }
+ v.reset(OpLess64U)
+ v0 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v1.AuxInt = int64ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq64 (Const64 [c]) x) (Leq64 x (Const64 [d])))
+ // cond: d >= c
+ // result: (Leq64U (Sub64 <x.Type> x (Const64 <x.Type> [c])) (Const64 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq64 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLeq64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(d >= c) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v1.AuxInt = int64ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq32 (Const32 [c]) x) (Less32 x (Const32 [d])))
+ // cond: d >= c
+ // result: (Less32U (Sub32 <x.Type> x (Const32 <x.Type> [c])) (Const32 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq32 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLess32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(d >= c) {
+ continue
+ }
+ v.reset(OpLess32U)
+ v0 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v1.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq32 (Const32 [c]) x) (Leq32 x (Const32 [d])))
+ // cond: d >= c
+ // result: (Leq32U (Sub32 <x.Type> x (Const32 <x.Type> [c])) (Const32 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq32 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLeq32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(d >= c) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v1.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq16 (Const16 [c]) x) (Less16 x (Const16 [d])))
+ // cond: d >= c
+ // result: (Less16U (Sub16 <x.Type> x (Const16 <x.Type> [c])) (Const16 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq16 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLess16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(d >= c) {
+ continue
+ }
+ v.reset(OpLess16U)
+ v0 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v1.AuxInt = int16ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq16 (Const16 [c]) x) (Leq16 x (Const16 [d])))
+ // cond: d >= c
+ // result: (Leq16U (Sub16 <x.Type> x (Const16 <x.Type> [c])) (Const16 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq16 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLeq16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(d >= c) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v1.AuxInt = int16ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq8 (Const8 [c]) x) (Less8 x (Const8 [d])))
+ // cond: d >= c
+ // result: (Less8U (Sub8 <x.Type> x (Const8 <x.Type> [c])) (Const8 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq8 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLess8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(d >= c) {
+ continue
+ }
+ v.reset(OpLess8U)
+ v0 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v1.AuxInt = int8ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq8 (Const8 [c]) x) (Leq8 x (Const8 [d])))
+ // cond: d >= c
+ // result: (Leq8U (Sub8 <x.Type> x (Const8 <x.Type> [c])) (Const8 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq8 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLeq8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(d >= c) {
+ continue
+ }
+ v.reset(OpLeq8U)
+ v0 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v1.AuxInt = int8ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less64 (Const64 [c]) x) (Less64 x (Const64 [d])))
+ // cond: d >= c+1 && c+1 > c
+ // result: (Less64U (Sub64 <x.Type> x (Const64 <x.Type> [c+1])) (Const64 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess64 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLess64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(d >= c+1 && c+1 > c) {
+ continue
+ }
+ v.reset(OpLess64U)
+ v0 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v1.AuxInt = int64ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less64 (Const64 [c]) x) (Leq64 x (Const64 [d])))
+ // cond: d >= c+1 && c+1 > c
+ // result: (Leq64U (Sub64 <x.Type> x (Const64 <x.Type> [c+1])) (Const64 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess64 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLeq64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(d >= c+1 && c+1 > c) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v1.AuxInt = int64ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less32 (Const32 [c]) x) (Less32 x (Const32 [d])))
+ // cond: d >= c+1 && c+1 > c
+ // result: (Less32U (Sub32 <x.Type> x (Const32 <x.Type> [c+1])) (Const32 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess32 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLess32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(d >= c+1 && c+1 > c) {
+ continue
+ }
+ v.reset(OpLess32U)
+ v0 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v1.AuxInt = int32ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less32 (Const32 [c]) x) (Leq32 x (Const32 [d])))
+ // cond: d >= c+1 && c+1 > c
+ // result: (Leq32U (Sub32 <x.Type> x (Const32 <x.Type> [c+1])) (Const32 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess32 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLeq32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(d >= c+1 && c+1 > c) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v1.AuxInt = int32ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less16 (Const16 [c]) x) (Less16 x (Const16 [d])))
+ // cond: d >= c+1 && c+1 > c
+ // result: (Less16U (Sub16 <x.Type> x (Const16 <x.Type> [c+1])) (Const16 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess16 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLess16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(d >= c+1 && c+1 > c) {
+ continue
+ }
+ v.reset(OpLess16U)
+ v0 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v1.AuxInt = int16ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less16 (Const16 [c]) x) (Leq16 x (Const16 [d])))
+ // cond: d >= c+1 && c+1 > c
+ // result: (Leq16U (Sub16 <x.Type> x (Const16 <x.Type> [c+1])) (Const16 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess16 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLeq16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(d >= c+1 && c+1 > c) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v1.AuxInt = int16ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less8 (Const8 [c]) x) (Less8 x (Const8 [d])))
+ // cond: d >= c+1 && c+1 > c
+ // result: (Less8U (Sub8 <x.Type> x (Const8 <x.Type> [c+1])) (Const8 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess8 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLess8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(d >= c+1 && c+1 > c) {
+ continue
+ }
+ v.reset(OpLess8U)
+ v0 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v1.AuxInt = int8ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less8 (Const8 [c]) x) (Leq8 x (Const8 [d])))
+ // cond: d >= c+1 && c+1 > c
+ // result: (Leq8U (Sub8 <x.Type> x (Const8 <x.Type> [c+1])) (Const8 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess8 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLeq8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(d >= c+1 && c+1 > c) {
+ continue
+ }
+ v.reset(OpLeq8U)
+ v0 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v1.AuxInt = int8ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq64U (Const64 [c]) x) (Less64U x (Const64 [d])))
+ // cond: uint64(d) >= uint64(c)
+ // result: (Less64U (Sub64 <x.Type> x (Const64 <x.Type> [c])) (Const64 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq64U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLess64U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(uint64(d) >= uint64(c)) {
+ continue
+ }
+ v.reset(OpLess64U)
+ v0 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v1.AuxInt = int64ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq64U (Const64 [c]) x) (Leq64U x (Const64 [d])))
+ // cond: uint64(d) >= uint64(c)
+ // result: (Leq64U (Sub64 <x.Type> x (Const64 <x.Type> [c])) (Const64 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq64U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLeq64U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(uint64(d) >= uint64(c)) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v1.AuxInt = int64ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq32U (Const32 [c]) x) (Less32U x (Const32 [d])))
+ // cond: uint32(d) >= uint32(c)
+ // result: (Less32U (Sub32 <x.Type> x (Const32 <x.Type> [c])) (Const32 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq32U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLess32U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(uint32(d) >= uint32(c)) {
+ continue
+ }
+ v.reset(OpLess32U)
+ v0 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v1.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq32U (Const32 [c]) x) (Leq32U x (Const32 [d])))
+ // cond: uint32(d) >= uint32(c)
+ // result: (Leq32U (Sub32 <x.Type> x (Const32 <x.Type> [c])) (Const32 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq32U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLeq32U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(uint32(d) >= uint32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v1.AuxInt = int32ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq16U (Const16 [c]) x) (Less16U x (Const16 [d])))
+ // cond: uint16(d) >= uint16(c)
+ // result: (Less16U (Sub16 <x.Type> x (Const16 <x.Type> [c])) (Const16 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq16U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLess16U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(uint16(d) >= uint16(c)) {
+ continue
+ }
+ v.reset(OpLess16U)
+ v0 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v1.AuxInt = int16ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq16U (Const16 [c]) x) (Leq16U x (Const16 [d])))
+ // cond: uint16(d) >= uint16(c)
+ // result: (Leq16U (Sub16 <x.Type> x (Const16 <x.Type> [c])) (Const16 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq16U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLeq16U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(uint16(d) >= uint16(c)) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v1.AuxInt = int16ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq8U (Const8 [c]) x) (Less8U x (Const8 [d])))
+ // cond: uint8(d) >= uint8(c)
+ // result: (Less8U (Sub8 <x.Type> x (Const8 <x.Type> [c])) (Const8 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq8U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLess8U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(uint8(d) >= uint8(c)) {
+ continue
+ }
+ v.reset(OpLess8U)
+ v0 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v1.AuxInt = int8ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Leq8U (Const8 [c]) x) (Leq8U x (Const8 [d])))
+ // cond: uint8(d) >= uint8(c)
+ // result: (Leq8U (Sub8 <x.Type> x (Const8 <x.Type> [c])) (Const8 <x.Type> [d-c]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq8U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLeq8U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(uint8(d) >= uint8(c)) {
+ continue
+ }
+ v.reset(OpLeq8U)
+ v0 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v1.AuxInt = int8ToAuxInt(c)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d - c)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less64U (Const64 [c]) x) (Less64U x (Const64 [d])))
+ // cond: uint64(d) >= uint64(c+1) && uint64(c+1) > uint64(c)
+ // result: (Less64U (Sub64 <x.Type> x (Const64 <x.Type> [c+1])) (Const64 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess64U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLess64U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(uint64(d) >= uint64(c+1) && uint64(c+1) > uint64(c)) {
+ continue
+ }
+ v.reset(OpLess64U)
+ v0 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v1.AuxInt = int64ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less64U (Const64 [c]) x) (Leq64U x (Const64 [d])))
+ // cond: uint64(d) >= uint64(c+1) && uint64(c+1) > uint64(c)
+ // result: (Leq64U (Sub64 <x.Type> x (Const64 <x.Type> [c+1])) (Const64 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess64U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLeq64U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(uint64(d) >= uint64(c+1) && uint64(c+1) > uint64(c)) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v1.AuxInt = int64ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less32U (Const32 [c]) x) (Less32U x (Const32 [d])))
+ // cond: uint32(d) >= uint32(c+1) && uint32(c+1) > uint32(c)
+ // result: (Less32U (Sub32 <x.Type> x (Const32 <x.Type> [c+1])) (Const32 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess32U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLess32U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(uint32(d) >= uint32(c+1) && uint32(c+1) > uint32(c)) {
+ continue
+ }
+ v.reset(OpLess32U)
+ v0 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v1.AuxInt = int32ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less32U (Const32 [c]) x) (Leq32U x (Const32 [d])))
+ // cond: uint32(d) >= uint32(c+1) && uint32(c+1) > uint32(c)
+ // result: (Leq32U (Sub32 <x.Type> x (Const32 <x.Type> [c+1])) (Const32 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess32U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLeq32U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(uint32(d) >= uint32(c+1) && uint32(c+1) > uint32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v1.AuxInt = int32ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less16U (Const16 [c]) x) (Less16U x (Const16 [d])))
+ // cond: uint16(d) >= uint16(c+1) && uint16(c+1) > uint16(c)
+ // result: (Less16U (Sub16 <x.Type> x (Const16 <x.Type> [c+1])) (Const16 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess16U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLess16U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(uint16(d) >= uint16(c+1) && uint16(c+1) > uint16(c)) {
+ continue
+ }
+ v.reset(OpLess16U)
+ v0 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v1.AuxInt = int16ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less16U (Const16 [c]) x) (Leq16U x (Const16 [d])))
+ // cond: uint16(d) >= uint16(c+1) && uint16(c+1) > uint16(c)
+ // result: (Leq16U (Sub16 <x.Type> x (Const16 <x.Type> [c+1])) (Const16 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess16U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLeq16U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(uint16(d) >= uint16(c+1) && uint16(c+1) > uint16(c)) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v1.AuxInt = int16ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less8U (Const8 [c]) x) (Less8U x (Const8 [d])))
+ // cond: uint8(d) >= uint8(c+1) && uint8(c+1) > uint8(c)
+ // result: (Less8U (Sub8 <x.Type> x (Const8 <x.Type> [c+1])) (Const8 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess8U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLess8U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(uint8(d) >= uint8(c+1) && uint8(c+1) > uint8(c)) {
+ continue
+ }
+ v.reset(OpLess8U)
+ v0 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v1.AuxInt = int8ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ // match: (AndB (Less8U (Const8 [c]) x) (Leq8U x (Const8 [d])))
+ // cond: uint8(d) >= uint8(c+1) && uint8(c+1) > uint8(c)
+ // result: (Leq8U (Sub8 <x.Type> x (Const8 <x.Type> [c+1])) (Const8 <x.Type> [d-c-1]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess8U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLeq8U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(uint8(d) >= uint8(c+1) && uint8(c+1) > uint8(c)) {
+ continue
+ }
+ v.reset(OpLeq8U)
+ v0 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v1 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v1.AuxInt = int8ToAuxInt(c + 1)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d - c - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpArraySelect(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ArraySelect (ArrayMake1 x))
+ // result: x
+ for {
+ if v_0.Op != OpArrayMake1 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (ArraySelect [0] (IData x))
+ // result: (IData x)
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 || v_0.Op != OpIData {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpIData)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCom16(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com16 (Com16 x))
+ // result: x
+ for {
+ if v_0.Op != OpCom16 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Com16 (Const16 [c]))
+ // result: (Const16 [^c])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(^c)
+ return true
+ }
+ // match: (Com16 (Add16 (Const16 [-1]) x))
+ // result: (Neg16 x)
+ for {
+ if v_0.Op != OpAdd16 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst16 || auxIntToInt16(v_0_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_0_1
+ v.reset(OpNeg16)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpCom32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com32 (Com32 x))
+ // result: x
+ for {
+ if v_0.Op != OpCom32 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Com32 (Const32 [c]))
+ // result: (Const32 [^c])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(^c)
+ return true
+ }
+ // match: (Com32 (Add32 (Const32 [-1]) x))
+ // result: (Neg32 x)
+ for {
+ if v_0.Op != OpAdd32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst32 || auxIntToInt32(v_0_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_0_1
+ v.reset(OpNeg32)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpCom64(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com64 (Com64 x))
+ // result: x
+ for {
+ if v_0.Op != OpCom64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Com64 (Const64 [c]))
+ // result: (Const64 [^c])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(^c)
+ return true
+ }
+ // match: (Com64 (Add64 (Const64 [-1]) x))
+ // result: (Neg64 x)
+ for {
+ if v_0.Op != OpAdd64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_0_1
+ v.reset(OpNeg64)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpCom8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Com8 (Com8 x))
+ // result: x
+ for {
+ if v_0.Op != OpCom8 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Com8 (Const8 [c]))
+ // result: (Const8 [^c])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(^c)
+ return true
+ }
+ // match: (Com8 (Add8 (Const8 [-1]) x))
+ // result: (Neg8 x)
+ for {
+ if v_0.Op != OpAdd8 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst8 || auxIntToInt8(v_0_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_0_1
+ v.reset(OpNeg8)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpConstInterface(v *Value) bool {
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (ConstInterface)
+ // result: (IMake (ConstNil <typ.Uintptr>) (ConstNil <typ.BytePtr>))
+ for {
+ v.reset(OpIMake)
+ v0 := b.NewValue0(v.Pos, OpConstNil, typ.Uintptr)
+ v1 := b.NewValue0(v.Pos, OpConstNil, typ.BytePtr)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuegeneric_OpConstSlice(v *Value) bool {
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (ConstSlice)
+ // cond: config.PtrSize == 4
+ // result: (SliceMake (ConstNil <v.Type.Elem().PtrTo()>) (Const32 <typ.Int> [0]) (Const32 <typ.Int> [0]))
+ for {
+ if !(config.PtrSize == 4) {
+ break
+ }
+ v.reset(OpSliceMake)
+ v0 := b.NewValue0(v.Pos, OpConstNil, v.Type.Elem().PtrTo())
+ v1 := b.NewValue0(v.Pos, OpConst32, typ.Int)
+ v1.AuxInt = int32ToAuxInt(0)
+ v.AddArg3(v0, v1, v1)
+ return true
+ }
+ // match: (ConstSlice)
+ // cond: config.PtrSize == 8
+ // result: (SliceMake (ConstNil <v.Type.Elem().PtrTo()>) (Const64 <typ.Int> [0]) (Const64 <typ.Int> [0]))
+ for {
+ if !(config.PtrSize == 8) {
+ break
+ }
+ v.reset(OpSliceMake)
+ v0 := b.NewValue0(v.Pos, OpConstNil, v.Type.Elem().PtrTo())
+ v1 := b.NewValue0(v.Pos, OpConst64, typ.Int)
+ v1.AuxInt = int64ToAuxInt(0)
+ v.AddArg3(v0, v1, v1)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpConstString(v *Value) bool {
+ b := v.Block
+ config := b.Func.Config
+ fe := b.Func.fe
+ typ := &b.Func.Config.Types
+ // match: (ConstString {str})
+ // cond: config.PtrSize == 4 && str == ""
+ // result: (StringMake (ConstNil) (Const32 <typ.Int> [0]))
+ for {
+ str := auxToString(v.Aux)
+ if !(config.PtrSize == 4 && str == "") {
+ break
+ }
+ v.reset(OpStringMake)
+ v0 := b.NewValue0(v.Pos, OpConstNil, typ.BytePtr)
+ v1 := b.NewValue0(v.Pos, OpConst32, typ.Int)
+ v1.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (ConstString {str})
+ // cond: config.PtrSize == 8 && str == ""
+ // result: (StringMake (ConstNil) (Const64 <typ.Int> [0]))
+ for {
+ str := auxToString(v.Aux)
+ if !(config.PtrSize == 8 && str == "") {
+ break
+ }
+ v.reset(OpStringMake)
+ v0 := b.NewValue0(v.Pos, OpConstNil, typ.BytePtr)
+ v1 := b.NewValue0(v.Pos, OpConst64, typ.Int)
+ v1.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ // match: (ConstString {str})
+ // cond: config.PtrSize == 4 && str != ""
+ // result: (StringMake (Addr <typ.BytePtr> {fe.StringData(str)} (SB)) (Const32 <typ.Int> [int32(len(str))]))
+ for {
+ str := auxToString(v.Aux)
+ if !(config.PtrSize == 4 && str != "") {
+ break
+ }
+ v.reset(OpStringMake)
+ v0 := b.NewValue0(v.Pos, OpAddr, typ.BytePtr)
+ v0.Aux = symToAux(fe.StringData(str))
+ v1 := b.NewValue0(v.Pos, OpSB, typ.Uintptr)
+ v0.AddArg(v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.Int)
+ v2.AuxInt = int32ToAuxInt(int32(len(str)))
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (ConstString {str})
+ // cond: config.PtrSize == 8 && str != ""
+ // result: (StringMake (Addr <typ.BytePtr> {fe.StringData(str)} (SB)) (Const64 <typ.Int> [int64(len(str))]))
+ for {
+ str := auxToString(v.Aux)
+ if !(config.PtrSize == 8 && str != "") {
+ break
+ }
+ v.reset(OpStringMake)
+ v0 := b.NewValue0(v.Pos, OpAddr, typ.BytePtr)
+ v0.Aux = symToAux(fe.StringData(str))
+ v1 := b.NewValue0(v.Pos, OpSB, typ.Uintptr)
+ v0.AddArg(v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.Int)
+ v2.AuxInt = int64ToAuxInt(int64(len(str)))
+ v.AddArg2(v0, v2)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpConvert(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Convert (Add64 (Convert ptr mem) off) mem)
+ // result: (AddPtr ptr off)
+ for {
+ if v_0.Op != OpAdd64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConvert {
+ continue
+ }
+ mem := v_0_0.Args[1]
+ ptr := v_0_0.Args[0]
+ off := v_0_1
+ if mem != v_1 {
+ continue
+ }
+ v.reset(OpAddPtr)
+ v.AddArg2(ptr, off)
+ return true
+ }
+ break
+ }
+ // match: (Convert (Add32 (Convert ptr mem) off) mem)
+ // result: (AddPtr ptr off)
+ for {
+ if v_0.Op != OpAdd32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConvert {
+ continue
+ }
+ mem := v_0_0.Args[1]
+ ptr := v_0_0.Args[0]
+ off := v_0_1
+ if mem != v_1 {
+ continue
+ }
+ v.reset(OpAddPtr)
+ v.AddArg2(ptr, off)
+ return true
+ }
+ break
+ }
+ // match: (Convert (Convert ptr mem) mem)
+ // result: ptr
+ for {
+ if v_0.Op != OpConvert {
+ break
+ }
+ mem := v_0.Args[1]
+ ptr := v_0.Args[0]
+ if mem != v_1 {
+ break
+ }
+ v.copyOf(ptr)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCtz16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (Ctz16 (Const16 [c]))
+ // cond: config.PtrSize == 4
+ // result: (Const32 [int32(ntz16(c))])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if !(config.PtrSize == 4) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(ntz16(c)))
+ return true
+ }
+ // match: (Ctz16 (Const16 [c]))
+ // cond: config.PtrSize == 8
+ // result: (Const64 [int64(ntz16(c))])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if !(config.PtrSize == 8) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(ntz16(c)))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCtz32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (Ctz32 (Const32 [c]))
+ // cond: config.PtrSize == 4
+ // result: (Const32 [int32(ntz32(c))])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(config.PtrSize == 4) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(ntz32(c)))
+ return true
+ }
+ // match: (Ctz32 (Const32 [c]))
+ // cond: config.PtrSize == 8
+ // result: (Const64 [int64(ntz32(c))])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if !(config.PtrSize == 8) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(ntz32(c)))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCtz64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (Ctz64 (Const64 [c]))
+ // cond: config.PtrSize == 4
+ // result: (Const32 [int32(ntz64(c))])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(config.PtrSize == 4) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(ntz64(c)))
+ return true
+ }
+ // match: (Ctz64 (Const64 [c]))
+ // cond: config.PtrSize == 8
+ // result: (Const64 [int64(ntz64(c))])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if !(config.PtrSize == 8) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(ntz64(c)))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCtz8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (Ctz8 (Const8 [c]))
+ // cond: config.PtrSize == 4
+ // result: (Const32 [int32(ntz8(c))])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if !(config.PtrSize == 4) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(ntz8(c)))
+ return true
+ }
+ // match: (Ctz8 (Const8 [c]))
+ // cond: config.PtrSize == 8
+ // result: (Const64 [int64(ntz8(c))])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if !(config.PtrSize == 8) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(ntz8(c)))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvt32Fto32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Cvt32Fto32 (Const32F [c]))
+ // result: (Const32 [int32(c)])
+ for {
+ if v_0.Op != OpConst32F {
+ break
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvt32Fto64(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Cvt32Fto64 (Const32F [c]))
+ // result: (Const64 [int64(c)])
+ for {
+ if v_0.Op != OpConst32F {
+ break
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvt32Fto64F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Cvt32Fto64F (Const32F [c]))
+ // result: (Const64F [float64(c)])
+ for {
+ if v_0.Op != OpConst32F {
+ break
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(float64(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvt32to32F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Cvt32to32F (Const32 [c]))
+ // result: (Const32F [float32(c)])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpConst32F)
+ v.AuxInt = float32ToAuxInt(float32(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvt32to64F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Cvt32to64F (Const32 [c]))
+ // result: (Const64F [float64(c)])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(float64(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvt64Fto32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Cvt64Fto32 (Const64F [c]))
+ // result: (Const32 [int32(c)])
+ for {
+ if v_0.Op != OpConst64F {
+ break
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvt64Fto32F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Cvt64Fto32F (Const64F [c]))
+ // result: (Const32F [float32(c)])
+ for {
+ if v_0.Op != OpConst64F {
+ break
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ v.reset(OpConst32F)
+ v.AuxInt = float32ToAuxInt(float32(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvt64Fto64(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Cvt64Fto64 (Const64F [c]))
+ // result: (Const64 [int64(c)])
+ for {
+ if v_0.Op != OpConst64F {
+ break
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvt64to32F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Cvt64to32F (Const64 [c]))
+ // result: (Const32F [float32(c)])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpConst32F)
+ v.AuxInt = float32ToAuxInt(float32(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvt64to64F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Cvt64to64F (Const64 [c]))
+ // result: (Const64F [float64(c)])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(float64(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpCvtBoolToUint8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (CvtBoolToUint8 (ConstBool [false]))
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConstBool || auxIntToBool(v_0.AuxInt) != false {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ // match: (CvtBoolToUint8 (ConstBool [true]))
+ // result: (Const8 [1])
+ for {
+ if v_0.Op != OpConstBool || auxIntToBool(v_0.AuxInt) != true {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(1)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpDiv16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div16 (Const16 [c]) (Const16 [d]))
+ // cond: d != 0
+ // result: (Const16 [c/d])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ break
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c / d)
+ return true
+ }
+ // match: (Div16 n (Const16 [c]))
+ // cond: isNonNegative(n) && isPowerOfTwo16(c)
+ // result: (Rsh16Ux64 n (Const64 <typ.UInt64> [log16(c)]))
+ for {
+ n := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(isNonNegative(n) && isPowerOfTwo16(c)) {
+ break
+ }
+ v.reset(OpRsh16Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log16(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Div16 <t> n (Const16 [c]))
+ // cond: c < 0 && c != -1<<15
+ // result: (Neg16 (Div16 <t> n (Const16 <t> [-c])))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(c < 0 && c != -1<<15) {
+ break
+ }
+ v.reset(OpNeg16)
+ v0 := b.NewValue0(v.Pos, OpDiv16, t)
+ v1 := b.NewValue0(v.Pos, OpConst16, t)
+ v1.AuxInt = int16ToAuxInt(-c)
+ v0.AddArg2(n, v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Div16 <t> x (Const16 [-1<<15]))
+ // result: (Rsh16Ux64 (And16 <t> x (Neg16 <t> x)) (Const64 <typ.UInt64> [15]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 || auxIntToInt16(v_1.AuxInt) != -1<<15 {
+ break
+ }
+ v.reset(OpRsh16Ux64)
+ v0 := b.NewValue0(v.Pos, OpAnd16, t)
+ v1 := b.NewValue0(v.Pos, OpNeg16, t)
+ v1.AddArg(x)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(15)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (Div16 <t> n (Const16 [c]))
+ // cond: isPowerOfTwo16(c)
+ // result: (Rsh16x64 (Add16 <t> n (Rsh16Ux64 <t> (Rsh16x64 <t> n (Const64 <typ.UInt64> [15])) (Const64 <typ.UInt64> [int64(16-log16(c))]))) (Const64 <typ.UInt64> [int64(log16(c))]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(isPowerOfTwo16(c)) {
+ break
+ }
+ v.reset(OpRsh16x64)
+ v0 := b.NewValue0(v.Pos, OpAdd16, t)
+ v1 := b.NewValue0(v.Pos, OpRsh16Ux64, t)
+ v2 := b.NewValue0(v.Pos, OpRsh16x64, t)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(15)
+ v2.AddArg2(n, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(int64(16 - log16(c)))
+ v1.AddArg2(v2, v4)
+ v0.AddArg2(n, v1)
+ v5 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(int64(log16(c)))
+ v.AddArg2(v0, v5)
+ return true
+ }
+ // match: (Div16 <t> x (Const16 [c]))
+ // cond: smagicOK16(c)
+ // result: (Sub16 <t> (Rsh32x64 <t> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(smagic16(c).m)]) (SignExt16to32 x)) (Const64 <typ.UInt64> [16+smagic16(c).s])) (Rsh32x64 <t> (SignExt16to32 x) (Const64 <typ.UInt64> [31])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(smagicOK16(c)) {
+ break
+ }
+ v.reset(OpSub16)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRsh32x64, t)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(smagic16(c).m))
+ v3 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v3.AddArg(x)
+ v1.AddArg2(v2, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(16 + smagic16(c).s)
+ v0.AddArg2(v1, v4)
+ v5 := b.NewValue0(v.Pos, OpRsh32x64, t)
+ v6 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v6.AuxInt = int64ToAuxInt(31)
+ v5.AddArg2(v3, v6)
+ v.AddArg2(v0, v5)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpDiv16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Div16u (Const16 [c]) (Const16 [d]))
+ // cond: d != 0
+ // result: (Const16 [int16(uint16(c)/uint16(d))])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ break
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(int16(uint16(c) / uint16(d)))
+ return true
+ }
+ // match: (Div16u n (Const16 [c]))
+ // cond: isPowerOfTwo16(c)
+ // result: (Rsh16Ux64 n (Const64 <typ.UInt64> [log16(c)]))
+ for {
+ n := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(isPowerOfTwo16(c)) {
+ break
+ }
+ v.reset(OpRsh16Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log16(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Div16u x (Const16 [c]))
+ // cond: umagicOK16(c) && config.RegSize == 8
+ // result: (Trunc64to16 (Rsh64Ux64 <typ.UInt64> (Mul64 <typ.UInt64> (Const64 <typ.UInt64> [int64(1<<16+umagic16(c).m)]) (ZeroExt16to64 x)) (Const64 <typ.UInt64> [16+umagic16(c).s])))
+ for {
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(umagicOK16(c) && config.RegSize == 8) {
+ break
+ }
+ v.reset(OpTrunc64to16)
+ v0 := b.NewValue0(v.Pos, OpRsh64Ux64, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(1<<16 + umagic16(c).m))
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+ v3.AddArg(x)
+ v1.AddArg2(v2, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(16 + umagic16(c).s)
+ v0.AddArg2(v1, v4)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Div16u x (Const16 [c]))
+ // cond: umagicOK16(c) && config.RegSize == 4 && umagic16(c).m&1 == 0
+ // result: (Trunc32to16 (Rsh32Ux64 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(1<<15+umagic16(c).m/2)]) (ZeroExt16to32 x)) (Const64 <typ.UInt64> [16+umagic16(c).s-1])))
+ for {
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(umagicOK16(c) && config.RegSize == 4 && umagic16(c).m&1 == 0) {
+ break
+ }
+ v.reset(OpTrunc32to16)
+ v0 := b.NewValue0(v.Pos, OpRsh32Ux64, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(1<<15 + umagic16(c).m/2))
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v3.AddArg(x)
+ v1.AddArg2(v2, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(16 + umagic16(c).s - 1)
+ v0.AddArg2(v1, v4)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Div16u x (Const16 [c]))
+ // cond: umagicOK16(c) && config.RegSize == 4 && c&1 == 0
+ // result: (Trunc32to16 (Rsh32Ux64 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(1<<15+(umagic16(c).m+1)/2)]) (Rsh32Ux64 <typ.UInt32> (ZeroExt16to32 x) (Const64 <typ.UInt64> [1]))) (Const64 <typ.UInt64> [16+umagic16(c).s-2])))
+ for {
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(umagicOK16(c) && config.RegSize == 4 && c&1 == 0) {
+ break
+ }
+ v.reset(OpTrunc32to16)
+ v0 := b.NewValue0(v.Pos, OpRsh32Ux64, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(1<<15 + (umagic16(c).m+1)/2))
+ v3 := b.NewValue0(v.Pos, OpRsh32Ux64, typ.UInt32)
+ v4 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v4.AddArg(x)
+ v5 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(1)
+ v3.AddArg2(v4, v5)
+ v1.AddArg2(v2, v3)
+ v6 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v6.AuxInt = int64ToAuxInt(16 + umagic16(c).s - 2)
+ v0.AddArg2(v1, v6)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Div16u x (Const16 [c]))
+ // cond: umagicOK16(c) && config.RegSize == 4 && config.useAvg
+ // result: (Trunc32to16 (Rsh32Ux64 <typ.UInt32> (Avg32u (Lsh32x64 <typ.UInt32> (ZeroExt16to32 x) (Const64 <typ.UInt64> [16])) (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(umagic16(c).m)]) (ZeroExt16to32 x))) (Const64 <typ.UInt64> [16+umagic16(c).s-1])))
+ for {
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(umagicOK16(c) && config.RegSize == 4 && config.useAvg) {
+ break
+ }
+ v.reset(OpTrunc32to16)
+ v0 := b.NewValue0(v.Pos, OpRsh32Ux64, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpAvg32u, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpLsh32x64, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(16)
+ v2.AddArg2(v3, v4)
+ v5 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v6 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v6.AuxInt = int32ToAuxInt(int32(umagic16(c).m))
+ v5.AddArg2(v6, v3)
+ v1.AddArg2(v2, v5)
+ v7 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v7.AuxInt = int64ToAuxInt(16 + umagic16(c).s - 1)
+ v0.AddArg2(v1, v7)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpDiv32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Div32 (Const32 [c]) (Const32 [d]))
+ // cond: d != 0
+ // result: (Const32 [c/d])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c / d)
+ return true
+ }
+ // match: (Div32 n (Const32 [c]))
+ // cond: isNonNegative(n) && isPowerOfTwo32(c)
+ // result: (Rsh32Ux64 n (Const64 <typ.UInt64> [log32(c)]))
+ for {
+ n := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(isNonNegative(n) && isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpRsh32Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log32(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Div32 <t> n (Const32 [c]))
+ // cond: c < 0 && c != -1<<31
+ // result: (Neg32 (Div32 <t> n (Const32 <t> [-c])))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c < 0 && c != -1<<31) {
+ break
+ }
+ v.reset(OpNeg32)
+ v0 := b.NewValue0(v.Pos, OpDiv32, t)
+ v1 := b.NewValue0(v.Pos, OpConst32, t)
+ v1.AuxInt = int32ToAuxInt(-c)
+ v0.AddArg2(n, v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Div32 <t> x (Const32 [-1<<31]))
+ // result: (Rsh32Ux64 (And32 <t> x (Neg32 <t> x)) (Const64 <typ.UInt64> [31]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 || auxIntToInt32(v_1.AuxInt) != -1<<31 {
+ break
+ }
+ v.reset(OpRsh32Ux64)
+ v0 := b.NewValue0(v.Pos, OpAnd32, t)
+ v1 := b.NewValue0(v.Pos, OpNeg32, t)
+ v1.AddArg(x)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(31)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (Div32 <t> n (Const32 [c]))
+ // cond: isPowerOfTwo32(c)
+ // result: (Rsh32x64 (Add32 <t> n (Rsh32Ux64 <t> (Rsh32x64 <t> n (Const64 <typ.UInt64> [31])) (Const64 <typ.UInt64> [int64(32-log32(c))]))) (Const64 <typ.UInt64> [int64(log32(c))]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpRsh32x64)
+ v0 := b.NewValue0(v.Pos, OpAdd32, t)
+ v1 := b.NewValue0(v.Pos, OpRsh32Ux64, t)
+ v2 := b.NewValue0(v.Pos, OpRsh32x64, t)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(31)
+ v2.AddArg2(n, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(int64(32 - log32(c)))
+ v1.AddArg2(v2, v4)
+ v0.AddArg2(n, v1)
+ v5 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(int64(log32(c)))
+ v.AddArg2(v0, v5)
+ return true
+ }
+ // match: (Div32 <t> x (Const32 [c]))
+ // cond: smagicOK32(c) && config.RegSize == 8
+ // result: (Sub32 <t> (Rsh64x64 <t> (Mul64 <typ.UInt64> (Const64 <typ.UInt64> [int64(smagic32(c).m)]) (SignExt32to64 x)) (Const64 <typ.UInt64> [32+smagic32(c).s])) (Rsh64x64 <t> (SignExt32to64 x) (Const64 <typ.UInt64> [63])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(smagicOK32(c) && config.RegSize == 8) {
+ break
+ }
+ v.reset(OpSub32)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRsh64x64, t)
+ v1 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(smagic32(c).m))
+ v3 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+ v3.AddArg(x)
+ v1.AddArg2(v2, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(32 + smagic32(c).s)
+ v0.AddArg2(v1, v4)
+ v5 := b.NewValue0(v.Pos, OpRsh64x64, t)
+ v6 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v6.AuxInt = int64ToAuxInt(63)
+ v5.AddArg2(v3, v6)
+ v.AddArg2(v0, v5)
+ return true
+ }
+ // match: (Div32 <t> x (Const32 [c]))
+ // cond: smagicOK32(c) && config.RegSize == 4 && smagic32(c).m&1 == 0 && config.useHmul
+ // result: (Sub32 <t> (Rsh32x64 <t> (Hmul32 <t> (Const32 <typ.UInt32> [int32(smagic32(c).m/2)]) x) (Const64 <typ.UInt64> [smagic32(c).s-1])) (Rsh32x64 <t> x (Const64 <typ.UInt64> [31])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(smagicOK32(c) && config.RegSize == 4 && smagic32(c).m&1 == 0 && config.useHmul) {
+ break
+ }
+ v.reset(OpSub32)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRsh32x64, t)
+ v1 := b.NewValue0(v.Pos, OpHmul32, t)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(smagic32(c).m / 2))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(smagic32(c).s - 1)
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpRsh32x64, t)
+ v5 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(31)
+ v4.AddArg2(x, v5)
+ v.AddArg2(v0, v4)
+ return true
+ }
+ // match: (Div32 <t> x (Const32 [c]))
+ // cond: smagicOK32(c) && config.RegSize == 4 && smagic32(c).m&1 != 0 && config.useHmul
+ // result: (Sub32 <t> (Rsh32x64 <t> (Add32 <t> (Hmul32 <t> (Const32 <typ.UInt32> [int32(smagic32(c).m)]) x) x) (Const64 <typ.UInt64> [smagic32(c).s])) (Rsh32x64 <t> x (Const64 <typ.UInt64> [31])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(smagicOK32(c) && config.RegSize == 4 && smagic32(c).m&1 != 0 && config.useHmul) {
+ break
+ }
+ v.reset(OpSub32)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRsh32x64, t)
+ v1 := b.NewValue0(v.Pos, OpAdd32, t)
+ v2 := b.NewValue0(v.Pos, OpHmul32, t)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(int32(smagic32(c).m))
+ v2.AddArg2(v3, x)
+ v1.AddArg2(v2, x)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(smagic32(c).s)
+ v0.AddArg2(v1, v4)
+ v5 := b.NewValue0(v.Pos, OpRsh32x64, t)
+ v6 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v6.AuxInt = int64ToAuxInt(31)
+ v5.AddArg2(x, v6)
+ v.AddArg2(v0, v5)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpDiv32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Div32F (Const32F [c]) (Const32F [d]))
+ // cond: c/d == c/d
+ // result: (Const32F [c/d])
+ for {
+ if v_0.Op != OpConst32F {
+ break
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ if v_1.Op != OpConst32F {
+ break
+ }
+ d := auxIntToFloat32(v_1.AuxInt)
+ if !(c/d == c/d) {
+ break
+ }
+ v.reset(OpConst32F)
+ v.AuxInt = float32ToAuxInt(c / d)
+ return true
+ }
+ // match: (Div32F x (Const32F <t> [c]))
+ // cond: reciprocalExact32(c)
+ // result: (Mul32F x (Const32F <t> [1/c]))
+ for {
+ x := v_0
+ if v_1.Op != OpConst32F {
+ break
+ }
+ t := v_1.Type
+ c := auxIntToFloat32(v_1.AuxInt)
+ if !(reciprocalExact32(c)) {
+ break
+ }
+ v.reset(OpMul32F)
+ v0 := b.NewValue0(v.Pos, OpConst32F, t)
+ v0.AuxInt = float32ToAuxInt(1 / c)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpDiv32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Div32u (Const32 [c]) (Const32 [d]))
+ // cond: d != 0
+ // result: (Const32 [int32(uint32(c)/uint32(d))])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) / uint32(d)))
+ return true
+ }
+ // match: (Div32u n (Const32 [c]))
+ // cond: isPowerOfTwo32(c)
+ // result: (Rsh32Ux64 n (Const64 <typ.UInt64> [log32(c)]))
+ for {
+ n := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpRsh32Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log32(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Div32u x (Const32 [c]))
+ // cond: umagicOK32(c) && config.RegSize == 4 && umagic32(c).m&1 == 0 && config.useHmul
+ // result: (Rsh32Ux64 <typ.UInt32> (Hmul32u <typ.UInt32> (Const32 <typ.UInt32> [int32(1<<31+umagic32(c).m/2)]) x) (Const64 <typ.UInt64> [umagic32(c).s-1]))
+ for {
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(umagicOK32(c) && config.RegSize == 4 && umagic32(c).m&1 == 0 && config.useHmul) {
+ break
+ }
+ v.reset(OpRsh32Ux64)
+ v.Type = typ.UInt32
+ v0 := b.NewValue0(v.Pos, OpHmul32u, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(int32(1<<31 + umagic32(c).m/2))
+ v0.AddArg2(v1, x)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(umagic32(c).s - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (Div32u x (Const32 [c]))
+ // cond: umagicOK32(c) && config.RegSize == 4 && c&1 == 0 && config.useHmul
+ // result: (Rsh32Ux64 <typ.UInt32> (Hmul32u <typ.UInt32> (Const32 <typ.UInt32> [int32(1<<31+(umagic32(c).m+1)/2)]) (Rsh32Ux64 <typ.UInt32> x (Const64 <typ.UInt64> [1]))) (Const64 <typ.UInt64> [umagic32(c).s-2]))
+ for {
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(umagicOK32(c) && config.RegSize == 4 && c&1 == 0 && config.useHmul) {
+ break
+ }
+ v.reset(OpRsh32Ux64)
+ v.Type = typ.UInt32
+ v0 := b.NewValue0(v.Pos, OpHmul32u, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v1.AuxInt = int32ToAuxInt(int32(1<<31 + (umagic32(c).m+1)/2))
+ v2 := b.NewValue0(v.Pos, OpRsh32Ux64, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(1)
+ v2.AddArg2(x, v3)
+ v0.AddArg2(v1, v2)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(umagic32(c).s - 2)
+ v.AddArg2(v0, v4)
+ return true
+ }
+ // match: (Div32u x (Const32 [c]))
+ // cond: umagicOK32(c) && config.RegSize == 4 && config.useAvg && config.useHmul
+ // result: (Rsh32Ux64 <typ.UInt32> (Avg32u x (Hmul32u <typ.UInt32> (Const32 <typ.UInt32> [int32(umagic32(c).m)]) x)) (Const64 <typ.UInt64> [umagic32(c).s-1]))
+ for {
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(umagicOK32(c) && config.RegSize == 4 && config.useAvg && config.useHmul) {
+ break
+ }
+ v.reset(OpRsh32Ux64)
+ v.Type = typ.UInt32
+ v0 := b.NewValue0(v.Pos, OpAvg32u, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpHmul32u, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(umagic32(c).m))
+ v1.AddArg2(v2, x)
+ v0.AddArg2(x, v1)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(umagic32(c).s - 1)
+ v.AddArg2(v0, v3)
+ return true
+ }
+ // match: (Div32u x (Const32 [c]))
+ // cond: umagicOK32(c) && config.RegSize == 8 && umagic32(c).m&1 == 0
+ // result: (Trunc64to32 (Rsh64Ux64 <typ.UInt64> (Mul64 <typ.UInt64> (Const64 <typ.UInt64> [int64(1<<31+umagic32(c).m/2)]) (ZeroExt32to64 x)) (Const64 <typ.UInt64> [32+umagic32(c).s-1])))
+ for {
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(umagicOK32(c) && config.RegSize == 8 && umagic32(c).m&1 == 0) {
+ break
+ }
+ v.reset(OpTrunc64to32)
+ v0 := b.NewValue0(v.Pos, OpRsh64Ux64, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(1<<31 + umagic32(c).m/2))
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(x)
+ v1.AddArg2(v2, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(32 + umagic32(c).s - 1)
+ v0.AddArg2(v1, v4)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Div32u x (Const32 [c]))
+ // cond: umagicOK32(c) && config.RegSize == 8 && c&1 == 0
+ // result: (Trunc64to32 (Rsh64Ux64 <typ.UInt64> (Mul64 <typ.UInt64> (Const64 <typ.UInt64> [int64(1<<31+(umagic32(c).m+1)/2)]) (Rsh64Ux64 <typ.UInt64> (ZeroExt32to64 x) (Const64 <typ.UInt64> [1]))) (Const64 <typ.UInt64> [32+umagic32(c).s-2])))
+ for {
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(umagicOK32(c) && config.RegSize == 8 && c&1 == 0) {
+ break
+ }
+ v.reset(OpTrunc64to32)
+ v0 := b.NewValue0(v.Pos, OpRsh64Ux64, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(1<<31 + (umagic32(c).m+1)/2))
+ v3 := b.NewValue0(v.Pos, OpRsh64Ux64, typ.UInt64)
+ v4 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4.AddArg(x)
+ v5 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(1)
+ v3.AddArg2(v4, v5)
+ v1.AddArg2(v2, v3)
+ v6 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v6.AuxInt = int64ToAuxInt(32 + umagic32(c).s - 2)
+ v0.AddArg2(v1, v6)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Div32u x (Const32 [c]))
+ // cond: umagicOK32(c) && config.RegSize == 8 && config.useAvg
+ // result: (Trunc64to32 (Rsh64Ux64 <typ.UInt64> (Avg64u (Lsh64x64 <typ.UInt64> (ZeroExt32to64 x) (Const64 <typ.UInt64> [32])) (Mul64 <typ.UInt64> (Const64 <typ.UInt32> [int64(umagic32(c).m)]) (ZeroExt32to64 x))) (Const64 <typ.UInt64> [32+umagic32(c).s-1])))
+ for {
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(umagicOK32(c) && config.RegSize == 8 && config.useAvg) {
+ break
+ }
+ v.reset(OpTrunc64to32)
+ v0 := b.NewValue0(v.Pos, OpRsh64Ux64, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpAvg64u, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpLsh64x64, typ.UInt64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v3.AddArg(x)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(32)
+ v2.AddArg2(v3, v4)
+ v5 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v6 := b.NewValue0(v.Pos, OpConst64, typ.UInt32)
+ v6.AuxInt = int64ToAuxInt(int64(umagic32(c).m))
+ v5.AddArg2(v6, v3)
+ v1.AddArg2(v2, v5)
+ v7 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v7.AuxInt = int64ToAuxInt(32 + umagic32(c).s - 1)
+ v0.AddArg2(v1, v7)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpDiv64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Div64 (Const64 [c]) (Const64 [d]))
+ // cond: d != 0
+ // result: (Const64 [c/d])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c / d)
+ return true
+ }
+ // match: (Div64 n (Const64 [c]))
+ // cond: isNonNegative(n) && isPowerOfTwo64(c)
+ // result: (Rsh64Ux64 n (Const64 <typ.UInt64> [log64(c)]))
+ for {
+ n := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isNonNegative(n) && isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Div64 n (Const64 [-1<<63]))
+ // cond: isNonNegative(n)
+ // result: (Const64 [0])
+ for {
+ n := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != -1<<63 || !(isNonNegative(n)) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Div64 <t> n (Const64 [c]))
+ // cond: c < 0 && c != -1<<63
+ // result: (Neg64 (Div64 <t> n (Const64 <t> [-c])))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c < 0 && c != -1<<63) {
+ break
+ }
+ v.reset(OpNeg64)
+ v0 := b.NewValue0(v.Pos, OpDiv64, t)
+ v1 := b.NewValue0(v.Pos, OpConst64, t)
+ v1.AuxInt = int64ToAuxInt(-c)
+ v0.AddArg2(n, v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Div64 <t> x (Const64 [-1<<63]))
+ // result: (Rsh64Ux64 (And64 <t> x (Neg64 <t> x)) (Const64 <typ.UInt64> [63]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != -1<<63 {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Pos, OpAnd64, t)
+ v1 := b.NewValue0(v.Pos, OpNeg64, t)
+ v1.AddArg(x)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(63)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (Div64 <t> n (Const64 [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (Rsh64x64 (Add64 <t> n (Rsh64Ux64 <t> (Rsh64x64 <t> n (Const64 <typ.UInt64> [63])) (Const64 <typ.UInt64> [int64(64-log64(c))]))) (Const64 <typ.UInt64> [int64(log64(c))]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpRsh64x64)
+ v0 := b.NewValue0(v.Pos, OpAdd64, t)
+ v1 := b.NewValue0(v.Pos, OpRsh64Ux64, t)
+ v2 := b.NewValue0(v.Pos, OpRsh64x64, t)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(63)
+ v2.AddArg2(n, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(int64(64 - log64(c)))
+ v1.AddArg2(v2, v4)
+ v0.AddArg2(n, v1)
+ v5 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(int64(log64(c)))
+ v.AddArg2(v0, v5)
+ return true
+ }
+ // match: (Div64 <t> x (Const64 [c]))
+ // cond: smagicOK64(c) && smagic64(c).m&1 == 0 && config.useHmul
+ // result: (Sub64 <t> (Rsh64x64 <t> (Hmul64 <t> (Const64 <typ.UInt64> [int64(smagic64(c).m/2)]) x) (Const64 <typ.UInt64> [smagic64(c).s-1])) (Rsh64x64 <t> x (Const64 <typ.UInt64> [63])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(smagicOK64(c) && smagic64(c).m&1 == 0 && config.useHmul) {
+ break
+ }
+ v.reset(OpSub64)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRsh64x64, t)
+ v1 := b.NewValue0(v.Pos, OpHmul64, t)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(smagic64(c).m / 2))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(smagic64(c).s - 1)
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpRsh64x64, t)
+ v5 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(63)
+ v4.AddArg2(x, v5)
+ v.AddArg2(v0, v4)
+ return true
+ }
+ // match: (Div64 <t> x (Const64 [c]))
+ // cond: smagicOK64(c) && smagic64(c).m&1 != 0 && config.useHmul
+ // result: (Sub64 <t> (Rsh64x64 <t> (Add64 <t> (Hmul64 <t> (Const64 <typ.UInt64> [int64(smagic64(c).m)]) x) x) (Const64 <typ.UInt64> [smagic64(c).s])) (Rsh64x64 <t> x (Const64 <typ.UInt64> [63])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(smagicOK64(c) && smagic64(c).m&1 != 0 && config.useHmul) {
+ break
+ }
+ v.reset(OpSub64)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRsh64x64, t)
+ v1 := b.NewValue0(v.Pos, OpAdd64, t)
+ v2 := b.NewValue0(v.Pos, OpHmul64, t)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(int64(smagic64(c).m))
+ v2.AddArg2(v3, x)
+ v1.AddArg2(v2, x)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(smagic64(c).s)
+ v0.AddArg2(v1, v4)
+ v5 := b.NewValue0(v.Pos, OpRsh64x64, t)
+ v6 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v6.AuxInt = int64ToAuxInt(63)
+ v5.AddArg2(x, v6)
+ v.AddArg2(v0, v5)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpDiv64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Div64F (Const64F [c]) (Const64F [d]))
+ // cond: c/d == c/d
+ // result: (Const64F [c/d])
+ for {
+ if v_0.Op != OpConst64F {
+ break
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ if v_1.Op != OpConst64F {
+ break
+ }
+ d := auxIntToFloat64(v_1.AuxInt)
+ if !(c/d == c/d) {
+ break
+ }
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(c / d)
+ return true
+ }
+ // match: (Div64F x (Const64F <t> [c]))
+ // cond: reciprocalExact64(c)
+ // result: (Mul64F x (Const64F <t> [1/c]))
+ for {
+ x := v_0
+ if v_1.Op != OpConst64F {
+ break
+ }
+ t := v_1.Type
+ c := auxIntToFloat64(v_1.AuxInt)
+ if !(reciprocalExact64(c)) {
+ break
+ }
+ v.reset(OpMul64F)
+ v0 := b.NewValue0(v.Pos, OpConst64F, t)
+ v0.AuxInt = float64ToAuxInt(1 / c)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpDiv64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Div64u (Const64 [c]) (Const64 [d]))
+ // cond: d != 0
+ // result: (Const64 [int64(uint64(c)/uint64(d))])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d)))
+ return true
+ }
+ // match: (Div64u n (Const64 [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (Rsh64Ux64 n (Const64 <typ.UInt64> [log64(c)]))
+ for {
+ n := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Div64u n (Const64 [-1<<63]))
+ // result: (Rsh64Ux64 n (Const64 <typ.UInt64> [63]))
+ for {
+ n := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != -1<<63 {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(63)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Div64u x (Const64 [c]))
+ // cond: c > 0 && c <= 0xFFFF && umagicOK32(int32(c)) && config.RegSize == 4 && config.useHmul
+ // result: (Add64 (Add64 <typ.UInt64> (Add64 <typ.UInt64> (Lsh64x64 <typ.UInt64> (ZeroExt32to64 (Div32u <typ.UInt32> (Trunc64to32 <typ.UInt32> (Rsh64Ux64 <typ.UInt64> x (Const64 <typ.UInt64> [32]))) (Const32 <typ.UInt32> [int32(c)]))) (Const64 <typ.UInt64> [32])) (ZeroExt32to64 (Div32u <typ.UInt32> (Trunc64to32 <typ.UInt32> x) (Const32 <typ.UInt32> [int32(c)])))) (Mul64 <typ.UInt64> (ZeroExt32to64 <typ.UInt64> (Mod32u <typ.UInt32> (Trunc64to32 <typ.UInt32> (Rsh64Ux64 <typ.UInt64> x (Const64 <typ.UInt64> [32]))) (Const32 <typ.UInt32> [int32(c)]))) (Const64 <typ.UInt64> [int64((1<<32)/c)]))) (ZeroExt32to64 (Div32u <typ.UInt32> (Add32 <typ.UInt32> (Mod32u <typ.UInt32> (Trunc64to32 <typ.UInt32> x) (Const32 <typ.UInt32> [int32(c)])) (Mul32 <typ.UInt32> (Mod32u <typ.UInt32> (Trunc64to32 <typ.UInt32> (Rsh64Ux64 <typ.UInt64> x (Const64 <typ.UInt64> [32]))) (Const32 <typ.UInt32> [int32(c)])) (Const32 <typ.UInt32> [int32((1<<32)%c)]))) (Const32 <typ.UInt32> [int32(c)]))))
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c > 0 && c <= 0xFFFF && umagicOK32(int32(c)) && config.RegSize == 4 && config.useHmul) {
+ break
+ }
+ v.reset(OpAdd64)
+ v0 := b.NewValue0(v.Pos, OpAdd64, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpAdd64, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpLsh64x64, typ.UInt64)
+ v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v4 := b.NewValue0(v.Pos, OpDiv32u, typ.UInt32)
+ v5 := b.NewValue0(v.Pos, OpTrunc64to32, typ.UInt32)
+ v6 := b.NewValue0(v.Pos, OpRsh64Ux64, typ.UInt64)
+ v7 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v7.AuxInt = int64ToAuxInt(32)
+ v6.AddArg2(x, v7)
+ v5.AddArg(v6)
+ v8 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v8.AuxInt = int32ToAuxInt(int32(c))
+ v4.AddArg2(v5, v8)
+ v3.AddArg(v4)
+ v2.AddArg2(v3, v7)
+ v9 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v10 := b.NewValue0(v.Pos, OpDiv32u, typ.UInt32)
+ v11 := b.NewValue0(v.Pos, OpTrunc64to32, typ.UInt32)
+ v11.AddArg(x)
+ v10.AddArg2(v11, v8)
+ v9.AddArg(v10)
+ v1.AddArg2(v2, v9)
+ v12 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v13 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v14 := b.NewValue0(v.Pos, OpMod32u, typ.UInt32)
+ v14.AddArg2(v5, v8)
+ v13.AddArg(v14)
+ v15 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v15.AuxInt = int64ToAuxInt(int64((1 << 32) / c))
+ v12.AddArg2(v13, v15)
+ v0.AddArg2(v1, v12)
+ v16 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+ v17 := b.NewValue0(v.Pos, OpDiv32u, typ.UInt32)
+ v18 := b.NewValue0(v.Pos, OpAdd32, typ.UInt32)
+ v19 := b.NewValue0(v.Pos, OpMod32u, typ.UInt32)
+ v19.AddArg2(v11, v8)
+ v20 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v21 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v21.AuxInt = int32ToAuxInt(int32((1 << 32) % c))
+ v20.AddArg2(v14, v21)
+ v18.AddArg2(v19, v20)
+ v17.AddArg2(v18, v8)
+ v16.AddArg(v17)
+ v.AddArg2(v0, v16)
+ return true
+ }
+ // match: (Div64u x (Const64 [c]))
+ // cond: umagicOK64(c) && config.RegSize == 8 && umagic64(c).m&1 == 0 && config.useHmul
+ // result: (Rsh64Ux64 <typ.UInt64> (Hmul64u <typ.UInt64> (Const64 <typ.UInt64> [int64(1<<63+umagic64(c).m/2)]) x) (Const64 <typ.UInt64> [umagic64(c).s-1]))
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(umagicOK64(c) && config.RegSize == 8 && umagic64(c).m&1 == 0 && config.useHmul) {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpHmul64u, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(int64(1<<63 + umagic64(c).m/2))
+ v0.AddArg2(v1, x)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(umagic64(c).s - 1)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (Div64u x (Const64 [c]))
+ // cond: umagicOK64(c) && config.RegSize == 8 && c&1 == 0 && config.useHmul
+ // result: (Rsh64Ux64 <typ.UInt64> (Hmul64u <typ.UInt64> (Const64 <typ.UInt64> [int64(1<<63+(umagic64(c).m+1)/2)]) (Rsh64Ux64 <typ.UInt64> x (Const64 <typ.UInt64> [1]))) (Const64 <typ.UInt64> [umagic64(c).s-2]))
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(umagicOK64(c) && config.RegSize == 8 && c&1 == 0 && config.useHmul) {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpHmul64u, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(int64(1<<63 + (umagic64(c).m+1)/2))
+ v2 := b.NewValue0(v.Pos, OpRsh64Ux64, typ.UInt64)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(1)
+ v2.AddArg2(x, v3)
+ v0.AddArg2(v1, v2)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(umagic64(c).s - 2)
+ v.AddArg2(v0, v4)
+ return true
+ }
+ // match: (Div64u x (Const64 [c]))
+ // cond: umagicOK64(c) && config.RegSize == 8 && config.useAvg && config.useHmul
+ // result: (Rsh64Ux64 <typ.UInt64> (Avg64u x (Hmul64u <typ.UInt64> (Const64 <typ.UInt64> [int64(umagic64(c).m)]) x)) (Const64 <typ.UInt64> [umagic64(c).s-1]))
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(umagicOK64(c) && config.RegSize == 8 && config.useAvg && config.useHmul) {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v.Type = typ.UInt64
+ v0 := b.NewValue0(v.Pos, OpAvg64u, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpHmul64u, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(umagic64(c).m))
+ v1.AddArg2(v2, x)
+ v0.AddArg2(x, v1)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(umagic64(c).s - 1)
+ v.AddArg2(v0, v3)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpDiv8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8 (Const8 [c]) (Const8 [d]))
+ // cond: d != 0
+ // result: (Const8 [c/d])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ break
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c / d)
+ return true
+ }
+ // match: (Div8 n (Const8 [c]))
+ // cond: isNonNegative(n) && isPowerOfTwo8(c)
+ // result: (Rsh8Ux64 n (Const64 <typ.UInt64> [log8(c)]))
+ for {
+ n := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(isNonNegative(n) && isPowerOfTwo8(c)) {
+ break
+ }
+ v.reset(OpRsh8Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log8(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Div8 <t> n (Const8 [c]))
+ // cond: c < 0 && c != -1<<7
+ // result: (Neg8 (Div8 <t> n (Const8 <t> [-c])))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(c < 0 && c != -1<<7) {
+ break
+ }
+ v.reset(OpNeg8)
+ v0 := b.NewValue0(v.Pos, OpDiv8, t)
+ v1 := b.NewValue0(v.Pos, OpConst8, t)
+ v1.AuxInt = int8ToAuxInt(-c)
+ v0.AddArg2(n, v1)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Div8 <t> x (Const8 [-1<<7 ]))
+ // result: (Rsh8Ux64 (And8 <t> x (Neg8 <t> x)) (Const64 <typ.UInt64> [7 ]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 || auxIntToInt8(v_1.AuxInt) != -1<<7 {
+ break
+ }
+ v.reset(OpRsh8Ux64)
+ v0 := b.NewValue0(v.Pos, OpAnd8, t)
+ v1 := b.NewValue0(v.Pos, OpNeg8, t)
+ v1.AddArg(x)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(7)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (Div8 <t> n (Const8 [c]))
+ // cond: isPowerOfTwo8(c)
+ // result: (Rsh8x64 (Add8 <t> n (Rsh8Ux64 <t> (Rsh8x64 <t> n (Const64 <typ.UInt64> [ 7])) (Const64 <typ.UInt64> [int64( 8-log8(c))]))) (Const64 <typ.UInt64> [int64(log8(c))]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(isPowerOfTwo8(c)) {
+ break
+ }
+ v.reset(OpRsh8x64)
+ v0 := b.NewValue0(v.Pos, OpAdd8, t)
+ v1 := b.NewValue0(v.Pos, OpRsh8Ux64, t)
+ v2 := b.NewValue0(v.Pos, OpRsh8x64, t)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(7)
+ v2.AddArg2(n, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(int64(8 - log8(c)))
+ v1.AddArg2(v2, v4)
+ v0.AddArg2(n, v1)
+ v5 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(int64(log8(c)))
+ v.AddArg2(v0, v5)
+ return true
+ }
+ // match: (Div8 <t> x (Const8 [c]))
+ // cond: smagicOK8(c)
+ // result: (Sub8 <t> (Rsh32x64 <t> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(smagic8(c).m)]) (SignExt8to32 x)) (Const64 <typ.UInt64> [8+smagic8(c).s])) (Rsh32x64 <t> (SignExt8to32 x) (Const64 <typ.UInt64> [31])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(smagicOK8(c)) {
+ break
+ }
+ v.reset(OpSub8)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpRsh32x64, t)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(smagic8(c).m))
+ v3 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v3.AddArg(x)
+ v1.AddArg2(v2, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(8 + smagic8(c).s)
+ v0.AddArg2(v1, v4)
+ v5 := b.NewValue0(v.Pos, OpRsh32x64, t)
+ v6 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v6.AuxInt = int64ToAuxInt(31)
+ v5.AddArg2(v3, v6)
+ v.AddArg2(v0, v5)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpDiv8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Div8u (Const8 [c]) (Const8 [d]))
+ // cond: d != 0
+ // result: (Const8 [int8(uint8(c)/uint8(d))])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ break
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(int8(uint8(c) / uint8(d)))
+ return true
+ }
+ // match: (Div8u n (Const8 [c]))
+ // cond: isPowerOfTwo8(c)
+ // result: (Rsh8Ux64 n (Const64 <typ.UInt64> [log8(c)]))
+ for {
+ n := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(isPowerOfTwo8(c)) {
+ break
+ }
+ v.reset(OpRsh8Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log8(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Div8u x (Const8 [c]))
+ // cond: umagicOK8(c)
+ // result: (Trunc32to8 (Rsh32Ux64 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(1<<8+umagic8(c).m)]) (ZeroExt8to32 x)) (Const64 <typ.UInt64> [8+umagic8(c).s])))
+ for {
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(umagicOK8(c)) {
+ break
+ }
+ v.reset(OpTrunc32to8)
+ v0 := b.NewValue0(v.Pos, OpRsh32Ux64, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(1<<8 + umagic8(c).m))
+ v3 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v3.AddArg(x)
+ v1.AddArg2(v2, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(8 + umagic8(c).s)
+ v0.AddArg2(v1, v4)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpEq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Eq16 x x)
+ // result: (ConstBool [true])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (Eq16 (Const16 <t> [c]) (Add16 (Const16 <t> [d]) x))
+ // result: (Eq16 (Const16 <t> [c-d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpAdd16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt16(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpEq16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Eq16 (Const16 [c]) (Const16 [d]))
+ // result: (ConstBool [c == d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c == d)
+ return true
+ }
+ break
+ }
+ // match: (Eq16 (Mod16u x (Const16 [c])) (Const16 [0]))
+ // cond: x.Op != OpConst16 && udivisibleOK16(c) && !hasSmallRotate(config)
+ // result: (Eq32 (Mod32u <typ.UInt32> (ZeroExt16to32 <typ.UInt32> x) (Const32 <typ.UInt32> [int32(uint16(c))])) (Const32 <typ.UInt32> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMod16u {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_1.AuxInt)
+ if v_1.Op != OpConst16 || auxIntToInt16(v_1.AuxInt) != 0 || !(x.Op != OpConst16 && udivisibleOK16(c) && !hasSmallRotate(config)) {
+ continue
+ }
+ v.reset(OpEq32)
+ v0 := b.NewValue0(v.Pos, OpMod32u, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(uint16(c)))
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v3)
+ return true
+ }
+ break
+ }
+ // match: (Eq16 (Mod16 x (Const16 [c])) (Const16 [0]))
+ // cond: x.Op != OpConst16 && sdivisibleOK16(c) && !hasSmallRotate(config)
+ // result: (Eq32 (Mod32 <typ.Int32> (SignExt16to32 <typ.Int32> x) (Const32 <typ.Int32> [int32(c)])) (Const32 <typ.Int32> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMod16 {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_1.AuxInt)
+ if v_1.Op != OpConst16 || auxIntToInt16(v_1.AuxInt) != 0 || !(x.Op != OpConst16 && sdivisibleOK16(c) && !hasSmallRotate(config)) {
+ continue
+ }
+ v.reset(OpEq32)
+ v0 := b.NewValue0(v.Pos, OpMod32, typ.Int32)
+ v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.Int32)
+ v2.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.Int32)
+ v3.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v3)
+ return true
+ }
+ break
+ }
+ // match: (Eq16 x (Mul16 (Const16 [c]) (Trunc64to16 (Rsh64Ux64 mul:(Mul64 (Const64 [m]) (ZeroExt16to64 x)) (Const64 [s]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(1<<16+umagic16(c).m) && s == 16+umagic16(c).s && x.Op != OpConst16 && udivisibleOK16(c)
+ // result: (Leq16U (RotateLeft16 <typ.UInt16> (Mul16 <typ.UInt16> (Const16 <typ.UInt16> [int16(udivisible16(c).m)]) x) (Const16 <typ.UInt16> [int16(16-udivisible16(c).k)]) ) (Const16 <typ.UInt16> [int16(udivisible16(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_1_0.AuxInt)
+ if v_1_1.Op != OpTrunc64to16 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh64Ux64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpMul64 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(mul_0.AuxInt)
+ if mul_1.Op != OpZeroExt16to64 || x != mul_1.Args[0] {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(1<<16+umagic16(c).m) && s == 16+umagic16(c).s && x.Op != OpConst16 && udivisibleOK16(c)) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft16, typ.UInt16)
+ v1 := b.NewValue0(v.Pos, OpMul16, typ.UInt16)
+ v2 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v2.AuxInt = int16ToAuxInt(int16(udivisible16(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v3.AuxInt = int16ToAuxInt(int16(16 - udivisible16(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v4.AuxInt = int16ToAuxInt(int16(udivisible16(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq16 x (Mul16 (Const16 [c]) (Trunc32to16 (Rsh32Ux64 mul:(Mul32 (Const32 [m]) (ZeroExt16to32 x)) (Const64 [s]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(1<<15+umagic16(c).m/2) && s == 16+umagic16(c).s-1 && x.Op != OpConst16 && udivisibleOK16(c)
+ // result: (Leq16U (RotateLeft16 <typ.UInt16> (Mul16 <typ.UInt16> (Const16 <typ.UInt16> [int16(udivisible16(c).m)]) x) (Const16 <typ.UInt16> [int16(16-udivisible16(c).k)]) ) (Const16 <typ.UInt16> [int16(udivisible16(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_1_0.AuxInt)
+ if v_1_1.Op != OpTrunc32to16 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh32Ux64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpMul32 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if mul_1.Op != OpZeroExt16to32 || x != mul_1.Args[0] {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(1<<15+umagic16(c).m/2) && s == 16+umagic16(c).s-1 && x.Op != OpConst16 && udivisibleOK16(c)) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft16, typ.UInt16)
+ v1 := b.NewValue0(v.Pos, OpMul16, typ.UInt16)
+ v2 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v2.AuxInt = int16ToAuxInt(int16(udivisible16(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v3.AuxInt = int16ToAuxInt(int16(16 - udivisible16(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v4.AuxInt = int16ToAuxInt(int16(udivisible16(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq16 x (Mul16 (Const16 [c]) (Trunc32to16 (Rsh32Ux64 mul:(Mul32 (Const32 [m]) (Rsh32Ux64 (ZeroExt16to32 x) (Const64 [1]))) (Const64 [s]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(1<<15+(umagic16(c).m+1)/2) && s == 16+umagic16(c).s-2 && x.Op != OpConst16 && udivisibleOK16(c)
+ // result: (Leq16U (RotateLeft16 <typ.UInt16> (Mul16 <typ.UInt16> (Const16 <typ.UInt16> [int16(udivisible16(c).m)]) x) (Const16 <typ.UInt16> [int16(16-udivisible16(c).k)]) ) (Const16 <typ.UInt16> [int16(udivisible16(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_1_0.AuxInt)
+ if v_1_1.Op != OpTrunc32to16 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh32Ux64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpMul32 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if mul_1.Op != OpRsh32Ux64 {
+ continue
+ }
+ _ = mul_1.Args[1]
+ mul_1_0 := mul_1.Args[0]
+ if mul_1_0.Op != OpZeroExt16to32 || x != mul_1_0.Args[0] {
+ continue
+ }
+ mul_1_1 := mul_1.Args[1]
+ if mul_1_1.Op != OpConst64 || auxIntToInt64(mul_1_1.AuxInt) != 1 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(1<<15+(umagic16(c).m+1)/2) && s == 16+umagic16(c).s-2 && x.Op != OpConst16 && udivisibleOK16(c)) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft16, typ.UInt16)
+ v1 := b.NewValue0(v.Pos, OpMul16, typ.UInt16)
+ v2 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v2.AuxInt = int16ToAuxInt(int16(udivisible16(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v3.AuxInt = int16ToAuxInt(int16(16 - udivisible16(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v4.AuxInt = int16ToAuxInt(int16(udivisible16(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq16 x (Mul16 (Const16 [c]) (Trunc32to16 (Rsh32Ux64 (Avg32u (Lsh32x64 (ZeroExt16to32 x) (Const64 [16])) mul:(Mul32 (Const32 [m]) (ZeroExt16to32 x))) (Const64 [s]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(umagic16(c).m) && s == 16+umagic16(c).s-1 && x.Op != OpConst16 && udivisibleOK16(c)
+ // result: (Leq16U (RotateLeft16 <typ.UInt16> (Mul16 <typ.UInt16> (Const16 <typ.UInt16> [int16(udivisible16(c).m)]) x) (Const16 <typ.UInt16> [int16(16-udivisible16(c).k)]) ) (Const16 <typ.UInt16> [int16(udivisible16(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_1_0.AuxInt)
+ if v_1_1.Op != OpTrunc32to16 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh32Ux64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAvg32u {
+ continue
+ }
+ _ = v_1_1_0_0.Args[1]
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpLsh32x64 {
+ continue
+ }
+ _ = v_1_1_0_0_0.Args[1]
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpZeroExt16to32 || x != v_1_1_0_0_0_0.Args[0] {
+ continue
+ }
+ v_1_1_0_0_0_1 := v_1_1_0_0_0.Args[1]
+ if v_1_1_0_0_0_1.Op != OpConst64 || auxIntToInt64(v_1_1_0_0_0_1.AuxInt) != 16 {
+ continue
+ }
+ mul := v_1_1_0_0.Args[1]
+ if mul.Op != OpMul32 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if mul_1.Op != OpZeroExt16to32 || x != mul_1.Args[0] {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(umagic16(c).m) && s == 16+umagic16(c).s-1 && x.Op != OpConst16 && udivisibleOK16(c)) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft16, typ.UInt16)
+ v1 := b.NewValue0(v.Pos, OpMul16, typ.UInt16)
+ v2 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v2.AuxInt = int16ToAuxInt(int16(udivisible16(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v3.AuxInt = int16ToAuxInt(int16(16 - udivisible16(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v4.AuxInt = int16ToAuxInt(int16(udivisible16(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq16 x (Mul16 (Const16 [c]) (Sub16 (Rsh32x64 mul:(Mul32 (Const32 [m]) (SignExt16to32 x)) (Const64 [s])) (Rsh32x64 (SignExt16to32 x) (Const64 [31]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(smagic16(c).m) && s == 16+smagic16(c).s && x.Op != OpConst16 && sdivisibleOK16(c)
+ // result: (Leq16U (RotateLeft16 <typ.UInt16> (Add16 <typ.UInt16> (Mul16 <typ.UInt16> (Const16 <typ.UInt16> [int16(sdivisible16(c).m)]) x) (Const16 <typ.UInt16> [int16(sdivisible16(c).a)]) ) (Const16 <typ.UInt16> [int16(16-sdivisible16(c).k)]) ) (Const16 <typ.UInt16> [int16(sdivisible16(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_1_0.AuxInt)
+ if v_1_1.Op != OpSub16 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh32x64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpMul32 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if mul_1.Op != OpSignExt16to32 || x != mul_1.Args[0] {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpRsh32x64 {
+ continue
+ }
+ _ = v_1_1_1.Args[1]
+ v_1_1_1_0 := v_1_1_1.Args[0]
+ if v_1_1_1_0.Op != OpSignExt16to32 || x != v_1_1_1_0.Args[0] {
+ continue
+ }
+ v_1_1_1_1 := v_1_1_1.Args[1]
+ if v_1_1_1_1.Op != OpConst64 || auxIntToInt64(v_1_1_1_1.AuxInt) != 31 || !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(smagic16(c).m) && s == 16+smagic16(c).s && x.Op != OpConst16 && sdivisibleOK16(c)) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft16, typ.UInt16)
+ v1 := b.NewValue0(v.Pos, OpAdd16, typ.UInt16)
+ v2 := b.NewValue0(v.Pos, OpMul16, typ.UInt16)
+ v3 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v3.AuxInt = int16ToAuxInt(int16(sdivisible16(c).m))
+ v2.AddArg2(v3, x)
+ v4 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v4.AuxInt = int16ToAuxInt(int16(sdivisible16(c).a))
+ v1.AddArg2(v2, v4)
+ v5 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v5.AuxInt = int16ToAuxInt(int16(16 - sdivisible16(c).k))
+ v0.AddArg2(v1, v5)
+ v6 := b.NewValue0(v.Pos, OpConst16, typ.UInt16)
+ v6.AuxInt = int16ToAuxInt(int16(sdivisible16(c).max))
+ v.AddArg2(v0, v6)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq16 n (Lsh16x64 (Rsh16x64 (Add16 <t> n (Rsh16Ux64 <t> (Rsh16x64 <t> n (Const64 <typ.UInt64> [15])) (Const64 <typ.UInt64> [kbar]))) (Const64 <typ.UInt64> [k])) (Const64 <typ.UInt64> [k])) )
+ // cond: k > 0 && k < 15 && kbar == 16 - k
+ // result: (Eq16 (And16 <t> n (Const16 <t> [1<<uint(k)-1])) (Const16 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpLsh16x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpRsh16x64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAdd16 {
+ continue
+ }
+ t := v_1_0_0.Type
+ _ = v_1_0_0.Args[1]
+ v_1_0_0_0 := v_1_0_0.Args[0]
+ v_1_0_0_1 := v_1_0_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0_0_0, v_1_0_0_1 = _i1+1, v_1_0_0_1, v_1_0_0_0 {
+ if n != v_1_0_0_0 || v_1_0_0_1.Op != OpRsh16Ux64 || v_1_0_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1.Args[1]
+ v_1_0_0_1_0 := v_1_0_0_1.Args[0]
+ if v_1_0_0_1_0.Op != OpRsh16x64 || v_1_0_0_1_0.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1_0.Args[1]
+ if n != v_1_0_0_1_0.Args[0] {
+ continue
+ }
+ v_1_0_0_1_0_1 := v_1_0_0_1_0.Args[1]
+ if v_1_0_0_1_0_1.Op != OpConst64 || v_1_0_0_1_0_1.Type != typ.UInt64 || auxIntToInt64(v_1_0_0_1_0_1.AuxInt) != 15 {
+ continue
+ }
+ v_1_0_0_1_1 := v_1_0_0_1.Args[1]
+ if v_1_0_0_1_1.Op != OpConst64 || v_1_0_0_1_1.Type != typ.UInt64 {
+ continue
+ }
+ kbar := auxIntToInt64(v_1_0_0_1_1.AuxInt)
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpConst64 || v_1_0_1.Type != typ.UInt64 {
+ continue
+ }
+ k := auxIntToInt64(v_1_0_1.AuxInt)
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 || v_1_1.Type != typ.UInt64 || auxIntToInt64(v_1_1.AuxInt) != k || !(k > 0 && k < 15 && kbar == 16-k) {
+ continue
+ }
+ v.reset(OpEq16)
+ v0 := b.NewValue0(v.Pos, OpAnd16, t)
+ v1 := b.NewValue0(v.Pos, OpConst16, t)
+ v1.AuxInt = int16ToAuxInt(1<<uint(k) - 1)
+ v0.AddArg2(n, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, t)
+ v2.AuxInt = int16ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Eq16 s:(Sub16 x y) (Const16 [0]))
+ // cond: s.Uses == 1
+ // result: (Eq16 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s := v_0
+ if s.Op != OpSub16 {
+ continue
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ if v_1.Op != OpConst16 || auxIntToInt16(v_1.AuxInt) != 0 || !(s.Uses == 1) {
+ continue
+ }
+ v.reset(OpEq16)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y]))
+ // cond: oneBit16(y)
+ // result: (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd16 {
+ continue
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst16 || v_0_1.Type != t {
+ continue
+ }
+ y := auxIntToInt16(v_0_1.AuxInt)
+ if v_1.Op != OpConst16 || v_1.Type != t || auxIntToInt16(v_1.AuxInt) != y || !(oneBit16(y)) {
+ continue
+ }
+ v.reset(OpNeq16)
+ v0 := b.NewValue0(v.Pos, OpAnd16, t)
+ v1 := b.NewValue0(v.Pos, OpConst16, t)
+ v1.AuxInt = int16ToAuxInt(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, t)
+ v2.AuxInt = int16ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpEq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq32 x x)
+ // result: (ConstBool [true])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (Eq32 (Const32 <t> [c]) (Add32 (Const32 <t> [d]) x))
+ // result: (Eq32 (Const32 <t> [c-d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpAdd32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpEq32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Eq32 (Const32 [c]) (Const32 [d]))
+ // result: (ConstBool [c == d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c == d)
+ return true
+ }
+ break
+ }
+ // match: (Eq32 x (Mul32 (Const32 [c]) (Rsh32Ux64 mul:(Hmul32u (Const32 [m]) x) (Const64 [s])) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(1<<31+umagic32(c).m/2) && s == umagic32(c).s-1 && x.Op != OpConst32 && udivisibleOK32(c)
+ // result: (Leq32U (RotateLeft32 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(udivisible32(c).m)]) x) (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)]) ) (Const32 <typ.UInt32> [int32(udivisible32(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if v_1_1.Op != OpRsh32Ux64 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ mul := v_1_1.Args[0]
+ if mul.Op != OpHmul32u {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if x != mul_1 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(1<<31+umagic32(c).m/2) && s == umagic32(c).s-1 && x.Op != OpConst32 && udivisibleOK32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(udivisible32(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(int32(32 - udivisible32(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(int32(udivisible32(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq32 x (Mul32 (Const32 [c]) (Rsh32Ux64 mul:(Hmul32u (Const32 <typ.UInt32> [m]) (Rsh32Ux64 x (Const64 [1]))) (Const64 [s])) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(1<<31+(umagic32(c).m+1)/2) && s == umagic32(c).s-2 && x.Op != OpConst32 && udivisibleOK32(c)
+ // result: (Leq32U (RotateLeft32 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(udivisible32(c).m)]) x) (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)]) ) (Const32 <typ.UInt32> [int32(udivisible32(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if v_1_1.Op != OpRsh32Ux64 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ mul := v_1_1.Args[0]
+ if mul.Op != OpHmul32u {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 || mul_0.Type != typ.UInt32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if mul_1.Op != OpRsh32Ux64 {
+ continue
+ }
+ _ = mul_1.Args[1]
+ if x != mul_1.Args[0] {
+ continue
+ }
+ mul_1_1 := mul_1.Args[1]
+ if mul_1_1.Op != OpConst64 || auxIntToInt64(mul_1_1.AuxInt) != 1 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(1<<31+(umagic32(c).m+1)/2) && s == umagic32(c).s-2 && x.Op != OpConst32 && udivisibleOK32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(udivisible32(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(int32(32 - udivisible32(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(int32(udivisible32(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq32 x (Mul32 (Const32 [c]) (Rsh32Ux64 (Avg32u x mul:(Hmul32u (Const32 [m]) x)) (Const64 [s])) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(umagic32(c).m) && s == umagic32(c).s-1 && x.Op != OpConst32 && udivisibleOK32(c)
+ // result: (Leq32U (RotateLeft32 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(udivisible32(c).m)]) x) (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)]) ) (Const32 <typ.UInt32> [int32(udivisible32(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if v_1_1.Op != OpRsh32Ux64 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAvg32u {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ if x != v_1_1_0.Args[0] {
+ continue
+ }
+ mul := v_1_1_0.Args[1]
+ if mul.Op != OpHmul32u {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if x != mul_1 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(umagic32(c).m) && s == umagic32(c).s-1 && x.Op != OpConst32 && udivisibleOK32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(udivisible32(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(int32(32 - udivisible32(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(int32(udivisible32(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq32 x (Mul32 (Const32 [c]) (Trunc64to32 (Rsh64Ux64 mul:(Mul64 (Const64 [m]) (ZeroExt32to64 x)) (Const64 [s]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(1<<31+umagic32(c).m/2) && s == 32+umagic32(c).s-1 && x.Op != OpConst32 && udivisibleOK32(c)
+ // result: (Leq32U (RotateLeft32 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(udivisible32(c).m)]) x) (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)]) ) (Const32 <typ.UInt32> [int32(udivisible32(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if v_1_1.Op != OpTrunc64to32 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh64Ux64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpMul64 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(mul_0.AuxInt)
+ if mul_1.Op != OpZeroExt32to64 || x != mul_1.Args[0] {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(1<<31+umagic32(c).m/2) && s == 32+umagic32(c).s-1 && x.Op != OpConst32 && udivisibleOK32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(udivisible32(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(int32(32 - udivisible32(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(int32(udivisible32(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq32 x (Mul32 (Const32 [c]) (Trunc64to32 (Rsh64Ux64 mul:(Mul64 (Const64 [m]) (Rsh64Ux64 (ZeroExt32to64 x) (Const64 [1]))) (Const64 [s]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(1<<31+(umagic32(c).m+1)/2) && s == 32+umagic32(c).s-2 && x.Op != OpConst32 && udivisibleOK32(c)
+ // result: (Leq32U (RotateLeft32 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(udivisible32(c).m)]) x) (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)]) ) (Const32 <typ.UInt32> [int32(udivisible32(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if v_1_1.Op != OpTrunc64to32 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh64Ux64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpMul64 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(mul_0.AuxInt)
+ if mul_1.Op != OpRsh64Ux64 {
+ continue
+ }
+ _ = mul_1.Args[1]
+ mul_1_0 := mul_1.Args[0]
+ if mul_1_0.Op != OpZeroExt32to64 || x != mul_1_0.Args[0] {
+ continue
+ }
+ mul_1_1 := mul_1.Args[1]
+ if mul_1_1.Op != OpConst64 || auxIntToInt64(mul_1_1.AuxInt) != 1 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(1<<31+(umagic32(c).m+1)/2) && s == 32+umagic32(c).s-2 && x.Op != OpConst32 && udivisibleOK32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(udivisible32(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(int32(32 - udivisible32(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(int32(udivisible32(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq32 x (Mul32 (Const32 [c]) (Trunc64to32 (Rsh64Ux64 (Avg64u (Lsh64x64 (ZeroExt32to64 x) (Const64 [32])) mul:(Mul64 (Const64 [m]) (ZeroExt32to64 x))) (Const64 [s]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(umagic32(c).m) && s == 32+umagic32(c).s-1 && x.Op != OpConst32 && udivisibleOK32(c)
+ // result: (Leq32U (RotateLeft32 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(udivisible32(c).m)]) x) (Const32 <typ.UInt32> [int32(32-udivisible32(c).k)]) ) (Const32 <typ.UInt32> [int32(udivisible32(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if v_1_1.Op != OpTrunc64to32 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh64Ux64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAvg64u {
+ continue
+ }
+ _ = v_1_1_0_0.Args[1]
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ if v_1_1_0_0_0.Op != OpLsh64x64 {
+ continue
+ }
+ _ = v_1_1_0_0_0.Args[1]
+ v_1_1_0_0_0_0 := v_1_1_0_0_0.Args[0]
+ if v_1_1_0_0_0_0.Op != OpZeroExt32to64 || x != v_1_1_0_0_0_0.Args[0] {
+ continue
+ }
+ v_1_1_0_0_0_1 := v_1_1_0_0_0.Args[1]
+ if v_1_1_0_0_0_1.Op != OpConst64 || auxIntToInt64(v_1_1_0_0_0_1.AuxInt) != 32 {
+ continue
+ }
+ mul := v_1_1_0_0.Args[1]
+ if mul.Op != OpMul64 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(mul_0.AuxInt)
+ if mul_1.Op != OpZeroExt32to64 || x != mul_1.Args[0] {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(umagic32(c).m) && s == 32+umagic32(c).s-1 && x.Op != OpConst32 && udivisibleOK32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(udivisible32(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(int32(32 - udivisible32(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(int32(udivisible32(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq32 x (Mul32 (Const32 [c]) (Sub32 (Rsh64x64 mul:(Mul64 (Const64 [m]) (SignExt32to64 x)) (Const64 [s])) (Rsh64x64 (SignExt32to64 x) (Const64 [63]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(smagic32(c).m) && s == 32+smagic32(c).s && x.Op != OpConst32 && sdivisibleOK32(c)
+ // result: (Leq32U (RotateLeft32 <typ.UInt32> (Add32 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(sdivisible32(c).m)]) x) (Const32 <typ.UInt32> [int32(sdivisible32(c).a)]) ) (Const32 <typ.UInt32> [int32(32-sdivisible32(c).k)]) ) (Const32 <typ.UInt32> [int32(sdivisible32(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if v_1_1.Op != OpSub32 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh64x64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpMul64 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(mul_0.AuxInt)
+ if mul_1.Op != OpSignExt32to64 || x != mul_1.Args[0] {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpRsh64x64 {
+ continue
+ }
+ _ = v_1_1_1.Args[1]
+ v_1_1_1_0 := v_1_1_1.Args[0]
+ if v_1_1_1_0.Op != OpSignExt32to64 || x != v_1_1_1_0.Args[0] {
+ continue
+ }
+ v_1_1_1_1 := v_1_1_1.Args[1]
+ if v_1_1_1_1.Op != OpConst64 || auxIntToInt64(v_1_1_1_1.AuxInt) != 63 || !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(smagic32(c).m) && s == 32+smagic32(c).s && x.Op != OpConst32 && sdivisibleOK32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpAdd32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(int32(sdivisible32(c).m))
+ v2.AddArg2(v3, x)
+ v4 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(int32(sdivisible32(c).a))
+ v1.AddArg2(v2, v4)
+ v5 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v5.AuxInt = int32ToAuxInt(int32(32 - sdivisible32(c).k))
+ v0.AddArg2(v1, v5)
+ v6 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v6.AuxInt = int32ToAuxInt(int32(sdivisible32(c).max))
+ v.AddArg2(v0, v6)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq32 x (Mul32 (Const32 [c]) (Sub32 (Rsh32x64 mul:(Hmul32 (Const32 [m]) x) (Const64 [s])) (Rsh32x64 x (Const64 [31]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(smagic32(c).m/2) && s == smagic32(c).s-1 && x.Op != OpConst32 && sdivisibleOK32(c)
+ // result: (Leq32U (RotateLeft32 <typ.UInt32> (Add32 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(sdivisible32(c).m)]) x) (Const32 <typ.UInt32> [int32(sdivisible32(c).a)]) ) (Const32 <typ.UInt32> [int32(32-sdivisible32(c).k)]) ) (Const32 <typ.UInt32> [int32(sdivisible32(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if v_1_1.Op != OpSub32 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh32x64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpHmul32 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if x != mul_1 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpRsh32x64 {
+ continue
+ }
+ _ = v_1_1_1.Args[1]
+ if x != v_1_1_1.Args[0] {
+ continue
+ }
+ v_1_1_1_1 := v_1_1_1.Args[1]
+ if v_1_1_1_1.Op != OpConst64 || auxIntToInt64(v_1_1_1_1.AuxInt) != 31 || !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(smagic32(c).m/2) && s == smagic32(c).s-1 && x.Op != OpConst32 && sdivisibleOK32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpAdd32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(int32(sdivisible32(c).m))
+ v2.AddArg2(v3, x)
+ v4 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(int32(sdivisible32(c).a))
+ v1.AddArg2(v2, v4)
+ v5 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v5.AuxInt = int32ToAuxInt(int32(32 - sdivisible32(c).k))
+ v0.AddArg2(v1, v5)
+ v6 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v6.AuxInt = int32ToAuxInt(int32(sdivisible32(c).max))
+ v.AddArg2(v0, v6)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq32 x (Mul32 (Const32 [c]) (Sub32 (Rsh32x64 (Add32 mul:(Hmul32 (Const32 [m]) x) x) (Const64 [s])) (Rsh32x64 x (Const64 [31]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(smagic32(c).m) && s == smagic32(c).s && x.Op != OpConst32 && sdivisibleOK32(c)
+ // result: (Leq32U (RotateLeft32 <typ.UInt32> (Add32 <typ.UInt32> (Mul32 <typ.UInt32> (Const32 <typ.UInt32> [int32(sdivisible32(c).m)]) x) (Const32 <typ.UInt32> [int32(sdivisible32(c).a)]) ) (Const32 <typ.UInt32> [int32(32-sdivisible32(c).k)]) ) (Const32 <typ.UInt32> [int32(sdivisible32(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1_0.AuxInt)
+ if v_1_1.Op != OpSub32 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh32x64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAdd32 {
+ continue
+ }
+ _ = v_1_1_0_0.Args[1]
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ v_1_1_0_0_1 := v_1_1_0_0.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, v_1_1_0_0_0, v_1_1_0_0_1 = _i2+1, v_1_1_0_0_1, v_1_1_0_0_0 {
+ mul := v_1_1_0_0_0
+ if mul.Op != OpHmul32 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i3 := 0; _i3 <= 1; _i3, mul_0, mul_1 = _i3+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if x != mul_1 || x != v_1_1_0_0_1 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpRsh32x64 {
+ continue
+ }
+ _ = v_1_1_1.Args[1]
+ if x != v_1_1_1.Args[0] {
+ continue
+ }
+ v_1_1_1_1 := v_1_1_1.Args[1]
+ if v_1_1_1_1.Op != OpConst64 || auxIntToInt64(v_1_1_1_1.AuxInt) != 31 || !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(smagic32(c).m) && s == smagic32(c).s && x.Op != OpConst32 && sdivisibleOK32(c)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft32, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpAdd32, typ.UInt32)
+ v2 := b.NewValue0(v.Pos, OpMul32, typ.UInt32)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(int32(sdivisible32(c).m))
+ v2.AddArg2(v3, x)
+ v4 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v4.AuxInt = int32ToAuxInt(int32(sdivisible32(c).a))
+ v1.AddArg2(v2, v4)
+ v5 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v5.AuxInt = int32ToAuxInt(int32(32 - sdivisible32(c).k))
+ v0.AddArg2(v1, v5)
+ v6 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v6.AuxInt = int32ToAuxInt(int32(sdivisible32(c).max))
+ v.AddArg2(v0, v6)
+ return true
+ }
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq32 n (Lsh32x64 (Rsh32x64 (Add32 <t> n (Rsh32Ux64 <t> (Rsh32x64 <t> n (Const64 <typ.UInt64> [31])) (Const64 <typ.UInt64> [kbar]))) (Const64 <typ.UInt64> [k])) (Const64 <typ.UInt64> [k])) )
+ // cond: k > 0 && k < 31 && kbar == 32 - k
+ // result: (Eq32 (And32 <t> n (Const32 <t> [1<<uint(k)-1])) (Const32 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpLsh32x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpRsh32x64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAdd32 {
+ continue
+ }
+ t := v_1_0_0.Type
+ _ = v_1_0_0.Args[1]
+ v_1_0_0_0 := v_1_0_0.Args[0]
+ v_1_0_0_1 := v_1_0_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0_0_0, v_1_0_0_1 = _i1+1, v_1_0_0_1, v_1_0_0_0 {
+ if n != v_1_0_0_0 || v_1_0_0_1.Op != OpRsh32Ux64 || v_1_0_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1.Args[1]
+ v_1_0_0_1_0 := v_1_0_0_1.Args[0]
+ if v_1_0_0_1_0.Op != OpRsh32x64 || v_1_0_0_1_0.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1_0.Args[1]
+ if n != v_1_0_0_1_0.Args[0] {
+ continue
+ }
+ v_1_0_0_1_0_1 := v_1_0_0_1_0.Args[1]
+ if v_1_0_0_1_0_1.Op != OpConst64 || v_1_0_0_1_0_1.Type != typ.UInt64 || auxIntToInt64(v_1_0_0_1_0_1.AuxInt) != 31 {
+ continue
+ }
+ v_1_0_0_1_1 := v_1_0_0_1.Args[1]
+ if v_1_0_0_1_1.Op != OpConst64 || v_1_0_0_1_1.Type != typ.UInt64 {
+ continue
+ }
+ kbar := auxIntToInt64(v_1_0_0_1_1.AuxInt)
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpConst64 || v_1_0_1.Type != typ.UInt64 {
+ continue
+ }
+ k := auxIntToInt64(v_1_0_1.AuxInt)
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 || v_1_1.Type != typ.UInt64 || auxIntToInt64(v_1_1.AuxInt) != k || !(k > 0 && k < 31 && kbar == 32-k) {
+ continue
+ }
+ v.reset(OpEq32)
+ v0 := b.NewValue0(v.Pos, OpAnd32, t)
+ v1 := b.NewValue0(v.Pos, OpConst32, t)
+ v1.AuxInt = int32ToAuxInt(1<<uint(k) - 1)
+ v0.AddArg2(n, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, t)
+ v2.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Eq32 s:(Sub32 x y) (Const32 [0]))
+ // cond: s.Uses == 1
+ // result: (Eq32 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s := v_0
+ if s.Op != OpSub32 {
+ continue
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ if v_1.Op != OpConst32 || auxIntToInt32(v_1.AuxInt) != 0 || !(s.Uses == 1) {
+ continue
+ }
+ v.reset(OpEq32)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y]))
+ // cond: oneBit32(y)
+ // result: (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd32 {
+ continue
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst32 || v_0_1.Type != t {
+ continue
+ }
+ y := auxIntToInt32(v_0_1.AuxInt)
+ if v_1.Op != OpConst32 || v_1.Type != t || auxIntToInt32(v_1.AuxInt) != y || !(oneBit32(y)) {
+ continue
+ }
+ v.reset(OpNeq32)
+ v0 := b.NewValue0(v.Pos, OpAnd32, t)
+ v1 := b.NewValue0(v.Pos, OpConst32, t)
+ v1.AuxInt = int32ToAuxInt(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, t)
+ v2.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpEq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Eq32F (Const32F [c]) (Const32F [d]))
+ // result: (ConstBool [c == d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32F {
+ continue
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ if v_1.Op != OpConst32F {
+ continue
+ }
+ d := auxIntToFloat32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c == d)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpEq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Eq64 x x)
+ // result: (ConstBool [true])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (Eq64 (Const64 <t> [c]) (Add64 (Const64 <t> [d]) x))
+ // result: (Eq64 (Const64 <t> [c-d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAdd64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpEq64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Eq64 (Const64 [c]) (Const64 [d]))
+ // result: (ConstBool [c == d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c == d)
+ return true
+ }
+ break
+ }
+ // match: (Eq64 x (Mul64 (Const64 [c]) (Rsh64Ux64 mul:(Hmul64u (Const64 [m]) x) (Const64 [s])) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(1<<63+umagic64(c).m/2) && s == umagic64(c).s-1 && x.Op != OpConst64 && udivisibleOK64(c)
+ // result: (Leq64U (RotateLeft64 <typ.UInt64> (Mul64 <typ.UInt64> (Const64 <typ.UInt64> [int64(udivisible64(c).m)]) x) (Const64 <typ.UInt64> [64-udivisible64(c).k]) ) (Const64 <typ.UInt64> [int64(udivisible64(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ if v_1_1.Op != OpRsh64Ux64 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ mul := v_1_1.Args[0]
+ if mul.Op != OpHmul64u {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(mul_0.AuxInt)
+ if x != mul_1 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(1<<63+umagic64(c).m/2) && s == umagic64(c).s-1 && x.Op != OpConst64 && udivisibleOK64(c)) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft64, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(udivisible64(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(64 - udivisible64(c).k)
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(int64(udivisible64(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq64 x (Mul64 (Const64 [c]) (Rsh64Ux64 mul:(Hmul64u (Const64 [m]) (Rsh64Ux64 x (Const64 [1]))) (Const64 [s])) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(1<<63+(umagic64(c).m+1)/2) && s == umagic64(c).s-2 && x.Op != OpConst64 && udivisibleOK64(c)
+ // result: (Leq64U (RotateLeft64 <typ.UInt64> (Mul64 <typ.UInt64> (Const64 <typ.UInt64> [int64(udivisible64(c).m)]) x) (Const64 <typ.UInt64> [64-udivisible64(c).k]) ) (Const64 <typ.UInt64> [int64(udivisible64(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ if v_1_1.Op != OpRsh64Ux64 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ mul := v_1_1.Args[0]
+ if mul.Op != OpHmul64u {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(mul_0.AuxInt)
+ if mul_1.Op != OpRsh64Ux64 {
+ continue
+ }
+ _ = mul_1.Args[1]
+ if x != mul_1.Args[0] {
+ continue
+ }
+ mul_1_1 := mul_1.Args[1]
+ if mul_1_1.Op != OpConst64 || auxIntToInt64(mul_1_1.AuxInt) != 1 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(1<<63+(umagic64(c).m+1)/2) && s == umagic64(c).s-2 && x.Op != OpConst64 && udivisibleOK64(c)) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft64, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(udivisible64(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(64 - udivisible64(c).k)
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(int64(udivisible64(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq64 x (Mul64 (Const64 [c]) (Rsh64Ux64 (Avg64u x mul:(Hmul64u (Const64 [m]) x)) (Const64 [s])) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(umagic64(c).m) && s == umagic64(c).s-1 && x.Op != OpConst64 && udivisibleOK64(c)
+ // result: (Leq64U (RotateLeft64 <typ.UInt64> (Mul64 <typ.UInt64> (Const64 <typ.UInt64> [int64(udivisible64(c).m)]) x) (Const64 <typ.UInt64> [64-udivisible64(c).k]) ) (Const64 <typ.UInt64> [int64(udivisible64(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ if v_1_1.Op != OpRsh64Ux64 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpAvg64u {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ if x != v_1_1_0.Args[0] {
+ continue
+ }
+ mul := v_1_1_0.Args[1]
+ if mul.Op != OpHmul64u {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(mul_0.AuxInt)
+ if x != mul_1 {
+ continue
+ }
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(umagic64(c).m) && s == umagic64(c).s-1 && x.Op != OpConst64 && udivisibleOK64(c)) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft64, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v2.AuxInt = int64ToAuxInt(int64(udivisible64(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(64 - udivisible64(c).k)
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(int64(udivisible64(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq64 x (Mul64 (Const64 [c]) (Sub64 (Rsh64x64 mul:(Hmul64 (Const64 [m]) x) (Const64 [s])) (Rsh64x64 x (Const64 [63]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(smagic64(c).m/2) && s == smagic64(c).s-1 && x.Op != OpConst64 && sdivisibleOK64(c)
+ // result: (Leq64U (RotateLeft64 <typ.UInt64> (Add64 <typ.UInt64> (Mul64 <typ.UInt64> (Const64 <typ.UInt64> [int64(sdivisible64(c).m)]) x) (Const64 <typ.UInt64> [int64(sdivisible64(c).a)]) ) (Const64 <typ.UInt64> [64-sdivisible64(c).k]) ) (Const64 <typ.UInt64> [int64(sdivisible64(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ if v_1_1.Op != OpSub64 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh64x64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpHmul64 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(mul_0.AuxInt)
+ if x != mul_1 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpRsh64x64 {
+ continue
+ }
+ _ = v_1_1_1.Args[1]
+ if x != v_1_1_1.Args[0] {
+ continue
+ }
+ v_1_1_1_1 := v_1_1_1.Args[1]
+ if v_1_1_1_1.Op != OpConst64 || auxIntToInt64(v_1_1_1_1.AuxInt) != 63 || !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(smagic64(c).m/2) && s == smagic64(c).s-1 && x.Op != OpConst64 && sdivisibleOK64(c)) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft64, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpAdd64, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(int64(sdivisible64(c).m))
+ v2.AddArg2(v3, x)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(int64(sdivisible64(c).a))
+ v1.AddArg2(v2, v4)
+ v5 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(64 - sdivisible64(c).k)
+ v0.AddArg2(v1, v5)
+ v6 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v6.AuxInt = int64ToAuxInt(int64(sdivisible64(c).max))
+ v.AddArg2(v0, v6)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq64 x (Mul64 (Const64 [c]) (Sub64 (Rsh64x64 (Add64 mul:(Hmul64 (Const64 [m]) x) x) (Const64 [s])) (Rsh64x64 x (Const64 [63]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(smagic64(c).m) && s == smagic64(c).s && x.Op != OpConst64 && sdivisibleOK64(c)
+ // result: (Leq64U (RotateLeft64 <typ.UInt64> (Add64 <typ.UInt64> (Mul64 <typ.UInt64> (Const64 <typ.UInt64> [int64(sdivisible64(c).m)]) x) (Const64 <typ.UInt64> [int64(sdivisible64(c).a)]) ) (Const64 <typ.UInt64> [64-sdivisible64(c).k]) ) (Const64 <typ.UInt64> [int64(sdivisible64(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_0.AuxInt)
+ if v_1_1.Op != OpSub64 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh64x64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpAdd64 {
+ continue
+ }
+ _ = v_1_1_0_0.Args[1]
+ v_1_1_0_0_0 := v_1_1_0_0.Args[0]
+ v_1_1_0_0_1 := v_1_1_0_0.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, v_1_1_0_0_0, v_1_1_0_0_1 = _i2+1, v_1_1_0_0_1, v_1_1_0_0_0 {
+ mul := v_1_1_0_0_0
+ if mul.Op != OpHmul64 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i3 := 0; _i3 <= 1; _i3, mul_0, mul_1 = _i3+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst64 {
+ continue
+ }
+ m := auxIntToInt64(mul_0.AuxInt)
+ if x != mul_1 || x != v_1_1_0_0_1 {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpRsh64x64 {
+ continue
+ }
+ _ = v_1_1_1.Args[1]
+ if x != v_1_1_1.Args[0] {
+ continue
+ }
+ v_1_1_1_1 := v_1_1_1.Args[1]
+ if v_1_1_1_1.Op != OpConst64 || auxIntToInt64(v_1_1_1_1.AuxInt) != 63 || !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int64(smagic64(c).m) && s == smagic64(c).s && x.Op != OpConst64 && sdivisibleOK64(c)) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft64, typ.UInt64)
+ v1 := b.NewValue0(v.Pos, OpAdd64, typ.UInt64)
+ v2 := b.NewValue0(v.Pos, OpMul64, typ.UInt64)
+ v3 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v3.AuxInt = int64ToAuxInt(int64(sdivisible64(c).m))
+ v2.AddArg2(v3, x)
+ v4 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v4.AuxInt = int64ToAuxInt(int64(sdivisible64(c).a))
+ v1.AddArg2(v2, v4)
+ v5 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v5.AuxInt = int64ToAuxInt(64 - sdivisible64(c).k)
+ v0.AddArg2(v1, v5)
+ v6 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v6.AuxInt = int64ToAuxInt(int64(sdivisible64(c).max))
+ v.AddArg2(v0, v6)
+ return true
+ }
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq64 n (Lsh64x64 (Rsh64x64 (Add64 <t> n (Rsh64Ux64 <t> (Rsh64x64 <t> n (Const64 <typ.UInt64> [63])) (Const64 <typ.UInt64> [kbar]))) (Const64 <typ.UInt64> [k])) (Const64 <typ.UInt64> [k])) )
+ // cond: k > 0 && k < 63 && kbar == 64 - k
+ // result: (Eq64 (And64 <t> n (Const64 <t> [1<<uint(k)-1])) (Const64 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpLsh64x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpRsh64x64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAdd64 {
+ continue
+ }
+ t := v_1_0_0.Type
+ _ = v_1_0_0.Args[1]
+ v_1_0_0_0 := v_1_0_0.Args[0]
+ v_1_0_0_1 := v_1_0_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0_0_0, v_1_0_0_1 = _i1+1, v_1_0_0_1, v_1_0_0_0 {
+ if n != v_1_0_0_0 || v_1_0_0_1.Op != OpRsh64Ux64 || v_1_0_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1.Args[1]
+ v_1_0_0_1_0 := v_1_0_0_1.Args[0]
+ if v_1_0_0_1_0.Op != OpRsh64x64 || v_1_0_0_1_0.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1_0.Args[1]
+ if n != v_1_0_0_1_0.Args[0] {
+ continue
+ }
+ v_1_0_0_1_0_1 := v_1_0_0_1_0.Args[1]
+ if v_1_0_0_1_0_1.Op != OpConst64 || v_1_0_0_1_0_1.Type != typ.UInt64 || auxIntToInt64(v_1_0_0_1_0_1.AuxInt) != 63 {
+ continue
+ }
+ v_1_0_0_1_1 := v_1_0_0_1.Args[1]
+ if v_1_0_0_1_1.Op != OpConst64 || v_1_0_0_1_1.Type != typ.UInt64 {
+ continue
+ }
+ kbar := auxIntToInt64(v_1_0_0_1_1.AuxInt)
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpConst64 || v_1_0_1.Type != typ.UInt64 {
+ continue
+ }
+ k := auxIntToInt64(v_1_0_1.AuxInt)
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 || v_1_1.Type != typ.UInt64 || auxIntToInt64(v_1_1.AuxInt) != k || !(k > 0 && k < 63 && kbar == 64-k) {
+ continue
+ }
+ v.reset(OpEq64)
+ v0 := b.NewValue0(v.Pos, OpAnd64, t)
+ v1 := b.NewValue0(v.Pos, OpConst64, t)
+ v1.AuxInt = int64ToAuxInt(1<<uint(k) - 1)
+ v0.AddArg2(n, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Eq64 s:(Sub64 x y) (Const64 [0]))
+ // cond: s.Uses == 1
+ // result: (Eq64 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s := v_0
+ if s.Op != OpSub64 {
+ continue
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 || !(s.Uses == 1) {
+ continue
+ }
+ v.reset(OpEq64)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y]))
+ // cond: oneBit64(y)
+ // result: (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd64 {
+ continue
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst64 || v_0_1.Type != t {
+ continue
+ }
+ y := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 || v_1.Type != t || auxIntToInt64(v_1.AuxInt) != y || !(oneBit64(y)) {
+ continue
+ }
+ v.reset(OpNeq64)
+ v0 := b.NewValue0(v.Pos, OpAnd64, t)
+ v1 := b.NewValue0(v.Pos, OpConst64, t)
+ v1.AuxInt = int64ToAuxInt(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpEq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Eq64F (Const64F [c]) (Const64F [d]))
+ // result: (ConstBool [c == d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64F {
+ continue
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ if v_1.Op != OpConst64F {
+ continue
+ }
+ d := auxIntToFloat64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c == d)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpEq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (Eq8 x x)
+ // result: (ConstBool [true])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (Eq8 (Const8 <t> [c]) (Add8 (Const8 <t> [d]) x))
+ // result: (Eq8 (Const8 <t> [c-d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpAdd8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst8 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt8(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpEq8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Eq8 (Const8 [c]) (Const8 [d]))
+ // result: (ConstBool [c == d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c == d)
+ return true
+ }
+ break
+ }
+ // match: (Eq8 (Mod8u x (Const8 [c])) (Const8 [0]))
+ // cond: x.Op != OpConst8 && udivisibleOK8(c) && !hasSmallRotate(config)
+ // result: (Eq32 (Mod32u <typ.UInt32> (ZeroExt8to32 <typ.UInt32> x) (Const32 <typ.UInt32> [int32(uint8(c))])) (Const32 <typ.UInt32> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMod8u {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_1.AuxInt)
+ if v_1.Op != OpConst8 || auxIntToInt8(v_1.AuxInt) != 0 || !(x.Op != OpConst8 && udivisibleOK8(c) && !hasSmallRotate(config)) {
+ continue
+ }
+ v.reset(OpEq32)
+ v0 := b.NewValue0(v.Pos, OpMod32u, typ.UInt32)
+ v1 := b.NewValue0(v.Pos, OpZeroExt8to32, typ.UInt32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v2.AuxInt = int32ToAuxInt(int32(uint8(c)))
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.UInt32)
+ v3.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v3)
+ return true
+ }
+ break
+ }
+ // match: (Eq8 (Mod8 x (Const8 [c])) (Const8 [0]))
+ // cond: x.Op != OpConst8 && sdivisibleOK8(c) && !hasSmallRotate(config)
+ // result: (Eq32 (Mod32 <typ.Int32> (SignExt8to32 <typ.Int32> x) (Const32 <typ.Int32> [int32(c)])) (Const32 <typ.Int32> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMod8 {
+ continue
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_1.AuxInt)
+ if v_1.Op != OpConst8 || auxIntToInt8(v_1.AuxInt) != 0 || !(x.Op != OpConst8 && sdivisibleOK8(c) && !hasSmallRotate(config)) {
+ continue
+ }
+ v.reset(OpEq32)
+ v0 := b.NewValue0(v.Pos, OpMod32, typ.Int32)
+ v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
+ v1.AddArg(x)
+ v2 := b.NewValue0(v.Pos, OpConst32, typ.Int32)
+ v2.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg2(v1, v2)
+ v3 := b.NewValue0(v.Pos, OpConst32, typ.Int32)
+ v3.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v3)
+ return true
+ }
+ break
+ }
+ // match: (Eq8 x (Mul8 (Const8 [c]) (Trunc32to8 (Rsh32Ux64 mul:(Mul32 (Const32 [m]) (ZeroExt8to32 x)) (Const64 [s]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(1<<8+umagic8(c).m) && s == 8+umagic8(c).s && x.Op != OpConst8 && udivisibleOK8(c)
+ // result: (Leq8U (RotateLeft8 <typ.UInt8> (Mul8 <typ.UInt8> (Const8 <typ.UInt8> [int8(udivisible8(c).m)]) x) (Const8 <typ.UInt8> [int8(8-udivisible8(c).k)]) ) (Const8 <typ.UInt8> [int8(udivisible8(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_1_0.AuxInt)
+ if v_1_1.Op != OpTrunc32to8 {
+ continue
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh32Ux64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpMul32 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if mul_1.Op != OpZeroExt8to32 || x != mul_1.Args[0] {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ if !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(1<<8+umagic8(c).m) && s == 8+umagic8(c).s && x.Op != OpConst8 && udivisibleOK8(c)) {
+ continue
+ }
+ v.reset(OpLeq8U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft8, typ.UInt8)
+ v1 := b.NewValue0(v.Pos, OpMul8, typ.UInt8)
+ v2 := b.NewValue0(v.Pos, OpConst8, typ.UInt8)
+ v2.AuxInt = int8ToAuxInt(int8(udivisible8(c).m))
+ v1.AddArg2(v2, x)
+ v3 := b.NewValue0(v.Pos, OpConst8, typ.UInt8)
+ v3.AuxInt = int8ToAuxInt(int8(8 - udivisible8(c).k))
+ v0.AddArg2(v1, v3)
+ v4 := b.NewValue0(v.Pos, OpConst8, typ.UInt8)
+ v4.AuxInt = int8ToAuxInt(int8(udivisible8(c).max))
+ v.AddArg2(v0, v4)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq8 x (Mul8 (Const8 [c]) (Sub8 (Rsh32x64 mul:(Mul32 (Const32 [m]) (SignExt8to32 x)) (Const64 [s])) (Rsh32x64 (SignExt8to32 x) (Const64 [31]))) ) )
+ // cond: v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(smagic8(c).m) && s == 8+smagic8(c).s && x.Op != OpConst8 && sdivisibleOK8(c)
+ // result: (Leq8U (RotateLeft8 <typ.UInt8> (Add8 <typ.UInt8> (Mul8 <typ.UInt8> (Const8 <typ.UInt8> [int8(sdivisible8(c).m)]) x) (Const8 <typ.UInt8> [int8(sdivisible8(c).a)]) ) (Const8 <typ.UInt8> [int8(8-sdivisible8(c).k)]) ) (Const8 <typ.UInt8> [int8(sdivisible8(c).max)]) )
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpMul8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_1_0.AuxInt)
+ if v_1_1.Op != OpSub8 {
+ continue
+ }
+ _ = v_1_1.Args[1]
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpRsh32x64 {
+ continue
+ }
+ _ = v_1_1_0.Args[1]
+ mul := v_1_1_0.Args[0]
+ if mul.Op != OpMul32 {
+ continue
+ }
+ _ = mul.Args[1]
+ mul_0 := mul.Args[0]
+ mul_1 := mul.Args[1]
+ for _i2 := 0; _i2 <= 1; _i2, mul_0, mul_1 = _i2+1, mul_1, mul_0 {
+ if mul_0.Op != OpConst32 {
+ continue
+ }
+ m := auxIntToInt32(mul_0.AuxInt)
+ if mul_1.Op != OpSignExt8to32 || x != mul_1.Args[0] {
+ continue
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpConst64 {
+ continue
+ }
+ s := auxIntToInt64(v_1_1_0_1.AuxInt)
+ v_1_1_1 := v_1_1.Args[1]
+ if v_1_1_1.Op != OpRsh32x64 {
+ continue
+ }
+ _ = v_1_1_1.Args[1]
+ v_1_1_1_0 := v_1_1_1.Args[0]
+ if v_1_1_1_0.Op != OpSignExt8to32 || x != v_1_1_1_0.Args[0] {
+ continue
+ }
+ v_1_1_1_1 := v_1_1_1.Args[1]
+ if v_1_1_1_1.Op != OpConst64 || auxIntToInt64(v_1_1_1_1.AuxInt) != 31 || !(v.Block.Func.pass.name != "opt" && mul.Uses == 1 && m == int32(smagic8(c).m) && s == 8+smagic8(c).s && x.Op != OpConst8 && sdivisibleOK8(c)) {
+ continue
+ }
+ v.reset(OpLeq8U)
+ v0 := b.NewValue0(v.Pos, OpRotateLeft8, typ.UInt8)
+ v1 := b.NewValue0(v.Pos, OpAdd8, typ.UInt8)
+ v2 := b.NewValue0(v.Pos, OpMul8, typ.UInt8)
+ v3 := b.NewValue0(v.Pos, OpConst8, typ.UInt8)
+ v3.AuxInt = int8ToAuxInt(int8(sdivisible8(c).m))
+ v2.AddArg2(v3, x)
+ v4 := b.NewValue0(v.Pos, OpConst8, typ.UInt8)
+ v4.AuxInt = int8ToAuxInt(int8(sdivisible8(c).a))
+ v1.AddArg2(v2, v4)
+ v5 := b.NewValue0(v.Pos, OpConst8, typ.UInt8)
+ v5.AuxInt = int8ToAuxInt(int8(8 - sdivisible8(c).k))
+ v0.AddArg2(v1, v5)
+ v6 := b.NewValue0(v.Pos, OpConst8, typ.UInt8)
+ v6.AuxInt = int8ToAuxInt(int8(sdivisible8(c).max))
+ v.AddArg2(v0, v6)
+ return true
+ }
+ }
+ }
+ break
+ }
+ // match: (Eq8 n (Lsh8x64 (Rsh8x64 (Add8 <t> n (Rsh8Ux64 <t> (Rsh8x64 <t> n (Const64 <typ.UInt64> [ 7])) (Const64 <typ.UInt64> [kbar]))) (Const64 <typ.UInt64> [k])) (Const64 <typ.UInt64> [k])) )
+ // cond: k > 0 && k < 7 && kbar == 8 - k
+ // result: (Eq8 (And8 <t> n (Const8 <t> [1<<uint(k)-1])) (Const8 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpLsh8x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpRsh8x64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAdd8 {
+ continue
+ }
+ t := v_1_0_0.Type
+ _ = v_1_0_0.Args[1]
+ v_1_0_0_0 := v_1_0_0.Args[0]
+ v_1_0_0_1 := v_1_0_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0_0_0, v_1_0_0_1 = _i1+1, v_1_0_0_1, v_1_0_0_0 {
+ if n != v_1_0_0_0 || v_1_0_0_1.Op != OpRsh8Ux64 || v_1_0_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1.Args[1]
+ v_1_0_0_1_0 := v_1_0_0_1.Args[0]
+ if v_1_0_0_1_0.Op != OpRsh8x64 || v_1_0_0_1_0.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1_0.Args[1]
+ if n != v_1_0_0_1_0.Args[0] {
+ continue
+ }
+ v_1_0_0_1_0_1 := v_1_0_0_1_0.Args[1]
+ if v_1_0_0_1_0_1.Op != OpConst64 || v_1_0_0_1_0_1.Type != typ.UInt64 || auxIntToInt64(v_1_0_0_1_0_1.AuxInt) != 7 {
+ continue
+ }
+ v_1_0_0_1_1 := v_1_0_0_1.Args[1]
+ if v_1_0_0_1_1.Op != OpConst64 || v_1_0_0_1_1.Type != typ.UInt64 {
+ continue
+ }
+ kbar := auxIntToInt64(v_1_0_0_1_1.AuxInt)
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpConst64 || v_1_0_1.Type != typ.UInt64 {
+ continue
+ }
+ k := auxIntToInt64(v_1_0_1.AuxInt)
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 || v_1_1.Type != typ.UInt64 || auxIntToInt64(v_1_1.AuxInt) != k || !(k > 0 && k < 7 && kbar == 8-k) {
+ continue
+ }
+ v.reset(OpEq8)
+ v0 := b.NewValue0(v.Pos, OpAnd8, t)
+ v1 := b.NewValue0(v.Pos, OpConst8, t)
+ v1.AuxInt = int8ToAuxInt(1<<uint(k) - 1)
+ v0.AddArg2(n, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, t)
+ v2.AuxInt = int8ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Eq8 s:(Sub8 x y) (Const8 [0]))
+ // cond: s.Uses == 1
+ // result: (Eq8 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s := v_0
+ if s.Op != OpSub8 {
+ continue
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ if v_1.Op != OpConst8 || auxIntToInt8(v_1.AuxInt) != 0 || !(s.Uses == 1) {
+ continue
+ }
+ v.reset(OpEq8)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y]))
+ // cond: oneBit8(y)
+ // result: (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd8 {
+ continue
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst8 || v_0_1.Type != t {
+ continue
+ }
+ y := auxIntToInt8(v_0_1.AuxInt)
+ if v_1.Op != OpConst8 || v_1.Type != t || auxIntToInt8(v_1.AuxInt) != y || !(oneBit8(y)) {
+ continue
+ }
+ v.reset(OpNeq8)
+ v0 := b.NewValue0(v.Pos, OpAnd8, t)
+ v1 := b.NewValue0(v.Pos, OpConst8, t)
+ v1.AuxInt = int8ToAuxInt(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, t)
+ v2.AuxInt = int8ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpEqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (EqB (ConstBool [c]) (ConstBool [d]))
+ // result: (ConstBool [c == d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConstBool {
+ continue
+ }
+ c := auxIntToBool(v_0.AuxInt)
+ if v_1.Op != OpConstBool {
+ continue
+ }
+ d := auxIntToBool(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c == d)
+ return true
+ }
+ break
+ }
+ // match: (EqB (ConstBool [false]) x)
+ // result: (Not x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConstBool || auxIntToBool(v_0.AuxInt) != false {
+ continue
+ }
+ x := v_1
+ v.reset(OpNot)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (EqB (ConstBool [true]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConstBool || auxIntToBool(v_0.AuxInt) != true {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpEqInter(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqInter x y)
+ // result: (EqPtr (ITab x) (ITab y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpEqPtr)
+ v0 := b.NewValue0(v.Pos, OpITab, typ.Uintptr)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpITab, typ.Uintptr)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuegeneric_OpEqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqPtr x x)
+ // result: (ConstBool [true])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (EqPtr (Addr {a} _) (Addr {b} _))
+ // result: (ConstBool [a == b])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAddr {
+ continue
+ }
+ a := auxToSym(v_0.Aux)
+ if v_1.Op != OpAddr {
+ continue
+ }
+ b := auxToSym(v_1.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a == b)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (Addr {a} _) (OffPtr [o] (Addr {b} _)))
+ // result: (ConstBool [a == b && o == 0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAddr {
+ continue
+ }
+ a := auxToSym(v_0.Aux)
+ if v_1.Op != OpOffPtr {
+ continue
+ }
+ o := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAddr {
+ continue
+ }
+ b := auxToSym(v_1_0.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a == b && o == 0)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (OffPtr [o1] (Addr {a} _)) (OffPtr [o2] (Addr {b} _)))
+ // result: (ConstBool [a == b && o1 == o2])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ o1 := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAddr {
+ continue
+ }
+ a := auxToSym(v_0_0.Aux)
+ if v_1.Op != OpOffPtr {
+ continue
+ }
+ o2 := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAddr {
+ continue
+ }
+ b := auxToSym(v_1_0.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a == b && o1 == o2)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (LocalAddr {a} _ _) (LocalAddr {b} _ _))
+ // result: (ConstBool [a == b])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLocalAddr {
+ continue
+ }
+ a := auxToSym(v_0.Aux)
+ if v_1.Op != OpLocalAddr {
+ continue
+ }
+ b := auxToSym(v_1.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a == b)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (LocalAddr {a} _ _) (OffPtr [o] (LocalAddr {b} _ _)))
+ // result: (ConstBool [a == b && o == 0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLocalAddr {
+ continue
+ }
+ a := auxToSym(v_0.Aux)
+ if v_1.Op != OpOffPtr {
+ continue
+ }
+ o := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpLocalAddr {
+ continue
+ }
+ b := auxToSym(v_1_0.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a == b && o == 0)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (OffPtr [o1] (LocalAddr {a} _ _)) (OffPtr [o2] (LocalAddr {b} _ _)))
+ // result: (ConstBool [a == b && o1 == o2])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ o1 := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLocalAddr {
+ continue
+ }
+ a := auxToSym(v_0_0.Aux)
+ if v_1.Op != OpOffPtr {
+ continue
+ }
+ o2 := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpLocalAddr {
+ continue
+ }
+ b := auxToSym(v_1_0.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a == b && o1 == o2)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (OffPtr [o1] p1) p2)
+ // cond: isSamePtr(p1, p2)
+ // result: (ConstBool [o1 == 0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ o1 := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ p2 := v_1
+ if !(isSamePtr(p1, p2)) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(o1 == 0)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (OffPtr [o1] p1) (OffPtr [o2] p2))
+ // cond: isSamePtr(p1, p2)
+ // result: (ConstBool [o1 == o2])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ o1 := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ if v_1.Op != OpOffPtr {
+ continue
+ }
+ o2 := auxIntToInt64(v_1.AuxInt)
+ p2 := v_1.Args[0]
+ if !(isSamePtr(p1, p2)) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(o1 == o2)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (Const32 [c]) (Const32 [d]))
+ // result: (ConstBool [c == d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c == d)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (Const64 [c]) (Const64 [d]))
+ // result: (ConstBool [c == d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c == d)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (LocalAddr _ _) (Addr _))
+ // result: (ConstBool [false])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLocalAddr || v_1.Op != OpAddr {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (OffPtr (LocalAddr _ _)) (Addr _))
+ // result: (ConstBool [false])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLocalAddr || v_1.Op != OpAddr {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (LocalAddr _ _) (OffPtr (Addr _)))
+ // result: (ConstBool [false])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLocalAddr || v_1.Op != OpOffPtr {
+ continue
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAddr {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (OffPtr (LocalAddr _ _)) (OffPtr (Addr _)))
+ // result: (ConstBool [false])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLocalAddr || v_1.Op != OpOffPtr {
+ continue
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAddr {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (AddPtr p1 o1) p2)
+ // cond: isSamePtr(p1, p2)
+ // result: (Not (IsNonNil o1))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAddPtr {
+ continue
+ }
+ o1 := v_0.Args[1]
+ p1 := v_0.Args[0]
+ p2 := v_1
+ if !(isSamePtr(p1, p2)) {
+ continue
+ }
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpIsNonNil, typ.Bool)
+ v0.AddArg(o1)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (Const32 [0]) p)
+ // result: (Not (IsNonNil p))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ continue
+ }
+ p := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpIsNonNil, typ.Bool)
+ v0.AddArg(p)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (Const64 [0]) p)
+ // result: (Not (IsNonNil p))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ continue
+ }
+ p := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpIsNonNil, typ.Bool)
+ v0.AddArg(p)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (EqPtr (ConstNil) p)
+ // result: (Not (IsNonNil p))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConstNil {
+ continue
+ }
+ p := v_1
+ v.reset(OpNot)
+ v0 := b.NewValue0(v.Pos, OpIsNonNil, typ.Bool)
+ v0.AddArg(p)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpEqSlice(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (EqSlice x y)
+ // result: (EqPtr (SlicePtr x) (SlicePtr y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpEqPtr)
+ v0 := b.NewValue0(v.Pos, OpSlicePtr, typ.BytePtr)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSlicePtr, typ.BytePtr)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuegeneric_OpIMake(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (IMake typ (StructMake1 val))
+ // result: (IMake typ val)
+ for {
+ typ := v_0
+ if v_1.Op != OpStructMake1 {
+ break
+ }
+ val := v_1.Args[0]
+ v.reset(OpIMake)
+ v.AddArg2(typ, val)
+ return true
+ }
+ // match: (IMake typ (ArrayMake1 val))
+ // result: (IMake typ val)
+ for {
+ typ := v_0
+ if v_1.Op != OpArrayMake1 {
+ break
+ }
+ val := v_1.Args[0]
+ v.reset(OpIMake)
+ v.AddArg2(typ, val)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpInterCall(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (InterCall [argsize] {auxCall} (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) mem)
+ // cond: devirt(v, auxCall, itab, off) != nil
+ // result: (StaticCall [int32(argsize)] {devirt(v, auxCall, itab, off)} mem)
+ for {
+ argsize := auxIntToInt32(v.AuxInt)
+ auxCall := auxToCall(v.Aux)
+ if v_0.Op != OpLoad {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpOffPtr {
+ break
+ }
+ off := auxIntToInt64(v_0_0.AuxInt)
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpITab {
+ break
+ }
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpIMake {
+ break
+ }
+ v_0_0_0_0_0 := v_0_0_0_0.Args[0]
+ if v_0_0_0_0_0.Op != OpAddr {
+ break
+ }
+ itab := auxToSym(v_0_0_0_0_0.Aux)
+ v_0_0_0_0_0_0 := v_0_0_0_0_0.Args[0]
+ if v_0_0_0_0_0_0.Op != OpSB {
+ break
+ }
+ mem := v_1
+ if !(devirt(v, auxCall, itab, off) != nil) {
+ break
+ }
+ v.reset(OpStaticCall)
+ v.AuxInt = int32ToAuxInt(int32(argsize))
+ v.Aux = callToAux(devirt(v, auxCall, itab, off))
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpInterLECall(v *Value) bool {
+ // match: (InterLECall [argsize] {auxCall} (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) ___)
+ // cond: devirtLESym(v, auxCall, itab, off) != nil
+ // result: devirtLECall(v, devirtLESym(v, auxCall, itab, off))
+ for {
+ if len(v.Args) < 1 {
+ break
+ }
+ auxCall := auxToCall(v.Aux)
+ v_0 := v.Args[0]
+ if v_0.Op != OpLoad {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpOffPtr {
+ break
+ }
+ off := auxIntToInt64(v_0_0.AuxInt)
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpITab {
+ break
+ }
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpIMake {
+ break
+ }
+ v_0_0_0_0_0 := v_0_0_0_0.Args[0]
+ if v_0_0_0_0_0.Op != OpAddr {
+ break
+ }
+ itab := auxToSym(v_0_0_0_0_0.Aux)
+ v_0_0_0_0_0_0 := v_0_0_0_0_0.Args[0]
+ if v_0_0_0_0_0_0.Op != OpSB || !(devirtLESym(v, auxCall, itab, off) != nil) {
+ break
+ }
+ v.copyOf(devirtLECall(v, devirtLESym(v, auxCall, itab, off)))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpIsInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (IsInBounds (ZeroExt8to32 _) (Const32 [c]))
+ // cond: (1 << 8) <= c
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt8to32 || v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !((1 << 8) <= c) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (ZeroExt8to64 _) (Const64 [c]))
+ // cond: (1 << 8) <= c
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt8to64 || v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !((1 << 8) <= c) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (ZeroExt16to32 _) (Const32 [c]))
+ // cond: (1 << 16) <= c
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt16to32 || v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !((1 << 16) <= c) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (ZeroExt16to64 _) (Const64 [c]))
+ // cond: (1 << 16) <= c
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt16to64 || v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !((1 << 16) <= c) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds x x)
+ // result: (ConstBool [false])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (IsInBounds (And8 (Const8 [c]) _) (Const8 [d]))
+ // cond: 0 <= c && c < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAnd8 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if !(0 <= c && c < d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsInBounds (ZeroExt8to16 (And8 (Const8 [c]) _)) (Const16 [d]))
+ // cond: 0 <= c && int16(c) < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt8to16 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAnd8 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0_0, v_0_0_1 = _i0+1, v_0_0_1, v_0_0_0 {
+ if v_0_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ if !(0 <= c && int16(c) < d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsInBounds (ZeroExt8to32 (And8 (Const8 [c]) _)) (Const32 [d]))
+ // cond: 0 <= c && int32(c) < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt8to32 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAnd8 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0_0, v_0_0_1 = _i0+1, v_0_0_1, v_0_0_0 {
+ if v_0_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if !(0 <= c && int32(c) < d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsInBounds (ZeroExt8to64 (And8 (Const8 [c]) _)) (Const64 [d]))
+ // cond: 0 <= c && int64(c) < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt8to64 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAnd8 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0_0, v_0_0_1 = _i0+1, v_0_0_1, v_0_0_0 {
+ if v_0_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 <= c && int64(c) < d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsInBounds (And16 (Const16 [c]) _) (Const16 [d]))
+ // cond: 0 <= c && c < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAnd16 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ if !(0 <= c && c < d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsInBounds (ZeroExt16to32 (And16 (Const16 [c]) _)) (Const32 [d]))
+ // cond: 0 <= c && int32(c) < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt16to32 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAnd16 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0_0, v_0_0_1 = _i0+1, v_0_0_1, v_0_0_0 {
+ if v_0_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if !(0 <= c && int32(c) < d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsInBounds (ZeroExt16to64 (And16 (Const16 [c]) _)) (Const64 [d]))
+ // cond: 0 <= c && int64(c) < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt16to64 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAnd16 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0_0, v_0_0_1 = _i0+1, v_0_0_1, v_0_0_0 {
+ if v_0_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 <= c && int64(c) < d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsInBounds (And32 (Const32 [c]) _) (Const32 [d]))
+ // cond: 0 <= c && c < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAnd32 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if !(0 <= c && c < d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsInBounds (ZeroExt32to64 (And32 (Const32 [c]) _)) (Const64 [d]))
+ // cond: 0 <= c && int64(c) < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt32to64 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAnd32 {
+ break
+ }
+ v_0_0_0 := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0_0, v_0_0_1 = _i0+1, v_0_0_1, v_0_0_0 {
+ if v_0_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 <= c && int64(c) < d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsInBounds (And64 (Const64 [c]) _) (Const64 [d]))
+ // cond: 0 <= c && c < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAnd64 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 <= c && c < d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsInBounds (Const32 [c]) (Const32 [d]))
+ // result: (ConstBool [0 <= c && c < d])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(0 <= c && c < d)
+ return true
+ }
+ // match: (IsInBounds (Const64 [c]) (Const64 [d]))
+ // result: (ConstBool [0 <= c && c < d])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(0 <= c && c < d)
+ return true
+ }
+ // match: (IsInBounds (Mod32u _ y) y)
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpMod32u {
+ break
+ }
+ y := v_0.Args[1]
+ if y != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (Mod64u _ y) y)
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpMod64u {
+ break
+ }
+ y := v_0.Args[1]
+ if y != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (ZeroExt8to64 (Rsh8Ux64 _ (Const64 [c]))) (Const64 [d]))
+ // cond: 0 < c && c < 8 && 1<<uint( 8-c)-1 < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt8to64 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpRsh8Ux64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (ZeroExt8to32 (Rsh8Ux64 _ (Const64 [c]))) (Const32 [d]))
+ // cond: 0 < c && c < 8 && 1<<uint( 8-c)-1 < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt8to32 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpRsh8Ux64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_0_1.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (ZeroExt8to16 (Rsh8Ux64 _ (Const64 [c]))) (Const16 [d]))
+ // cond: 0 < c && c < 8 && 1<<uint( 8-c)-1 < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt8to16 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpRsh8Ux64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_0_1.AuxInt)
+ if v_1.Op != OpConst16 {
+ break
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (Rsh8Ux64 _ (Const64 [c])) (Const64 [d]))
+ // cond: 0 < c && c < 8 && 1<<uint( 8-c)-1 < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpRsh8Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (ZeroExt16to64 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d]))
+ // cond: 0 < c && c < 16 && 1<<uint(16-c)-1 < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt16to64 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpRsh16Ux64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 < c && c < 16 && 1<<uint(16-c)-1 < d) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (ZeroExt16to32 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d]))
+ // cond: 0 < c && c < 16 && 1<<uint(16-c)-1 < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt16to32 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpRsh16Ux64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 < c && c < 16 && 1<<uint(16-c)-1 < d) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (Rsh16Ux64 _ (Const64 [c])) (Const64 [d]))
+ // cond: 0 < c && c < 16 && 1<<uint(16-c)-1 < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpRsh16Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 < c && c < 16 && 1<<uint(16-c)-1 < d) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (ZeroExt32to64 (Rsh32Ux64 _ (Const64 [c]))) (Const64 [d]))
+ // cond: 0 < c && c < 32 && 1<<uint(32-c)-1 < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpZeroExt32to64 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpRsh32Ux64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 < c && c < 32 && 1<<uint(32-c)-1 < d) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (Rsh32Ux64 _ (Const64 [c])) (Const64 [d]))
+ // cond: 0 < c && c < 32 && 1<<uint(32-c)-1 < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpRsh32Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 < c && c < 32 && 1<<uint(32-c)-1 < d) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsInBounds (Rsh64Ux64 _ (Const64 [c])) (Const64 [d]))
+ // cond: 0 < c && c < 64 && 1<<uint(64-c)-1 < d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpRsh64Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 < c && c < 64 && 1<<uint(64-c)-1 < d) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpIsNonNil(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (IsNonNil (ConstNil))
+ // result: (ConstBool [false])
+ for {
+ if v_0.Op != OpConstNil {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (IsNonNil (Const32 [c]))
+ // result: (ConstBool [c != 0])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != 0)
+ return true
+ }
+ // match: (IsNonNil (Const64 [c]))
+ // result: (ConstBool [c != 0])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != 0)
+ return true
+ }
+ // match: (IsNonNil (Addr _))
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAddr {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsNonNil (LocalAddr _ _))
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpLocalAddr {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpIsSliceInBounds(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (IsSliceInBounds x x)
+ // result: (ConstBool [true])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsSliceInBounds (And32 (Const32 [c]) _) (Const32 [d]))
+ // cond: 0 <= c && c <= d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAnd32 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if !(0 <= c && c <= d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsSliceInBounds (And64 (Const64 [c]) _) (Const64 [d]))
+ // cond: 0 <= c && c <= d
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpAnd64 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(0 <= c && c <= d) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (IsSliceInBounds (Const32 [0]) _)
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsSliceInBounds (Const64 [0]) _)
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ // match: (IsSliceInBounds (Const32 [c]) (Const32 [d]))
+ // result: (ConstBool [0 <= c && c <= d])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(0 <= c && c <= d)
+ return true
+ }
+ // match: (IsSliceInBounds (Const64 [c]) (Const64 [d]))
+ // result: (ConstBool [0 <= c && c <= d])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(0 <= c && c <= d)
+ return true
+ }
+ // match: (IsSliceInBounds (SliceLen x) (SliceCap x))
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpSliceLen {
+ break
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpSliceCap || x != v_1.Args[0] {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Leq16 (Const16 [c]) (Const16 [d]))
+ // result: (ConstBool [c <= d])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ break
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c <= d)
+ return true
+ }
+ // match: (Leq16 (Const16 [0]) (And16 _ (Const16 [c])))
+ // cond: c >= 0
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 || v_1.Op != OpAnd16 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_1_1.AuxInt)
+ if !(c >= 0) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (Leq16 (Const16 [0]) (Rsh16Ux64 _ (Const64 [c])))
+ // cond: c > 0
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 || v_1.Op != OpRsh16Ux64 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c > 0) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLeq16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Leq16U (Const16 [c]) (Const16 [d]))
+ // result: (ConstBool [uint16(c) <= uint16(d)])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ break
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(uint16(c) <= uint16(d))
+ return true
+ }
+ // match: (Leq16U (Const16 [0]) _)
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Leq32 (Const32 [c]) (Const32 [d]))
+ // result: (ConstBool [c <= d])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c <= d)
+ return true
+ }
+ // match: (Leq32 (Const32 [0]) (And32 _ (Const32 [c])))
+ // cond: c >= 0
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 || v_1.Op != OpAnd32 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1_1.AuxInt)
+ if !(c >= 0) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (Leq32 (Const32 [0]) (Rsh32Ux64 _ (Const64 [c])))
+ // cond: c > 0
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 || v_1.Op != OpRsh32Ux64 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c > 0) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Leq32F (Const32F [c]) (Const32F [d]))
+ // result: (ConstBool [c <= d])
+ for {
+ if v_0.Op != OpConst32F {
+ break
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ if v_1.Op != OpConst32F {
+ break
+ }
+ d := auxIntToFloat32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c <= d)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLeq32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Leq32U (Const32 [c]) (Const32 [d]))
+ // result: (ConstBool [uint32(c) <= uint32(d)])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(uint32(c) <= uint32(d))
+ return true
+ }
+ // match: (Leq32U (Const32 [0]) _)
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Leq64 (Const64 [c]) (Const64 [d]))
+ // result: (ConstBool [c <= d])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c <= d)
+ return true
+ }
+ // match: (Leq64 (Const64 [0]) (And64 _ (Const64 [c])))
+ // cond: c >= 0
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 || v_1.Op != OpAnd64 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= 0) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (Leq64 (Const64 [0]) (Rsh64Ux64 _ (Const64 [c])))
+ // cond: c > 0
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 || v_1.Op != OpRsh64Ux64 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c > 0) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Leq64F (Const64F [c]) (Const64F [d]))
+ // result: (ConstBool [c <= d])
+ for {
+ if v_0.Op != OpConst64F {
+ break
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ if v_1.Op != OpConst64F {
+ break
+ }
+ d := auxIntToFloat64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c <= d)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLeq64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Leq64U (Const64 [c]) (Const64 [d]))
+ // result: (ConstBool [uint64(c) <= uint64(d)])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(uint64(c) <= uint64(d))
+ return true
+ }
+ // match: (Leq64U (Const64 [0]) _)
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Leq8 (Const8 [c]) (Const8 [d]))
+ // result: (ConstBool [c <= d])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ break
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c <= d)
+ return true
+ }
+ // match: (Leq8 (Const8 [0]) (And8 _ (Const8 [c])))
+ // cond: c >= 0
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 || v_1.Op != OpAnd8 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_1_1.AuxInt)
+ if !(c >= 0) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (Leq8 (Const8 [0]) (Rsh8Ux64 _ (Const64 [c])))
+ // cond: c > 0
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 || v_1.Op != OpRsh8Ux64 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1_1.AuxInt)
+ if !(c > 0) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLeq8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Leq8U (Const8 [c]) (Const8 [d]))
+ // result: (ConstBool [ uint8(c) <= uint8(d)])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ break
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(uint8(c) <= uint8(d))
+ return true
+ }
+ // match: (Leq8U (Const8 [0]) _)
+ // result: (ConstBool [true])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLess16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less16 (Const16 [c]) (Const16 [d]))
+ // result: (ConstBool [c < d])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ break
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c < d)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLess16U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less16U (Const16 [c]) (Const16 [d]))
+ // result: (ConstBool [uint16(c) < uint16(d)])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ break
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(uint16(c) < uint16(d))
+ return true
+ }
+ // match: (Less16U _ (Const16 [0]))
+ // result: (ConstBool [false])
+ for {
+ if v_1.Op != OpConst16 || auxIntToInt16(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLess32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less32 (Const32 [c]) (Const32 [d]))
+ // result: (ConstBool [c < d])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c < d)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLess32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less32F (Const32F [c]) (Const32F [d]))
+ // result: (ConstBool [c < d])
+ for {
+ if v_0.Op != OpConst32F {
+ break
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ if v_1.Op != OpConst32F {
+ break
+ }
+ d := auxIntToFloat32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c < d)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLess32U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less32U (Const32 [c]) (Const32 [d]))
+ // result: (ConstBool [uint32(c) < uint32(d)])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(uint32(c) < uint32(d))
+ return true
+ }
+ // match: (Less32U _ (Const32 [0]))
+ // result: (ConstBool [false])
+ for {
+ if v_1.Op != OpConst32 || auxIntToInt32(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLess64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less64 (Const64 [c]) (Const64 [d]))
+ // result: (ConstBool [c < d])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c < d)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLess64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less64F (Const64F [c]) (Const64F [d]))
+ // result: (ConstBool [c < d])
+ for {
+ if v_0.Op != OpConst64F {
+ break
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ if v_1.Op != OpConst64F {
+ break
+ }
+ d := auxIntToFloat64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c < d)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLess64U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less64U (Const64 [c]) (Const64 [d]))
+ // result: (ConstBool [uint64(c) < uint64(d)])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(uint64(c) < uint64(d))
+ return true
+ }
+ // match: (Less64U _ (Const64 [0]))
+ // result: (ConstBool [false])
+ for {
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLess8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less8 (Const8 [c]) (Const8 [d]))
+ // result: (ConstBool [c < d])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ break
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c < d)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLess8U(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Less8U (Const8 [c]) (Const8 [d]))
+ // result: (ConstBool [ uint8(c) < uint8(d)])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ break
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(uint8(c) < uint8(d))
+ return true
+ }
+ // match: (Less8U _ (Const8 [0]))
+ // result: (ConstBool [false])
+ for {
+ if v_1.Op != OpConst8 || auxIntToInt8(v_1.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLoad(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ fe := b.Func.fe
+ // match: (Load <t1> p1 (Store {t2} p2 x _))
+ // cond: isSamePtr(p1, p2) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size()
+ // result: x
+ for {
+ t1 := v.Type
+ p1 := v_0
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ x := v_1.Args[1]
+ p2 := v_1.Args[0]
+ if !(isSamePtr(p1, p2) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size()) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Load <t1> p1 (Store {t2} p2 _ (Store {t3} p3 x _)))
+ // cond: isSamePtr(p1, p3) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size() && disjoint(p3, t3.Size(), p2, t2.Size())
+ // result: x
+ for {
+ t1 := v.Type
+ p1 := v_0
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[2]
+ p2 := v_1.Args[0]
+ v_1_2 := v_1.Args[2]
+ if v_1_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(v_1_2.Aux)
+ x := v_1_2.Args[1]
+ p3 := v_1_2.Args[0]
+ if !(isSamePtr(p1, p3) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size() && disjoint(p3, t3.Size(), p2, t2.Size())) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Load <t1> p1 (Store {t2} p2 _ (Store {t3} p3 _ (Store {t4} p4 x _))))
+ // cond: isSamePtr(p1, p4) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size() && disjoint(p4, t4.Size(), p2, t2.Size()) && disjoint(p4, t4.Size(), p3, t3.Size())
+ // result: x
+ for {
+ t1 := v.Type
+ p1 := v_0
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[2]
+ p2 := v_1.Args[0]
+ v_1_2 := v_1.Args[2]
+ if v_1_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(v_1_2.Aux)
+ _ = v_1_2.Args[2]
+ p3 := v_1_2.Args[0]
+ v_1_2_2 := v_1_2.Args[2]
+ if v_1_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(v_1_2_2.Aux)
+ x := v_1_2_2.Args[1]
+ p4 := v_1_2_2.Args[0]
+ if !(isSamePtr(p1, p4) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size() && disjoint(p4, t4.Size(), p2, t2.Size()) && disjoint(p4, t4.Size(), p3, t3.Size())) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Load <t1> p1 (Store {t2} p2 _ (Store {t3} p3 _ (Store {t4} p4 _ (Store {t5} p5 x _)))))
+ // cond: isSamePtr(p1, p5) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size() && disjoint(p5, t5.Size(), p2, t2.Size()) && disjoint(p5, t5.Size(), p3, t3.Size()) && disjoint(p5, t5.Size(), p4, t4.Size())
+ // result: x
+ for {
+ t1 := v.Type
+ p1 := v_0
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[2]
+ p2 := v_1.Args[0]
+ v_1_2 := v_1.Args[2]
+ if v_1_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(v_1_2.Aux)
+ _ = v_1_2.Args[2]
+ p3 := v_1_2.Args[0]
+ v_1_2_2 := v_1_2.Args[2]
+ if v_1_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(v_1_2_2.Aux)
+ _ = v_1_2_2.Args[2]
+ p4 := v_1_2_2.Args[0]
+ v_1_2_2_2 := v_1_2_2.Args[2]
+ if v_1_2_2_2.Op != OpStore {
+ break
+ }
+ t5 := auxToType(v_1_2_2_2.Aux)
+ x := v_1_2_2_2.Args[1]
+ p5 := v_1_2_2_2.Args[0]
+ if !(isSamePtr(p1, p5) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size() && disjoint(p5, t5.Size(), p2, t2.Size()) && disjoint(p5, t5.Size(), p3, t3.Size()) && disjoint(p5, t5.Size(), p4, t4.Size())) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Load <t1> p1 (Store {t2} p2 (Const64 [x]) _))
+ // cond: isSamePtr(p1,p2) && sizeof(t2) == 8 && is64BitFloat(t1) && !math.IsNaN(math.Float64frombits(uint64(x)))
+ // result: (Const64F [math.Float64frombits(uint64(x))])
+ for {
+ t1 := v.Type
+ p1 := v_0
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[1]
+ p2 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ break
+ }
+ x := auxIntToInt64(v_1_1.AuxInt)
+ if !(isSamePtr(p1, p2) && sizeof(t2) == 8 && is64BitFloat(t1) && !math.IsNaN(math.Float64frombits(uint64(x)))) {
+ break
+ }
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(math.Float64frombits(uint64(x)))
+ return true
+ }
+ // match: (Load <t1> p1 (Store {t2} p2 (Const32 [x]) _))
+ // cond: isSamePtr(p1,p2) && sizeof(t2) == 4 && is32BitFloat(t1) && !math.IsNaN(float64(math.Float32frombits(uint32(x))))
+ // result: (Const32F [math.Float32frombits(uint32(x))])
+ for {
+ t1 := v.Type
+ p1 := v_0
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[1]
+ p2 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ break
+ }
+ x := auxIntToInt32(v_1_1.AuxInt)
+ if !(isSamePtr(p1, p2) && sizeof(t2) == 4 && is32BitFloat(t1) && !math.IsNaN(float64(math.Float32frombits(uint32(x))))) {
+ break
+ }
+ v.reset(OpConst32F)
+ v.AuxInt = float32ToAuxInt(math.Float32frombits(uint32(x)))
+ return true
+ }
+ // match: (Load <t1> p1 (Store {t2} p2 (Const64F [x]) _))
+ // cond: isSamePtr(p1,p2) && sizeof(t2) == 8 && is64BitInt(t1)
+ // result: (Const64 [int64(math.Float64bits(x))])
+ for {
+ t1 := v.Type
+ p1 := v_0
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[1]
+ p2 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64F {
+ break
+ }
+ x := auxIntToFloat64(v_1_1.AuxInt)
+ if !(isSamePtr(p1, p2) && sizeof(t2) == 8 && is64BitInt(t1)) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(math.Float64bits(x)))
+ return true
+ }
+ // match: (Load <t1> p1 (Store {t2} p2 (Const32F [x]) _))
+ // cond: isSamePtr(p1,p2) && sizeof(t2) == 4 && is32BitInt(t1)
+ // result: (Const32 [int32(math.Float32bits(x))])
+ for {
+ t1 := v.Type
+ p1 := v_0
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[1]
+ p2 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32F {
+ break
+ }
+ x := auxIntToFloat32(v_1_1.AuxInt)
+ if !(isSamePtr(p1, p2) && sizeof(t2) == 4 && is32BitInt(t1)) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(math.Float32bits(x)))
+ return true
+ }
+ // match: (Load <t1> op:(OffPtr [o1] p1) (Store {t2} p2 _ mem:(Zero [n] p3 _)))
+ // cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p3) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size())
+ // result: @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p3) mem)
+ for {
+ t1 := v.Type
+ op := v_0
+ if op.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op.AuxInt)
+ p1 := op.Args[0]
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[2]
+ p2 := v_1.Args[0]
+ mem := v_1.Args[2]
+ if mem.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(mem.AuxInt)
+ p3 := mem.Args[0]
+ if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p3) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size())) {
+ break
+ }
+ b = mem.Block
+ v0 := b.NewValue0(v.Pos, OpLoad, t1)
+ v.copyOf(v0)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, op.Type)
+ v1.AuxInt = int64ToAuxInt(o1)
+ v1.AddArg(p3)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ // match: (Load <t1> op:(OffPtr [o1] p1) (Store {t2} p2 _ (Store {t3} p3 _ mem:(Zero [n] p4 _))))
+ // cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p4) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size())
+ // result: @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p4) mem)
+ for {
+ t1 := v.Type
+ op := v_0
+ if op.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op.AuxInt)
+ p1 := op.Args[0]
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[2]
+ p2 := v_1.Args[0]
+ v_1_2 := v_1.Args[2]
+ if v_1_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(v_1_2.Aux)
+ _ = v_1_2.Args[2]
+ p3 := v_1_2.Args[0]
+ mem := v_1_2.Args[2]
+ if mem.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(mem.AuxInt)
+ p4 := mem.Args[0]
+ if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p4) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size())) {
+ break
+ }
+ b = mem.Block
+ v0 := b.NewValue0(v.Pos, OpLoad, t1)
+ v.copyOf(v0)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, op.Type)
+ v1.AuxInt = int64ToAuxInt(o1)
+ v1.AddArg(p4)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ // match: (Load <t1> op:(OffPtr [o1] p1) (Store {t2} p2 _ (Store {t3} p3 _ (Store {t4} p4 _ mem:(Zero [n] p5 _)))))
+ // cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p5) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size())
+ // result: @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p5) mem)
+ for {
+ t1 := v.Type
+ op := v_0
+ if op.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op.AuxInt)
+ p1 := op.Args[0]
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[2]
+ p2 := v_1.Args[0]
+ v_1_2 := v_1.Args[2]
+ if v_1_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(v_1_2.Aux)
+ _ = v_1_2.Args[2]
+ p3 := v_1_2.Args[0]
+ v_1_2_2 := v_1_2.Args[2]
+ if v_1_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(v_1_2_2.Aux)
+ _ = v_1_2_2.Args[2]
+ p4 := v_1_2_2.Args[0]
+ mem := v_1_2_2.Args[2]
+ if mem.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(mem.AuxInt)
+ p5 := mem.Args[0]
+ if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p5) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size())) {
+ break
+ }
+ b = mem.Block
+ v0 := b.NewValue0(v.Pos, OpLoad, t1)
+ v.copyOf(v0)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, op.Type)
+ v1.AuxInt = int64ToAuxInt(o1)
+ v1.AddArg(p5)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ // match: (Load <t1> op:(OffPtr [o1] p1) (Store {t2} p2 _ (Store {t3} p3 _ (Store {t4} p4 _ (Store {t5} p5 _ mem:(Zero [n] p6 _))))))
+ // cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p6) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size()) && disjoint(op, t1.Size(), p5, t5.Size())
+ // result: @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p6) mem)
+ for {
+ t1 := v.Type
+ op := v_0
+ if op.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op.AuxInt)
+ p1 := op.Args[0]
+ if v_1.Op != OpStore {
+ break
+ }
+ t2 := auxToType(v_1.Aux)
+ _ = v_1.Args[2]
+ p2 := v_1.Args[0]
+ v_1_2 := v_1.Args[2]
+ if v_1_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(v_1_2.Aux)
+ _ = v_1_2.Args[2]
+ p3 := v_1_2.Args[0]
+ v_1_2_2 := v_1_2.Args[2]
+ if v_1_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(v_1_2_2.Aux)
+ _ = v_1_2_2.Args[2]
+ p4 := v_1_2_2.Args[0]
+ v_1_2_2_2 := v_1_2_2.Args[2]
+ if v_1_2_2_2.Op != OpStore {
+ break
+ }
+ t5 := auxToType(v_1_2_2_2.Aux)
+ _ = v_1_2_2_2.Args[2]
+ p5 := v_1_2_2_2.Args[0]
+ mem := v_1_2_2_2.Args[2]
+ if mem.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(mem.AuxInt)
+ p6 := mem.Args[0]
+ if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p6) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size()) && disjoint(op, t1.Size(), p5, t5.Size())) {
+ break
+ }
+ b = mem.Block
+ v0 := b.NewValue0(v.Pos, OpLoad, t1)
+ v.copyOf(v0)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, op.Type)
+ v1.AuxInt = int64ToAuxInt(o1)
+ v1.AddArg(p6)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ // match: (Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ // cond: t1.IsBoolean() && isSamePtr(p1, p2) && n >= o + 1
+ // result: (ConstBool [false])
+ for {
+ t1 := v.Type
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ o := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ if v_1.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(v_1.AuxInt)
+ p2 := v_1.Args[0]
+ if !(t1.IsBoolean() && isSamePtr(p1, p2) && n >= o+1) {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ // cond: is8BitInt(t1) && isSamePtr(p1, p2) && n >= o + 1
+ // result: (Const8 [0])
+ for {
+ t1 := v.Type
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ o := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ if v_1.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(v_1.AuxInt)
+ p2 := v_1.Args[0]
+ if !(is8BitInt(t1) && isSamePtr(p1, p2) && n >= o+1) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ // match: (Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ // cond: is16BitInt(t1) && isSamePtr(p1, p2) && n >= o + 2
+ // result: (Const16 [0])
+ for {
+ t1 := v.Type
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ o := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ if v_1.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(v_1.AuxInt)
+ p2 := v_1.Args[0]
+ if !(is16BitInt(t1) && isSamePtr(p1, p2) && n >= o+2) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ // match: (Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ // cond: is32BitInt(t1) && isSamePtr(p1, p2) && n >= o + 4
+ // result: (Const32 [0])
+ for {
+ t1 := v.Type
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ o := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ if v_1.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(v_1.AuxInt)
+ p2 := v_1.Args[0]
+ if !(is32BitInt(t1) && isSamePtr(p1, p2) && n >= o+4) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ // cond: is64BitInt(t1) && isSamePtr(p1, p2) && n >= o + 8
+ // result: (Const64 [0])
+ for {
+ t1 := v.Type
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ o := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ if v_1.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(v_1.AuxInt)
+ p2 := v_1.Args[0]
+ if !(is64BitInt(t1) && isSamePtr(p1, p2) && n >= o+8) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ // cond: is32BitFloat(t1) && isSamePtr(p1, p2) && n >= o + 4
+ // result: (Const32F [0])
+ for {
+ t1 := v.Type
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ o := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ if v_1.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(v_1.AuxInt)
+ p2 := v_1.Args[0]
+ if !(is32BitFloat(t1) && isSamePtr(p1, p2) && n >= o+4) {
+ break
+ }
+ v.reset(OpConst32F)
+ v.AuxInt = float32ToAuxInt(0)
+ return true
+ }
+ // match: (Load <t1> (OffPtr [o] p1) (Zero [n] p2 _))
+ // cond: is64BitFloat(t1) && isSamePtr(p1, p2) && n >= o + 8
+ // result: (Const64F [0])
+ for {
+ t1 := v.Type
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ o := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ if v_1.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(v_1.AuxInt)
+ p2 := v_1.Args[0]
+ if !(is64BitFloat(t1) && isSamePtr(p1, p2) && n >= o+8) {
+ break
+ }
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(0)
+ return true
+ }
+ // match: (Load <t> _ _)
+ // cond: t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t)
+ // result: (StructMake0)
+ for {
+ t := v.Type
+ if !(t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpStructMake0)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t)
+ // result: (StructMake1 (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpStructMake1)
+ v0 := b.NewValue0(v.Pos, OpLoad, t.FieldType(0))
+ v1 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
+ v1.AuxInt = int64ToAuxInt(0)
+ v1.AddArg(ptr)
+ v0.AddArg2(v1, mem)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t)
+ // result: (StructMake2 (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem) (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpStructMake2)
+ v0 := b.NewValue0(v.Pos, OpLoad, t.FieldType(0))
+ v1 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
+ v1.AuxInt = int64ToAuxInt(0)
+ v1.AddArg(ptr)
+ v0.AddArg2(v1, mem)
+ v2 := b.NewValue0(v.Pos, OpLoad, t.FieldType(1))
+ v3 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(1).PtrTo())
+ v3.AuxInt = int64ToAuxInt(t.FieldOff(1))
+ v3.AddArg(ptr)
+ v2.AddArg2(v3, mem)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t)
+ // result: (StructMake3 (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem) (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem) (Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpStructMake3)
+ v0 := b.NewValue0(v.Pos, OpLoad, t.FieldType(0))
+ v1 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
+ v1.AuxInt = int64ToAuxInt(0)
+ v1.AddArg(ptr)
+ v0.AddArg2(v1, mem)
+ v2 := b.NewValue0(v.Pos, OpLoad, t.FieldType(1))
+ v3 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(1).PtrTo())
+ v3.AuxInt = int64ToAuxInt(t.FieldOff(1))
+ v3.AddArg(ptr)
+ v2.AddArg2(v3, mem)
+ v4 := b.NewValue0(v.Pos, OpLoad, t.FieldType(2))
+ v5 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(2).PtrTo())
+ v5.AuxInt = int64ToAuxInt(t.FieldOff(2))
+ v5.AddArg(ptr)
+ v4.AddArg2(v5, mem)
+ v.AddArg3(v0, v2, v4)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t)
+ // result: (StructMake4 (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem) (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem) (Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem) (Load <t.FieldType(3)> (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] ptr) mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpStructMake4)
+ v0 := b.NewValue0(v.Pos, OpLoad, t.FieldType(0))
+ v1 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
+ v1.AuxInt = int64ToAuxInt(0)
+ v1.AddArg(ptr)
+ v0.AddArg2(v1, mem)
+ v2 := b.NewValue0(v.Pos, OpLoad, t.FieldType(1))
+ v3 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(1).PtrTo())
+ v3.AuxInt = int64ToAuxInt(t.FieldOff(1))
+ v3.AddArg(ptr)
+ v2.AddArg2(v3, mem)
+ v4 := b.NewValue0(v.Pos, OpLoad, t.FieldType(2))
+ v5 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(2).PtrTo())
+ v5.AuxInt = int64ToAuxInt(t.FieldOff(2))
+ v5.AddArg(ptr)
+ v4.AddArg2(v5, mem)
+ v6 := b.NewValue0(v.Pos, OpLoad, t.FieldType(3))
+ v7 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(3).PtrTo())
+ v7.AuxInt = int64ToAuxInt(t.FieldOff(3))
+ v7.AddArg(ptr)
+ v6.AddArg2(v7, mem)
+ v.AddArg4(v0, v2, v4, v6)
+ return true
+ }
+ // match: (Load <t> _ _)
+ // cond: t.IsArray() && t.NumElem() == 0
+ // result: (ArrayMake0)
+ for {
+ t := v.Type
+ if !(t.IsArray() && t.NumElem() == 0) {
+ break
+ }
+ v.reset(OpArrayMake0)
+ return true
+ }
+ // match: (Load <t> ptr mem)
+ // cond: t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t)
+ // result: (ArrayMake1 (Load <t.Elem()> ptr mem))
+ for {
+ t := v.Type
+ ptr := v_0
+ mem := v_1
+ if !(t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpArrayMake1)
+ v0 := b.NewValue0(v.Pos, OpLoad, t.Elem())
+ v0.AddArg2(ptr, mem)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x16 <t> x (Const16 [c]))
+ // result: (Lsh16x64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpLsh16x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh16x16 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x32 <t> x (Const32 [c]))
+ // result: (Lsh16x64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpLsh16x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh16x32 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh16x64 (Const16 [c]) (Const64 [d]))
+ // result: (Const16 [c << uint64(d)])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c << uint64(d))
+ return true
+ }
+ // match: (Lsh16x64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Lsh16x64 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh16x64 _ (Const64 [c]))
+ // cond: uint64(c) >= 16
+ // result: (Const16 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh16x64 <t> (Lsh16x64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Lsh16x64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpLsh16x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpLsh16x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh16x64 (Rsh16Ux64 (Lsh16x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
+ // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
+ // result: (Lsh16x64 x (Const64 <typ.UInt64> [c1-c2+c3]))
+ for {
+ if v_0.Op != OpRsh16Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLsh16x64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c1 := auxIntToInt64(v_0_0_1.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c2 := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c3 := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) {
+ break
+ }
+ v.reset(OpLsh16x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(c1 - c2 + c3)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh16x8 <t> x (Const8 [c]))
+ // result: (Lsh16x64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpLsh16x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh16x8 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x16 <t> x (Const16 [c]))
+ // result: (Lsh32x64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpLsh32x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh32x16 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x32 <t> x (Const32 [c]))
+ // result: (Lsh32x64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpLsh32x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh32x32 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh32x64 (Const32 [c]) (Const64 [d]))
+ // result: (Const32 [c << uint64(d)])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c << uint64(d))
+ return true
+ }
+ // match: (Lsh32x64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Lsh32x64 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh32x64 _ (Const64 [c]))
+ // cond: uint64(c) >= 32
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh32x64 <t> (Lsh32x64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Lsh32x64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpLsh32x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpLsh32x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh32x64 (Rsh32Ux64 (Lsh32x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
+ // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
+ // result: (Lsh32x64 x (Const64 <typ.UInt64> [c1-c2+c3]))
+ for {
+ if v_0.Op != OpRsh32Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLsh32x64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c1 := auxIntToInt64(v_0_0_1.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c2 := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c3 := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) {
+ break
+ }
+ v.reset(OpLsh32x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(c1 - c2 + c3)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh32x8 <t> x (Const8 [c]))
+ // result: (Lsh32x64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpLsh32x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh32x8 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh64x16 <t> x (Const16 [c]))
+ // result: (Lsh64x64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpLsh64x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh64x16 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh64x32 <t> x (Const32 [c]))
+ // result: (Lsh64x64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpLsh64x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh64x32 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh64x64 (Const64 [c]) (Const64 [d]))
+ // result: (Const64 [c << uint64(d)])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c << uint64(d))
+ return true
+ }
+ // match: (Lsh64x64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Lsh64x64 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh64x64 _ (Const64 [c]))
+ // cond: uint64(c) >= 64
+ // result: (Const64 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh64x64 <t> (Lsh64x64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Lsh64x64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpLsh64x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpLsh64x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh64x64 (Rsh64Ux64 (Lsh64x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
+ // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
+ // result: (Lsh64x64 x (Const64 <typ.UInt64> [c1-c2+c3]))
+ for {
+ if v_0.Op != OpRsh64Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLsh64x64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c1 := auxIntToInt64(v_0_0_1.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c2 := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c3 := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) {
+ break
+ }
+ v.reset(OpLsh64x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(c1 - c2 + c3)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh64x8 <t> x (Const8 [c]))
+ // result: (Lsh64x64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpLsh64x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh64x8 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x16 <t> x (Const16 [c]))
+ // result: (Lsh8x64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpLsh8x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh8x16 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x32 <t> x (Const32 [c]))
+ // result: (Lsh8x64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpLsh8x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh8x32 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Lsh8x64 (Const8 [c]) (Const64 [d]))
+ // result: (Const8 [c << uint64(d)])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c << uint64(d))
+ return true
+ }
+ // match: (Lsh8x64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Lsh8x64 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh8x64 _ (Const64 [c]))
+ // cond: uint64(c) >= 8
+ // result: (Const8 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ // match: (Lsh8x64 <t> (Lsh8x64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Lsh8x64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpLsh8x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpLsh8x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh8x64 (Rsh8Ux64 (Lsh8x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
+ // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
+ // result: (Lsh8x64 x (Const64 <typ.UInt64> [c1-c2+c3]))
+ for {
+ if v_0.Op != OpRsh8Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLsh8x64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c1 := auxIntToInt64(v_0_0_1.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c2 := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c3 := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) {
+ break
+ }
+ v.reset(OpLsh8x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(c1 - c2 + c3)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpLsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Lsh8x8 <t> x (Const8 [c]))
+ // result: (Lsh8x64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpLsh8x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Lsh8x8 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpMod16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Mod16 (Const16 [c]) (Const16 [d]))
+ // cond: d != 0
+ // result: (Const16 [c % d])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ break
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c % d)
+ return true
+ }
+ // match: (Mod16 <t> n (Const16 [c]))
+ // cond: isNonNegative(n) && isPowerOfTwo16(c)
+ // result: (And16 n (Const16 <t> [c-1]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(isNonNegative(n) && isPowerOfTwo16(c)) {
+ break
+ }
+ v.reset(OpAnd16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c - 1)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod16 <t> n (Const16 [c]))
+ // cond: c < 0 && c != -1<<15
+ // result: (Mod16 <t> n (Const16 <t> [-c]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(c < 0 && c != -1<<15) {
+ break
+ }
+ v.reset(OpMod16)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(-c)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod16 <t> x (Const16 [c]))
+ // cond: x.Op != OpConst16 && (c > 0 || c == -1<<15)
+ // result: (Sub16 x (Mul16 <t> (Div16 <t> x (Const16 <t> [c])) (Const16 <t> [c])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(x.Op != OpConst16 && (c > 0 || c == -1<<15)) {
+ break
+ }
+ v.reset(OpSub16)
+ v0 := b.NewValue0(v.Pos, OpMul16, t)
+ v1 := b.NewValue0(v.Pos, OpDiv16, t)
+ v2 := b.NewValue0(v.Pos, OpConst16, t)
+ v2.AuxInt = int16ToAuxInt(c)
+ v1.AddArg2(x, v2)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpMod16u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Mod16u (Const16 [c]) (Const16 [d]))
+ // cond: d != 0
+ // result: (Const16 [int16(uint16(c) % uint16(d))])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ break
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(int16(uint16(c) % uint16(d)))
+ return true
+ }
+ // match: (Mod16u <t> n (Const16 [c]))
+ // cond: isPowerOfTwo16(c)
+ // result: (And16 n (Const16 <t> [c-1]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(isPowerOfTwo16(c)) {
+ break
+ }
+ v.reset(OpAnd16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c - 1)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod16u <t> x (Const16 [c]))
+ // cond: x.Op != OpConst16 && c > 0 && umagicOK16(c)
+ // result: (Sub16 x (Mul16 <t> (Div16u <t> x (Const16 <t> [c])) (Const16 <t> [c])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(x.Op != OpConst16 && c > 0 && umagicOK16(c)) {
+ break
+ }
+ v.reset(OpSub16)
+ v0 := b.NewValue0(v.Pos, OpMul16, t)
+ v1 := b.NewValue0(v.Pos, OpDiv16u, t)
+ v2 := b.NewValue0(v.Pos, OpConst16, t)
+ v2.AuxInt = int16ToAuxInt(c)
+ v1.AddArg2(x, v2)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpMod32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Mod32 (Const32 [c]) (Const32 [d]))
+ // cond: d != 0
+ // result: (Const32 [c % d])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c % d)
+ return true
+ }
+ // match: (Mod32 <t> n (Const32 [c]))
+ // cond: isNonNegative(n) && isPowerOfTwo32(c)
+ // result: (And32 n (Const32 <t> [c-1]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(isNonNegative(n) && isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpAnd32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c - 1)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod32 <t> n (Const32 [c]))
+ // cond: c < 0 && c != -1<<31
+ // result: (Mod32 <t> n (Const32 <t> [-c]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c < 0 && c != -1<<31) {
+ break
+ }
+ v.reset(OpMod32)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(-c)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod32 <t> x (Const32 [c]))
+ // cond: x.Op != OpConst32 && (c > 0 || c == -1<<31)
+ // result: (Sub32 x (Mul32 <t> (Div32 <t> x (Const32 <t> [c])) (Const32 <t> [c])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(x.Op != OpConst32 && (c > 0 || c == -1<<31)) {
+ break
+ }
+ v.reset(OpSub32)
+ v0 := b.NewValue0(v.Pos, OpMul32, t)
+ v1 := b.NewValue0(v.Pos, OpDiv32, t)
+ v2 := b.NewValue0(v.Pos, OpConst32, t)
+ v2.AuxInt = int32ToAuxInt(c)
+ v1.AddArg2(x, v2)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpMod32u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Mod32u (Const32 [c]) (Const32 [d]))
+ // cond: d != 0
+ // result: (Const32 [int32(uint32(c) % uint32(d))])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) % uint32(d)))
+ return true
+ }
+ // match: (Mod32u <t> n (Const32 [c]))
+ // cond: isPowerOfTwo32(c)
+ // result: (And32 n (Const32 <t> [c-1]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(isPowerOfTwo32(c)) {
+ break
+ }
+ v.reset(OpAnd32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c - 1)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod32u <t> x (Const32 [c]))
+ // cond: x.Op != OpConst32 && c > 0 && umagicOK32(c)
+ // result: (Sub32 x (Mul32 <t> (Div32u <t> x (Const32 <t> [c])) (Const32 <t> [c])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(x.Op != OpConst32 && c > 0 && umagicOK32(c)) {
+ break
+ }
+ v.reset(OpSub32)
+ v0 := b.NewValue0(v.Pos, OpMul32, t)
+ v1 := b.NewValue0(v.Pos, OpDiv32u, t)
+ v2 := b.NewValue0(v.Pos, OpConst32, t)
+ v2.AuxInt = int32ToAuxInt(c)
+ v1.AddArg2(x, v2)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpMod64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Mod64 (Const64 [c]) (Const64 [d]))
+ // cond: d != 0
+ // result: (Const64 [c % d])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c % d)
+ return true
+ }
+ // match: (Mod64 <t> n (Const64 [c]))
+ // cond: isNonNegative(n) && isPowerOfTwo64(c)
+ // result: (And64 n (Const64 <t> [c-1]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isNonNegative(n) && isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpAnd64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c - 1)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod64 n (Const64 [-1<<63]))
+ // cond: isNonNegative(n)
+ // result: n
+ for {
+ n := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != -1<<63 || !(isNonNegative(n)) {
+ break
+ }
+ v.copyOf(n)
+ return true
+ }
+ // match: (Mod64 <t> n (Const64 [c]))
+ // cond: c < 0 && c != -1<<63
+ // result: (Mod64 <t> n (Const64 <t> [-c]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c < 0 && c != -1<<63) {
+ break
+ }
+ v.reset(OpMod64)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(-c)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod64 <t> x (Const64 [c]))
+ // cond: x.Op != OpConst64 && (c > 0 || c == -1<<63)
+ // result: (Sub64 x (Mul64 <t> (Div64 <t> x (Const64 <t> [c])) (Const64 <t> [c])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(x.Op != OpConst64 && (c > 0 || c == -1<<63)) {
+ break
+ }
+ v.reset(OpSub64)
+ v0 := b.NewValue0(v.Pos, OpMul64, t)
+ v1 := b.NewValue0(v.Pos, OpDiv64, t)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(c)
+ v1.AddArg2(x, v2)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpMod64u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Mod64u (Const64 [c]) (Const64 [d]))
+ // cond: d != 0
+ // result: (Const64 [int64(uint64(c) % uint64(d))])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d)))
+ return true
+ }
+ // match: (Mod64u <t> n (Const64 [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (And64 n (Const64 <t> [c-1]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ break
+ }
+ v.reset(OpAnd64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c - 1)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod64u <t> n (Const64 [-1<<63]))
+ // result: (And64 n (Const64 <t> [1<<63-1]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != -1<<63 {
+ break
+ }
+ v.reset(OpAnd64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(1<<63 - 1)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod64u <t> x (Const64 [c]))
+ // cond: x.Op != OpConst64 && c > 0 && umagicOK64(c)
+ // result: (Sub64 x (Mul64 <t> (Div64u <t> x (Const64 <t> [c])) (Const64 <t> [c])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(x.Op != OpConst64 && c > 0 && umagicOK64(c)) {
+ break
+ }
+ v.reset(OpSub64)
+ v0 := b.NewValue0(v.Pos, OpMul64, t)
+ v1 := b.NewValue0(v.Pos, OpDiv64u, t)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(c)
+ v1.AddArg2(x, v2)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpMod8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Mod8 (Const8 [c]) (Const8 [d]))
+ // cond: d != 0
+ // result: (Const8 [c % d])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ break
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c % d)
+ return true
+ }
+ // match: (Mod8 <t> n (Const8 [c]))
+ // cond: isNonNegative(n) && isPowerOfTwo8(c)
+ // result: (And8 n (Const8 <t> [c-1]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(isNonNegative(n) && isPowerOfTwo8(c)) {
+ break
+ }
+ v.reset(OpAnd8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c - 1)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod8 <t> n (Const8 [c]))
+ // cond: c < 0 && c != -1<<7
+ // result: (Mod8 <t> n (Const8 <t> [-c]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(c < 0 && c != -1<<7) {
+ break
+ }
+ v.reset(OpMod8)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(-c)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod8 <t> x (Const8 [c]))
+ // cond: x.Op != OpConst8 && (c > 0 || c == -1<<7)
+ // result: (Sub8 x (Mul8 <t> (Div8 <t> x (Const8 <t> [c])) (Const8 <t> [c])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(x.Op != OpConst8 && (c > 0 || c == -1<<7)) {
+ break
+ }
+ v.reset(OpSub8)
+ v0 := b.NewValue0(v.Pos, OpMul8, t)
+ v1 := b.NewValue0(v.Pos, OpDiv8, t)
+ v2 := b.NewValue0(v.Pos, OpConst8, t)
+ v2.AuxInt = int8ToAuxInt(c)
+ v1.AddArg2(x, v2)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpMod8u(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Mod8u (Const8 [c]) (Const8 [d]))
+ // cond: d != 0
+ // result: (Const8 [int8(uint8(c) % uint8(d))])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ break
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(int8(uint8(c) % uint8(d)))
+ return true
+ }
+ // match: (Mod8u <t> n (Const8 [c]))
+ // cond: isPowerOfTwo8(c)
+ // result: (And8 n (Const8 <t> [c-1]))
+ for {
+ t := v.Type
+ n := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(isPowerOfTwo8(c)) {
+ break
+ }
+ v.reset(OpAnd8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c - 1)
+ v.AddArg2(n, v0)
+ return true
+ }
+ // match: (Mod8u <t> x (Const8 [c]))
+ // cond: x.Op != OpConst8 && c > 0 && umagicOK8( c)
+ // result: (Sub8 x (Mul8 <t> (Div8u <t> x (Const8 <t> [c])) (Const8 <t> [c])))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(x.Op != OpConst8 && c > 0 && umagicOK8(c)) {
+ break
+ }
+ v.reset(OpSub8)
+ v0 := b.NewValue0(v.Pos, OpMul8, t)
+ v1 := b.NewValue0(v.Pos, OpDiv8u, t)
+ v2 := b.NewValue0(v.Pos, OpConst8, t)
+ v2.AuxInt = int8ToAuxInt(c)
+ v1.AddArg2(x, v2)
+ v0.AddArg2(v1, v2)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpMove(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (Move {t} [n] dst1 src mem:(Zero {t} [n] dst2 _))
+ // cond: isSamePtr(src, dst2)
+ // result: (Zero {t} [n] dst1 mem)
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst1 := v_0
+ src := v_1
+ mem := v_2
+ if mem.Op != OpZero || auxIntToInt64(mem.AuxInt) != n || auxToType(mem.Aux) != t {
+ break
+ }
+ dst2 := mem.Args[0]
+ if !(isSamePtr(src, dst2)) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t)
+ v.AddArg2(dst1, mem)
+ return true
+ }
+ // match: (Move {t} [n] dst1 src mem:(VarDef (Zero {t} [n] dst0 _)))
+ // cond: isSamePtr(src, dst0)
+ // result: (Zero {t} [n] dst1 mem)
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst1 := v_0
+ src := v_1
+ mem := v_2
+ if mem.Op != OpVarDef {
+ break
+ }
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpZero || auxIntToInt64(mem_0.AuxInt) != n || auxToType(mem_0.Aux) != t {
+ break
+ }
+ dst0 := mem_0.Args[0]
+ if !(isSamePtr(src, dst0)) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t)
+ v.AddArg2(dst1, mem)
+ return true
+ }
+ // match: (Move {t} [n] dst (Addr {sym} (SB)) mem)
+ // cond: symIsROZero(sym)
+ // result: (Zero {t} [n] dst mem)
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst := v_0
+ if v_1.Op != OpAddr {
+ break
+ }
+ sym := auxToSym(v_1.Aux)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpSB {
+ break
+ }
+ mem := v_2
+ if !(symIsROZero(sym)) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t)
+ v.AddArg2(dst, mem)
+ return true
+ }
+ // match: (Move {t1} [n] dst1 src1 store:(Store {t2} op:(OffPtr [o2] dst2) _ mem))
+ // cond: isSamePtr(dst1, dst2) && store.Uses == 1 && n >= o2 + t2.Size() && disjoint(src1, n, op, t2.Size()) && clobber(store)
+ // result: (Move {t1} [n] dst1 src1 mem)
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst1 := v_0
+ src1 := v_1
+ store := v_2
+ if store.Op != OpStore {
+ break
+ }
+ t2 := auxToType(store.Aux)
+ mem := store.Args[2]
+ op := store.Args[0]
+ if op.Op != OpOffPtr {
+ break
+ }
+ o2 := auxIntToInt64(op.AuxInt)
+ dst2 := op.Args[0]
+ if !(isSamePtr(dst1, dst2) && store.Uses == 1 && n >= o2+t2.Size() && disjoint(src1, n, op, t2.Size()) && clobber(store)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t1)
+ v.AddArg3(dst1, src1, mem)
+ return true
+ }
+ // match: (Move {t} [n] dst1 src1 move:(Move {t} [n] dst2 _ mem))
+ // cond: move.Uses == 1 && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n) && clobber(move)
+ // result: (Move {t} [n] dst1 src1 mem)
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst1 := v_0
+ src1 := v_1
+ move := v_2
+ if move.Op != OpMove || auxIntToInt64(move.AuxInt) != n || auxToType(move.Aux) != t {
+ break
+ }
+ mem := move.Args[2]
+ dst2 := move.Args[0]
+ if !(move.Uses == 1 && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n) && clobber(move)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t)
+ v.AddArg3(dst1, src1, mem)
+ return true
+ }
+ // match: (Move {t} [n] dst1 src1 vardef:(VarDef {x} move:(Move {t} [n] dst2 _ mem)))
+ // cond: move.Uses == 1 && vardef.Uses == 1 && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n) && clobber(move, vardef)
+ // result: (Move {t} [n] dst1 src1 (VarDef {x} mem))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst1 := v_0
+ src1 := v_1
+ vardef := v_2
+ if vardef.Op != OpVarDef {
+ break
+ }
+ x := auxToSym(vardef.Aux)
+ move := vardef.Args[0]
+ if move.Op != OpMove || auxIntToInt64(move.AuxInt) != n || auxToType(move.Aux) != t {
+ break
+ }
+ mem := move.Args[2]
+ dst2 := move.Args[0]
+ if !(move.Uses == 1 && vardef.Uses == 1 && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n) && clobber(move, vardef)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t)
+ v0 := b.NewValue0(v.Pos, OpVarDef, types.TypeMem)
+ v0.Aux = symToAux(x)
+ v0.AddArg(mem)
+ v.AddArg3(dst1, src1, v0)
+ return true
+ }
+ // match: (Move {t} [n] dst1 src1 zero:(Zero {t} [n] dst2 mem))
+ // cond: zero.Uses == 1 && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n) && clobber(zero)
+ // result: (Move {t} [n] dst1 src1 mem)
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst1 := v_0
+ src1 := v_1
+ zero := v_2
+ if zero.Op != OpZero || auxIntToInt64(zero.AuxInt) != n || auxToType(zero.Aux) != t {
+ break
+ }
+ mem := zero.Args[1]
+ dst2 := zero.Args[0]
+ if !(zero.Uses == 1 && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n) && clobber(zero)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t)
+ v.AddArg3(dst1, src1, mem)
+ return true
+ }
+ // match: (Move {t} [n] dst1 src1 vardef:(VarDef {x} zero:(Zero {t} [n] dst2 mem)))
+ // cond: zero.Uses == 1 && vardef.Uses == 1 && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n) && clobber(zero, vardef)
+ // result: (Move {t} [n] dst1 src1 (VarDef {x} mem))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst1 := v_0
+ src1 := v_1
+ vardef := v_2
+ if vardef.Op != OpVarDef {
+ break
+ }
+ x := auxToSym(vardef.Aux)
+ zero := vardef.Args[0]
+ if zero.Op != OpZero || auxIntToInt64(zero.AuxInt) != n || auxToType(zero.Aux) != t {
+ break
+ }
+ mem := zero.Args[1]
+ dst2 := zero.Args[0]
+ if !(zero.Uses == 1 && vardef.Uses == 1 && isSamePtr(dst1, dst2) && disjoint(src1, n, dst2, n) && clobber(zero, vardef)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t)
+ v0 := b.NewValue0(v.Pos, OpVarDef, types.TypeMem)
+ v0.Aux = symToAux(x)
+ v0.AddArg(mem)
+ v.AddArg3(dst1, src1, v0)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _)))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && o2 == t3.Size() && n == t2.Size() + t3.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ op2 := mem.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ tt2 := op2.Type
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d1 := mem.Args[1]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_2.Aux)
+ d2 := mem_2.Args[1]
+ op3 := mem_2.Args[0]
+ if op3.Op != OpOffPtr {
+ break
+ }
+ tt3 := op3.Type
+ if auxIntToInt64(op3.AuxInt) != 0 {
+ break
+ }
+ p3 := op3.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && o2 == t3.Size() && n == t2.Size()+t3.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(0)
+ v2.AddArg(dst)
+ v1.AddArg3(v2, d2, mem)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && o3 == t4.Size() && o2-o3 == t3.Size() && n == t2.Size() + t3.Size() + t4.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ op2 := mem.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ tt2 := op2.Type
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d1 := mem.Args[1]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_2.Aux)
+ _ = mem_2.Args[2]
+ op3 := mem_2.Args[0]
+ if op3.Op != OpOffPtr {
+ break
+ }
+ tt3 := op3.Type
+ o3 := auxIntToInt64(op3.AuxInt)
+ p3 := op3.Args[0]
+ d2 := mem_2.Args[1]
+ mem_2_2 := mem_2.Args[2]
+ if mem_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_2_2.Aux)
+ d3 := mem_2_2.Args[1]
+ op4 := mem_2_2.Args[0]
+ if op4.Op != OpOffPtr {
+ break
+ }
+ tt4 := op4.Type
+ if auxIntToInt64(op4.AuxInt) != 0 {
+ break
+ }
+ p4 := op4.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && o3 == t4.Size() && o2-o3 == t3.Size() && n == t2.Size()+t3.Size()+t4.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(o3)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t4)
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
+ v4.AuxInt = int64ToAuxInt(0)
+ v4.AddArg(dst)
+ v3.AddArg3(v4, d3, mem)
+ v1.AddArg3(v2, d2, v3)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3 (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _)))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && o4 == t5.Size() && o3-o4 == t4.Size() && o2-o3 == t3.Size() && n == t2.Size() + t3.Size() + t4.Size() + t5.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ op2 := mem.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ tt2 := op2.Type
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d1 := mem.Args[1]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_2.Aux)
+ _ = mem_2.Args[2]
+ op3 := mem_2.Args[0]
+ if op3.Op != OpOffPtr {
+ break
+ }
+ tt3 := op3.Type
+ o3 := auxIntToInt64(op3.AuxInt)
+ p3 := op3.Args[0]
+ d2 := mem_2.Args[1]
+ mem_2_2 := mem_2.Args[2]
+ if mem_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_2_2.Aux)
+ _ = mem_2_2.Args[2]
+ op4 := mem_2_2.Args[0]
+ if op4.Op != OpOffPtr {
+ break
+ }
+ tt4 := op4.Type
+ o4 := auxIntToInt64(op4.AuxInt)
+ p4 := op4.Args[0]
+ d3 := mem_2_2.Args[1]
+ mem_2_2_2 := mem_2_2.Args[2]
+ if mem_2_2_2.Op != OpStore {
+ break
+ }
+ t5 := auxToType(mem_2_2_2.Aux)
+ d4 := mem_2_2_2.Args[1]
+ op5 := mem_2_2_2.Args[0]
+ if op5.Op != OpOffPtr {
+ break
+ }
+ tt5 := op5.Type
+ if auxIntToInt64(op5.AuxInt) != 0 {
+ break
+ }
+ p5 := op5.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && o4 == t5.Size() && o3-o4 == t4.Size() && o2-o3 == t3.Size() && n == t2.Size()+t3.Size()+t4.Size()+t5.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(o3)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t4)
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
+ v4.AuxInt = int64ToAuxInt(o4)
+ v4.AddArg(dst)
+ v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v5.Aux = typeToAux(t5)
+ v6 := b.NewValue0(v.Pos, OpOffPtr, tt5)
+ v6.AuxInt = int64ToAuxInt(0)
+ v6.AddArg(dst)
+ v5.AddArg3(v6, d4, mem)
+ v3.AddArg3(v4, d3, v5)
+ v1.AddArg3(v2, d2, v3)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && o2 == t3.Size() && n == t2.Size() + t3.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpVarDef {
+ break
+ }
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem_0.Aux)
+ _ = mem_0.Args[2]
+ op2 := mem_0.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ tt2 := op2.Type
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d1 := mem_0.Args[1]
+ mem_0_2 := mem_0.Args[2]
+ if mem_0_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_0_2.Aux)
+ d2 := mem_0_2.Args[1]
+ op3 := mem_0_2.Args[0]
+ if op3.Op != OpOffPtr {
+ break
+ }
+ tt3 := op3.Type
+ if auxIntToInt64(op3.AuxInt) != 0 {
+ break
+ }
+ p3 := op3.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && o2 == t3.Size() && n == t2.Size()+t3.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(0)
+ v2.AddArg(dst)
+ v1.AddArg3(v2, d2, mem)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _)))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && o3 == t4.Size() && o2-o3 == t3.Size() && n == t2.Size() + t3.Size() + t4.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpVarDef {
+ break
+ }
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem_0.Aux)
+ _ = mem_0.Args[2]
+ op2 := mem_0.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ tt2 := op2.Type
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d1 := mem_0.Args[1]
+ mem_0_2 := mem_0.Args[2]
+ if mem_0_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_0_2.Aux)
+ _ = mem_0_2.Args[2]
+ op3 := mem_0_2.Args[0]
+ if op3.Op != OpOffPtr {
+ break
+ }
+ tt3 := op3.Type
+ o3 := auxIntToInt64(op3.AuxInt)
+ p3 := op3.Args[0]
+ d2 := mem_0_2.Args[1]
+ mem_0_2_2 := mem_0_2.Args[2]
+ if mem_0_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_0_2_2.Aux)
+ d3 := mem_0_2_2.Args[1]
+ op4 := mem_0_2_2.Args[0]
+ if op4.Op != OpOffPtr {
+ break
+ }
+ tt4 := op4.Type
+ if auxIntToInt64(op4.AuxInt) != 0 {
+ break
+ }
+ p4 := op4.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && o3 == t4.Size() && o2-o3 == t3.Size() && n == t2.Size()+t3.Size()+t4.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(o3)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t4)
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
+ v4.AuxInt = int64ToAuxInt(0)
+ v4.AddArg(dst)
+ v3.AddArg3(v4, d3, mem)
+ v1.AddArg3(v2, d2, v3)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3 (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _))))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && o4 == t5.Size() && o3-o4 == t4.Size() && o2-o3 == t3.Size() && n == t2.Size() + t3.Size() + t4.Size() + t5.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpVarDef {
+ break
+ }
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem_0.Aux)
+ _ = mem_0.Args[2]
+ op2 := mem_0.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ tt2 := op2.Type
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d1 := mem_0.Args[1]
+ mem_0_2 := mem_0.Args[2]
+ if mem_0_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_0_2.Aux)
+ _ = mem_0_2.Args[2]
+ op3 := mem_0_2.Args[0]
+ if op3.Op != OpOffPtr {
+ break
+ }
+ tt3 := op3.Type
+ o3 := auxIntToInt64(op3.AuxInt)
+ p3 := op3.Args[0]
+ d2 := mem_0_2.Args[1]
+ mem_0_2_2 := mem_0_2.Args[2]
+ if mem_0_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_0_2_2.Aux)
+ _ = mem_0_2_2.Args[2]
+ op4 := mem_0_2_2.Args[0]
+ if op4.Op != OpOffPtr {
+ break
+ }
+ tt4 := op4.Type
+ o4 := auxIntToInt64(op4.AuxInt)
+ p4 := op4.Args[0]
+ d3 := mem_0_2_2.Args[1]
+ mem_0_2_2_2 := mem_0_2_2.Args[2]
+ if mem_0_2_2_2.Op != OpStore {
+ break
+ }
+ t5 := auxToType(mem_0_2_2_2.Aux)
+ d4 := mem_0_2_2_2.Args[1]
+ op5 := mem_0_2_2_2.Args[0]
+ if op5.Op != OpOffPtr {
+ break
+ }
+ tt5 := op5.Type
+ if auxIntToInt64(op5.AuxInt) != 0 {
+ break
+ }
+ p5 := op5.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && o4 == t5.Size() && o3-o4 == t4.Size() && o2-o3 == t3.Size() && n == t2.Size()+t3.Size()+t4.Size()+t5.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(o3)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t4)
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
+ v4.AuxInt = int64ToAuxInt(o4)
+ v4.AddArg(dst)
+ v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v5.Aux = typeToAux(t5)
+ v6 := b.NewValue0(v.Pos, OpOffPtr, tt5)
+ v6.AuxInt = int64ToAuxInt(0)
+ v6.AddArg(dst)
+ v5.AddArg3(v6, d4, mem)
+ v3.AddArg3(v4, d3, v5)
+ v1.AddArg3(v2, d2, v3)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Zero {t3} [n] p3 _)))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && registerizable(b, t2) && n >= o2 + t2.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Zero {t1} [n] dst mem))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ op2 := mem.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ tt2 := op2.Type
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d1 := mem.Args[1]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpZero || auxIntToInt64(mem_2.AuxInt) != n {
+ break
+ }
+ t3 := auxToType(mem_2.Aux)
+ p3 := mem_2.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && registerizable(b, t2) && n >= o2+t2.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
+ v1.AuxInt = int64ToAuxInt(n)
+ v1.Aux = typeToAux(t1)
+ v1.AddArg2(dst, mem)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(Store {t2} (OffPtr <tt2> [o2] p2) d1 (Store {t3} (OffPtr <tt3> [o3] p3) d2 (Zero {t4} [n] p4 _))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && n >= o2 + t2.Size() && n >= o3 + t3.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Zero {t1} [n] dst mem)))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpOffPtr {
+ break
+ }
+ tt2 := mem_0.Type
+ o2 := auxIntToInt64(mem_0.AuxInt)
+ p2 := mem_0.Args[0]
+ d1 := mem.Args[1]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_2.Aux)
+ _ = mem_2.Args[2]
+ mem_2_0 := mem_2.Args[0]
+ if mem_2_0.Op != OpOffPtr {
+ break
+ }
+ tt3 := mem_2_0.Type
+ o3 := auxIntToInt64(mem_2_0.AuxInt)
+ p3 := mem_2_0.Args[0]
+ d2 := mem_2.Args[1]
+ mem_2_2 := mem_2.Args[2]
+ if mem_2_2.Op != OpZero || auxIntToInt64(mem_2_2.AuxInt) != n {
+ break
+ }
+ t4 := auxToType(mem_2_2.Aux)
+ p4 := mem_2_2.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && n >= o2+t2.Size() && n >= o3+t3.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(o3)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
+ v3.AuxInt = int64ToAuxInt(n)
+ v3.Aux = typeToAux(t1)
+ v3.AddArg2(dst, mem)
+ v1.AddArg3(v2, d2, v3)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(Store {t2} (OffPtr <tt2> [o2] p2) d1 (Store {t3} (OffPtr <tt3> [o3] p3) d2 (Store {t4} (OffPtr <tt4> [o4] p4) d3 (Zero {t5} [n] p5 _)))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && n >= o2 + t2.Size() && n >= o3 + t3.Size() && n >= o4 + t4.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Zero {t1} [n] dst mem))))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpOffPtr {
+ break
+ }
+ tt2 := mem_0.Type
+ o2 := auxIntToInt64(mem_0.AuxInt)
+ p2 := mem_0.Args[0]
+ d1 := mem.Args[1]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_2.Aux)
+ _ = mem_2.Args[2]
+ mem_2_0 := mem_2.Args[0]
+ if mem_2_0.Op != OpOffPtr {
+ break
+ }
+ tt3 := mem_2_0.Type
+ o3 := auxIntToInt64(mem_2_0.AuxInt)
+ p3 := mem_2_0.Args[0]
+ d2 := mem_2.Args[1]
+ mem_2_2 := mem_2.Args[2]
+ if mem_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_2_2.Aux)
+ _ = mem_2_2.Args[2]
+ mem_2_2_0 := mem_2_2.Args[0]
+ if mem_2_2_0.Op != OpOffPtr {
+ break
+ }
+ tt4 := mem_2_2_0.Type
+ o4 := auxIntToInt64(mem_2_2_0.AuxInt)
+ p4 := mem_2_2_0.Args[0]
+ d3 := mem_2_2.Args[1]
+ mem_2_2_2 := mem_2_2.Args[2]
+ if mem_2_2_2.Op != OpZero || auxIntToInt64(mem_2_2_2.AuxInt) != n {
+ break
+ }
+ t5 := auxToType(mem_2_2_2.Aux)
+ p5 := mem_2_2_2.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && n >= o2+t2.Size() && n >= o3+t3.Size() && n >= o4+t4.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(o3)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t4)
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
+ v4.AuxInt = int64ToAuxInt(o4)
+ v4.AddArg(dst)
+ v5 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
+ v5.AuxInt = int64ToAuxInt(n)
+ v5.Aux = typeToAux(t1)
+ v5.AddArg2(dst, mem)
+ v3.AddArg3(v4, d3, v5)
+ v1.AddArg3(v2, d2, v3)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(Store {t2} (OffPtr <tt2> [o2] p2) d1 (Store {t3} (OffPtr <tt3> [o3] p3) d2 (Store {t4} (OffPtr <tt4> [o4] p4) d3 (Store {t5} (OffPtr <tt5> [o5] p5) d4 (Zero {t6} [n] p6 _))))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && isSamePtr(p5, p6) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && t6.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && n >= o2 + t2.Size() && n >= o3 + t3.Size() && n >= o4 + t4.Size() && n >= o5 + t5.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [o5] dst) d4 (Zero {t1} [n] dst mem)))))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpOffPtr {
+ break
+ }
+ tt2 := mem_0.Type
+ o2 := auxIntToInt64(mem_0.AuxInt)
+ p2 := mem_0.Args[0]
+ d1 := mem.Args[1]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_2.Aux)
+ _ = mem_2.Args[2]
+ mem_2_0 := mem_2.Args[0]
+ if mem_2_0.Op != OpOffPtr {
+ break
+ }
+ tt3 := mem_2_0.Type
+ o3 := auxIntToInt64(mem_2_0.AuxInt)
+ p3 := mem_2_0.Args[0]
+ d2 := mem_2.Args[1]
+ mem_2_2 := mem_2.Args[2]
+ if mem_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_2_2.Aux)
+ _ = mem_2_2.Args[2]
+ mem_2_2_0 := mem_2_2.Args[0]
+ if mem_2_2_0.Op != OpOffPtr {
+ break
+ }
+ tt4 := mem_2_2_0.Type
+ o4 := auxIntToInt64(mem_2_2_0.AuxInt)
+ p4 := mem_2_2_0.Args[0]
+ d3 := mem_2_2.Args[1]
+ mem_2_2_2 := mem_2_2.Args[2]
+ if mem_2_2_2.Op != OpStore {
+ break
+ }
+ t5 := auxToType(mem_2_2_2.Aux)
+ _ = mem_2_2_2.Args[2]
+ mem_2_2_2_0 := mem_2_2_2.Args[0]
+ if mem_2_2_2_0.Op != OpOffPtr {
+ break
+ }
+ tt5 := mem_2_2_2_0.Type
+ o5 := auxIntToInt64(mem_2_2_2_0.AuxInt)
+ p5 := mem_2_2_2_0.Args[0]
+ d4 := mem_2_2_2.Args[1]
+ mem_2_2_2_2 := mem_2_2_2.Args[2]
+ if mem_2_2_2_2.Op != OpZero || auxIntToInt64(mem_2_2_2_2.AuxInt) != n {
+ break
+ }
+ t6 := auxToType(mem_2_2_2_2.Aux)
+ p6 := mem_2_2_2_2.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && isSamePtr(p5, p6) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && t6.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && n >= o2+t2.Size() && n >= o3+t3.Size() && n >= o4+t4.Size() && n >= o5+t5.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(o3)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t4)
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
+ v4.AuxInt = int64ToAuxInt(o4)
+ v4.AddArg(dst)
+ v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v5.Aux = typeToAux(t5)
+ v6 := b.NewValue0(v.Pos, OpOffPtr, tt5)
+ v6.AuxInt = int64ToAuxInt(o5)
+ v6.AddArg(dst)
+ v7 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
+ v7.AuxInt = int64ToAuxInt(n)
+ v7.Aux = typeToAux(t1)
+ v7.AddArg2(dst, mem)
+ v5.AddArg3(v6, d4, v7)
+ v3.AddArg3(v4, d3, v5)
+ v1.AddArg3(v2, d2, v3)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Zero {t3} [n] p3 _))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && registerizable(b, t2) && n >= o2 + t2.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Zero {t1} [n] dst mem))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpVarDef {
+ break
+ }
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem_0.Aux)
+ _ = mem_0.Args[2]
+ op2 := mem_0.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ tt2 := op2.Type
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d1 := mem_0.Args[1]
+ mem_0_2 := mem_0.Args[2]
+ if mem_0_2.Op != OpZero || auxIntToInt64(mem_0_2.AuxInt) != n {
+ break
+ }
+ t3 := auxToType(mem_0_2.Aux)
+ p3 := mem_0_2.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && registerizable(b, t2) && n >= o2+t2.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
+ v1.AuxInt = int64ToAuxInt(n)
+ v1.Aux = typeToAux(t1)
+ v1.AddArg2(dst, mem)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} (OffPtr <tt2> [o2] p2) d1 (Store {t3} (OffPtr <tt3> [o3] p3) d2 (Zero {t4} [n] p4 _)))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && n >= o2 + t2.Size() && n >= o3 + t3.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Zero {t1} [n] dst mem)))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpVarDef {
+ break
+ }
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem_0.Aux)
+ _ = mem_0.Args[2]
+ mem_0_0 := mem_0.Args[0]
+ if mem_0_0.Op != OpOffPtr {
+ break
+ }
+ tt2 := mem_0_0.Type
+ o2 := auxIntToInt64(mem_0_0.AuxInt)
+ p2 := mem_0_0.Args[0]
+ d1 := mem_0.Args[1]
+ mem_0_2 := mem_0.Args[2]
+ if mem_0_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_0_2.Aux)
+ _ = mem_0_2.Args[2]
+ mem_0_2_0 := mem_0_2.Args[0]
+ if mem_0_2_0.Op != OpOffPtr {
+ break
+ }
+ tt3 := mem_0_2_0.Type
+ o3 := auxIntToInt64(mem_0_2_0.AuxInt)
+ p3 := mem_0_2_0.Args[0]
+ d2 := mem_0_2.Args[1]
+ mem_0_2_2 := mem_0_2.Args[2]
+ if mem_0_2_2.Op != OpZero || auxIntToInt64(mem_0_2_2.AuxInt) != n {
+ break
+ }
+ t4 := auxToType(mem_0_2_2.Aux)
+ p4 := mem_0_2_2.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && n >= o2+t2.Size() && n >= o3+t3.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(o3)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
+ v3.AuxInt = int64ToAuxInt(n)
+ v3.Aux = typeToAux(t1)
+ v3.AddArg2(dst, mem)
+ v1.AddArg3(v2, d2, v3)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} (OffPtr <tt2> [o2] p2) d1 (Store {t3} (OffPtr <tt3> [o3] p3) d2 (Store {t4} (OffPtr <tt4> [o4] p4) d3 (Zero {t5} [n] p5 _))))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && n >= o2 + t2.Size() && n >= o3 + t3.Size() && n >= o4 + t4.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Zero {t1} [n] dst mem))))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpVarDef {
+ break
+ }
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem_0.Aux)
+ _ = mem_0.Args[2]
+ mem_0_0 := mem_0.Args[0]
+ if mem_0_0.Op != OpOffPtr {
+ break
+ }
+ tt2 := mem_0_0.Type
+ o2 := auxIntToInt64(mem_0_0.AuxInt)
+ p2 := mem_0_0.Args[0]
+ d1 := mem_0.Args[1]
+ mem_0_2 := mem_0.Args[2]
+ if mem_0_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_0_2.Aux)
+ _ = mem_0_2.Args[2]
+ mem_0_2_0 := mem_0_2.Args[0]
+ if mem_0_2_0.Op != OpOffPtr {
+ break
+ }
+ tt3 := mem_0_2_0.Type
+ o3 := auxIntToInt64(mem_0_2_0.AuxInt)
+ p3 := mem_0_2_0.Args[0]
+ d2 := mem_0_2.Args[1]
+ mem_0_2_2 := mem_0_2.Args[2]
+ if mem_0_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_0_2_2.Aux)
+ _ = mem_0_2_2.Args[2]
+ mem_0_2_2_0 := mem_0_2_2.Args[0]
+ if mem_0_2_2_0.Op != OpOffPtr {
+ break
+ }
+ tt4 := mem_0_2_2_0.Type
+ o4 := auxIntToInt64(mem_0_2_2_0.AuxInt)
+ p4 := mem_0_2_2_0.Args[0]
+ d3 := mem_0_2_2.Args[1]
+ mem_0_2_2_2 := mem_0_2_2.Args[2]
+ if mem_0_2_2_2.Op != OpZero || auxIntToInt64(mem_0_2_2_2.AuxInt) != n {
+ break
+ }
+ t5 := auxToType(mem_0_2_2_2.Aux)
+ p5 := mem_0_2_2_2.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && n >= o2+t2.Size() && n >= o3+t3.Size() && n >= o4+t4.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(o3)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t4)
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
+ v4.AuxInt = int64ToAuxInt(o4)
+ v4.AddArg(dst)
+ v5 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
+ v5.AuxInt = int64ToAuxInt(n)
+ v5.Aux = typeToAux(t1)
+ v5.AddArg2(dst, mem)
+ v3.AddArg3(v4, d3, v5)
+ v1.AddArg3(v2, d2, v3)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} (OffPtr <tt2> [o2] p2) d1 (Store {t3} (OffPtr <tt3> [o3] p3) d2 (Store {t4} (OffPtr <tt4> [o4] p4) d3 (Store {t5} (OffPtr <tt5> [o5] p5) d4 (Zero {t6} [n] p6 _)))))))
+ // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && isSamePtr(p5, p6) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && t6.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && n >= o2 + t2.Size() && n >= o3 + t3.Size() && n >= o4 + t4.Size() && n >= o5 + t5.Size()
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [o5] dst) d4 (Zero {t1} [n] dst mem)))))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ p1 := v_1
+ mem := v_2
+ if mem.Op != OpVarDef {
+ break
+ }
+ mem_0 := mem.Args[0]
+ if mem_0.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem_0.Aux)
+ _ = mem_0.Args[2]
+ mem_0_0 := mem_0.Args[0]
+ if mem_0_0.Op != OpOffPtr {
+ break
+ }
+ tt2 := mem_0_0.Type
+ o2 := auxIntToInt64(mem_0_0.AuxInt)
+ p2 := mem_0_0.Args[0]
+ d1 := mem_0.Args[1]
+ mem_0_2 := mem_0.Args[2]
+ if mem_0_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_0_2.Aux)
+ _ = mem_0_2.Args[2]
+ mem_0_2_0 := mem_0_2.Args[0]
+ if mem_0_2_0.Op != OpOffPtr {
+ break
+ }
+ tt3 := mem_0_2_0.Type
+ o3 := auxIntToInt64(mem_0_2_0.AuxInt)
+ p3 := mem_0_2_0.Args[0]
+ d2 := mem_0_2.Args[1]
+ mem_0_2_2 := mem_0_2.Args[2]
+ if mem_0_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_0_2_2.Aux)
+ _ = mem_0_2_2.Args[2]
+ mem_0_2_2_0 := mem_0_2_2.Args[0]
+ if mem_0_2_2_0.Op != OpOffPtr {
+ break
+ }
+ tt4 := mem_0_2_2_0.Type
+ o4 := auxIntToInt64(mem_0_2_2_0.AuxInt)
+ p4 := mem_0_2_2_0.Args[0]
+ d3 := mem_0_2_2.Args[1]
+ mem_0_2_2_2 := mem_0_2_2.Args[2]
+ if mem_0_2_2_2.Op != OpStore {
+ break
+ }
+ t5 := auxToType(mem_0_2_2_2.Aux)
+ _ = mem_0_2_2_2.Args[2]
+ mem_0_2_2_2_0 := mem_0_2_2_2.Args[0]
+ if mem_0_2_2_2_0.Op != OpOffPtr {
+ break
+ }
+ tt5 := mem_0_2_2_2_0.Type
+ o5 := auxIntToInt64(mem_0_2_2_2_0.AuxInt)
+ p5 := mem_0_2_2_2_0.Args[0]
+ d4 := mem_0_2_2_2.Args[1]
+ mem_0_2_2_2_2 := mem_0_2_2_2.Args[2]
+ if mem_0_2_2_2_2.Op != OpZero || auxIntToInt64(mem_0_2_2_2_2.AuxInt) != n {
+ break
+ }
+ t6 := auxToType(mem_0_2_2_2_2.Aux)
+ p6 := mem_0_2_2_2_2.Args[0]
+ if !(isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && isSamePtr(p5, p6) && t2.Alignment() <= t1.Alignment() && t3.Alignment() <= t1.Alignment() && t4.Alignment() <= t1.Alignment() && t5.Alignment() <= t1.Alignment() && t6.Alignment() <= t1.Alignment() && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && n >= o2+t2.Size() && n >= o3+t3.Size() && n >= o4+t4.Size() && n >= o5+t5.Size()) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t2)
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
+ v0.AuxInt = int64ToAuxInt(o2)
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
+ v2.AuxInt = int64ToAuxInt(o3)
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t4)
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
+ v4.AuxInt = int64ToAuxInt(o4)
+ v4.AddArg(dst)
+ v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v5.Aux = typeToAux(t5)
+ v6 := b.NewValue0(v.Pos, OpOffPtr, tt5)
+ v6.AuxInt = int64ToAuxInt(o5)
+ v6.AddArg(dst)
+ v7 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
+ v7.AuxInt = int64ToAuxInt(n)
+ v7.Aux = typeToAux(t1)
+ v7.AddArg2(dst, mem)
+ v5.AddArg3(v6, d4, v7)
+ v3.AddArg3(v4, d3, v5)
+ v1.AddArg3(v2, d2, v3)
+ v.AddArg3(v0, d1, v1)
+ return true
+ }
+ // match: (Move {t1} [s] dst tmp1 midmem:(Move {t2} [s] tmp2 src _))
+ // cond: t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && !isVolatile(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))
+ // result: (Move {t1} [s] dst src midmem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ tmp1 := v_1
+ midmem := v_2
+ if midmem.Op != OpMove || auxIntToInt64(midmem.AuxInt) != s {
+ break
+ }
+ t2 := auxToType(midmem.Aux)
+ src := midmem.Args[1]
+ tmp2 := midmem.Args[0]
+ if !(t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && !isVolatile(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(s)
+ v.Aux = typeToAux(t1)
+ v.AddArg3(dst, src, midmem)
+ return true
+ }
+ // match: (Move {t1} [s] dst tmp1 midmem:(VarDef (Move {t2} [s] tmp2 src _)))
+ // cond: t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && !isVolatile(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))
+ // result: (Move {t1} [s] dst src midmem)
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ dst := v_0
+ tmp1 := v_1
+ midmem := v_2
+ if midmem.Op != OpVarDef {
+ break
+ }
+ midmem_0 := midmem.Args[0]
+ if midmem_0.Op != OpMove || auxIntToInt64(midmem_0.AuxInt) != s {
+ break
+ }
+ t2 := auxToType(midmem_0.Aux)
+ src := midmem_0.Args[1]
+ tmp2 := midmem_0.Args[0]
+ if !(t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && !isVolatile(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(s)
+ v.Aux = typeToAux(t1)
+ v.AddArg3(dst, src, midmem)
+ return true
+ }
+ // match: (Move dst src mem)
+ // cond: isSamePtr(dst, src)
+ // result: mem
+ for {
+ dst := v_0
+ src := v_1
+ mem := v_2
+ if !(isSamePtr(dst, src)) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpMul16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul16 (Const16 [c]) (Const16 [d]))
+ // result: (Const16 [c*d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c * d)
+ return true
+ }
+ break
+ }
+ // match: (Mul16 (Const16 [1]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul16 (Const16 [-1]) x)
+ // result: (Neg16 x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpNeg16)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul16 <t> n (Const16 [c]))
+ // cond: isPowerOfTwo16(c)
+ // result: (Lsh16x64 <t> n (Const64 <typ.UInt64> [log16(c)]))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(isPowerOfTwo16(c)) {
+ continue
+ }
+ v.reset(OpLsh16x64)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log16(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ break
+ }
+ // match: (Mul16 <t> n (Const16 [c]))
+ // cond: t.IsSigned() && isPowerOfTwo16(-c)
+ // result: (Neg16 (Lsh16x64 <t> n (Const64 <typ.UInt64> [log16(-c)])))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(t.IsSigned() && isPowerOfTwo16(-c)) {
+ continue
+ }
+ v.reset(OpNeg16)
+ v0 := b.NewValue0(v.Pos, OpLsh16x64, t)
+ v1 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(log16(-c))
+ v0.AddArg2(n, v1)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (Mul16 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (Mul16 (Mul16 i:(Const16 <t>) z) x)
+ // cond: (z.Op != OpConst16 && x.Op != OpConst16)
+ // result: (Mul16 i (Mul16 <t> x z))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMul16 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst16 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst16 && x.Op != OpConst16) {
+ continue
+ }
+ v.reset(OpMul16)
+ v0 := b.NewValue0(v.Pos, OpMul16, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Mul16 (Const16 <t> [c]) (Mul16 (Const16 <t> [d]) x))
+ // result: (Mul16 (Const16 <t> [c*d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpMul16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt16(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpMul16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c * d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpMul32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul32 (Const32 [c]) (Const32 [d]))
+ // result: (Const32 [c*d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c * d)
+ return true
+ }
+ break
+ }
+ // match: (Mul32 (Const32 [1]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul32 (Const32 [-1]) x)
+ // result: (Neg32 x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpNeg32)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul32 <t> n (Const32 [c]))
+ // cond: isPowerOfTwo32(c)
+ // result: (Lsh32x64 <t> n (Const64 <typ.UInt64> [log32(c)]))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(isPowerOfTwo32(c)) {
+ continue
+ }
+ v.reset(OpLsh32x64)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log32(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ break
+ }
+ // match: (Mul32 <t> n (Const32 [c]))
+ // cond: t.IsSigned() && isPowerOfTwo32(-c)
+ // result: (Neg32 (Lsh32x64 <t> n (Const64 <typ.UInt64> [log32(-c)])))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(t.IsSigned() && isPowerOfTwo32(-c)) {
+ continue
+ }
+ v.reset(OpNeg32)
+ v0 := b.NewValue0(v.Pos, OpLsh32x64, t)
+ v1 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(log32(-c))
+ v0.AddArg2(n, v1)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (Mul32 (Const32 <t> [c]) (Add32 <t> (Const32 <t> [d]) x))
+ // result: (Add32 (Const32 <t> [c*d]) (Mul32 <t> (Const32 <t> [c]) x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpAdd32 || v_1.Type != t {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpAdd32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c * d)
+ v1 := b.NewValue0(v.Pos, OpMul32, t)
+ v2 := b.NewValue0(v.Pos, OpConst32, t)
+ v2.AuxInt = int32ToAuxInt(c)
+ v1.AddArg2(v2, x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Mul32 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (Mul32 (Mul32 i:(Const32 <t>) z) x)
+ // cond: (z.Op != OpConst32 && x.Op != OpConst32)
+ // result: (Mul32 i (Mul32 <t> x z))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMul32 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst32 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst32 && x.Op != OpConst32) {
+ continue
+ }
+ v.reset(OpMul32)
+ v0 := b.NewValue0(v.Pos, OpMul32, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Mul32 (Const32 <t> [c]) (Mul32 (Const32 <t> [d]) x))
+ // result: (Mul32 (Const32 <t> [c*d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpMul32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c * d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpMul32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Mul32F (Const32F [c]) (Const32F [d]))
+ // cond: c*d == c*d
+ // result: (Const32F [c*d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32F {
+ continue
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ if v_1.Op != OpConst32F {
+ continue
+ }
+ d := auxIntToFloat32(v_1.AuxInt)
+ if !(c*d == c*d) {
+ continue
+ }
+ v.reset(OpConst32F)
+ v.AuxInt = float32ToAuxInt(c * d)
+ return true
+ }
+ break
+ }
+ // match: (Mul32F x (Const32F [1]))
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpConst32F || auxIntToFloat32(v_1.AuxInt) != 1 {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul32F x (Const32F [-1]))
+ // result: (Neg32F x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpConst32F || auxIntToFloat32(v_1.AuxInt) != -1 {
+ continue
+ }
+ v.reset(OpNeg32F)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul32F x (Const32F [2]))
+ // result: (Add32F x x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpConst32F || auxIntToFloat32(v_1.AuxInt) != 2 {
+ continue
+ }
+ v.reset(OpAdd32F)
+ v.AddArg2(x, x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpMul64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul64 (Const64 [c]) (Const64 [d]))
+ // result: (Const64 [c*d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c * d)
+ return true
+ }
+ break
+ }
+ // match: (Mul64 (Const64 [1]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul64 (Const64 [-1]) x)
+ // result: (Neg64 x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpNeg64)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul64 <t> n (Const64 [c]))
+ // cond: isPowerOfTwo64(c)
+ // result: (Lsh64x64 <t> n (Const64 <typ.UInt64> [log64(c)]))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(isPowerOfTwo64(c)) {
+ continue
+ }
+ v.reset(OpLsh64x64)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log64(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ break
+ }
+ // match: (Mul64 <t> n (Const64 [c]))
+ // cond: t.IsSigned() && isPowerOfTwo64(-c)
+ // result: (Neg64 (Lsh64x64 <t> n (Const64 <typ.UInt64> [log64(-c)])))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(t.IsSigned() && isPowerOfTwo64(-c)) {
+ continue
+ }
+ v.reset(OpNeg64)
+ v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
+ v1 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(log64(-c))
+ v0.AddArg2(n, v1)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (Mul64 (Const64 <t> [c]) (Add64 <t> (Const64 <t> [d]) x))
+ // result: (Add64 (Const64 <t> [c*d]) (Mul64 <t> (Const64 <t> [c]) x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAdd64 || v_1.Type != t {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpAdd64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c * d)
+ v1 := b.NewValue0(v.Pos, OpMul64, t)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(c)
+ v1.AddArg2(v2, x)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Mul64 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (Mul64 (Mul64 i:(Const64 <t>) z) x)
+ // cond: (z.Op != OpConst64 && x.Op != OpConst64)
+ // result: (Mul64 i (Mul64 <t> x z))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMul64 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst64 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst64 && x.Op != OpConst64) {
+ continue
+ }
+ v.reset(OpMul64)
+ v0 := b.NewValue0(v.Pos, OpMul64, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Mul64 (Const64 <t> [c]) (Mul64 (Const64 <t> [d]) x))
+ // result: (Mul64 (Const64 <t> [c*d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpMul64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpMul64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c * d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpMul64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Mul64F (Const64F [c]) (Const64F [d]))
+ // cond: c*d == c*d
+ // result: (Const64F [c*d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64F {
+ continue
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ if v_1.Op != OpConst64F {
+ continue
+ }
+ d := auxIntToFloat64(v_1.AuxInt)
+ if !(c*d == c*d) {
+ continue
+ }
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(c * d)
+ return true
+ }
+ break
+ }
+ // match: (Mul64F x (Const64F [1]))
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpConst64F || auxIntToFloat64(v_1.AuxInt) != 1 {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul64F x (Const64F [-1]))
+ // result: (Neg64F x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpConst64F || auxIntToFloat64(v_1.AuxInt) != -1 {
+ continue
+ }
+ v.reset(OpNeg64F)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul64F x (Const64F [2]))
+ // result: (Add64F x x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpConst64F || auxIntToFloat64(v_1.AuxInt) != 2 {
+ continue
+ }
+ v.reset(OpAdd64F)
+ v.AddArg2(x, x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpMul8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Mul8 (Const8 [c]) (Const8 [d]))
+ // result: (Const8 [c*d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c * d)
+ return true
+ }
+ break
+ }
+ // match: (Mul8 (Const8 [1]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 1 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul8 (Const8 [-1]) x)
+ // result: (Neg8 x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != -1 {
+ continue
+ }
+ x := v_1
+ v.reset(OpNeg8)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (Mul8 <t> n (Const8 [c]))
+ // cond: isPowerOfTwo8(c)
+ // result: (Lsh8x64 <t> n (Const64 <typ.UInt64> [log8(c)]))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(isPowerOfTwo8(c)) {
+ continue
+ }
+ v.reset(OpLsh8x64)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(log8(c))
+ v.AddArg2(n, v0)
+ return true
+ }
+ break
+ }
+ // match: (Mul8 <t> n (Const8 [c]))
+ // cond: t.IsSigned() && isPowerOfTwo8(-c)
+ // result: (Neg8 (Lsh8x64 <t> n (Const64 <typ.UInt64> [log8(-c)])))
+ for {
+ t := v.Type
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(t.IsSigned() && isPowerOfTwo8(-c)) {
+ continue
+ }
+ v.reset(OpNeg8)
+ v0 := b.NewValue0(v.Pos, OpLsh8x64, t)
+ v1 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v1.AuxInt = int64ToAuxInt(log8(-c))
+ v0.AddArg2(n, v1)
+ v.AddArg(v0)
+ return true
+ }
+ break
+ }
+ // match: (Mul8 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ continue
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ break
+ }
+ // match: (Mul8 (Mul8 i:(Const8 <t>) z) x)
+ // cond: (z.Op != OpConst8 && x.Op != OpConst8)
+ // result: (Mul8 i (Mul8 <t> x z))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpMul8 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst8 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst8 && x.Op != OpConst8) {
+ continue
+ }
+ v.reset(OpMul8)
+ v0 := b.NewValue0(v.Pos, OpMul8, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Mul8 (Const8 <t> [c]) (Mul8 (Const8 <t> [d]) x))
+ // result: (Mul8 (Const8 <t> [c*d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpMul8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst8 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt8(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpMul8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c * d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeg16(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neg16 (Const16 [c]))
+ // result: (Const16 [-c])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(-c)
+ return true
+ }
+ // match: (Neg16 (Sub16 x y))
+ // result: (Sub16 y x)
+ for {
+ if v_0.Op != OpSub16 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpSub16)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Neg16 (Neg16 x))
+ // result: x
+ for {
+ if v_0.Op != OpNeg16 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Neg16 <t> (Com16 x))
+ // result: (Add16 (Const16 <t> [1]) x)
+ for {
+ t := v.Type
+ if v_0.Op != OpCom16 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAdd16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(1)
+ v.AddArg2(v0, x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeg32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neg32 (Const32 [c]))
+ // result: (Const32 [-c])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(-c)
+ return true
+ }
+ // match: (Neg32 (Sub32 x y))
+ // result: (Sub32 y x)
+ for {
+ if v_0.Op != OpSub32 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpSub32)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Neg32 (Neg32 x))
+ // result: x
+ for {
+ if v_0.Op != OpNeg32 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Neg32 <t> (Com32 x))
+ // result: (Add32 (Const32 <t> [1]) x)
+ for {
+ t := v.Type
+ if v_0.Op != OpCom32 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAdd32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(1)
+ v.AddArg2(v0, x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeg32F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Neg32F (Const32F [c]))
+ // cond: c != 0
+ // result: (Const32F [-c])
+ for {
+ if v_0.Op != OpConst32F {
+ break
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpConst32F)
+ v.AuxInt = float32ToAuxInt(-c)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeg64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neg64 (Const64 [c]))
+ // result: (Const64 [-c])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(-c)
+ return true
+ }
+ // match: (Neg64 (Sub64 x y))
+ // result: (Sub64 y x)
+ for {
+ if v_0.Op != OpSub64 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpSub64)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Neg64 (Neg64 x))
+ // result: x
+ for {
+ if v_0.Op != OpNeg64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Neg64 <t> (Com64 x))
+ // result: (Add64 (Const64 <t> [1]) x)
+ for {
+ t := v.Type
+ if v_0.Op != OpCom64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAdd64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(1)
+ v.AddArg2(v0, x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeg64F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Neg64F (Const64F [c]))
+ // cond: c != 0
+ // result: (Const64F [-c])
+ for {
+ if v_0.Op != OpConst64F {
+ break
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(-c)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeg8(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Neg8 (Const8 [c]))
+ // result: (Const8 [-c])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(-c)
+ return true
+ }
+ // match: (Neg8 (Sub8 x y))
+ // result: (Sub8 y x)
+ for {
+ if v_0.Op != OpSub8 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpSub8)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Neg8 (Neg8 x))
+ // result: x
+ for {
+ if v_0.Op != OpNeg8 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Neg8 <t> (Com8 x))
+ // result: (Add8 (Const8 <t> [1]) x)
+ for {
+ t := v.Type
+ if v_0.Op != OpCom8 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAdd8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(1)
+ v.AddArg2(v0, x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeq16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq16 x x)
+ // result: (ConstBool [false])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (Neq16 (Const16 <t> [c]) (Add16 (Const16 <t> [d]) x))
+ // result: (Neq16 (Const16 <t> [c-d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpAdd16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt16(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpNeq16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Neq16 (Const16 [c]) (Const16 [d]))
+ // result: (ConstBool [c != d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != d)
+ return true
+ }
+ break
+ }
+ // match: (Neq16 n (Lsh16x64 (Rsh16x64 (Add16 <t> n (Rsh16Ux64 <t> (Rsh16x64 <t> n (Const64 <typ.UInt64> [15])) (Const64 <typ.UInt64> [kbar]))) (Const64 <typ.UInt64> [k])) (Const64 <typ.UInt64> [k])) )
+ // cond: k > 0 && k < 15 && kbar == 16 - k
+ // result: (Neq16 (And16 <t> n (Const16 <t> [1<<uint(k)-1])) (Const16 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpLsh16x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpRsh16x64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAdd16 {
+ continue
+ }
+ t := v_1_0_0.Type
+ _ = v_1_0_0.Args[1]
+ v_1_0_0_0 := v_1_0_0.Args[0]
+ v_1_0_0_1 := v_1_0_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0_0_0, v_1_0_0_1 = _i1+1, v_1_0_0_1, v_1_0_0_0 {
+ if n != v_1_0_0_0 || v_1_0_0_1.Op != OpRsh16Ux64 || v_1_0_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1.Args[1]
+ v_1_0_0_1_0 := v_1_0_0_1.Args[0]
+ if v_1_0_0_1_0.Op != OpRsh16x64 || v_1_0_0_1_0.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1_0.Args[1]
+ if n != v_1_0_0_1_0.Args[0] {
+ continue
+ }
+ v_1_0_0_1_0_1 := v_1_0_0_1_0.Args[1]
+ if v_1_0_0_1_0_1.Op != OpConst64 || v_1_0_0_1_0_1.Type != typ.UInt64 || auxIntToInt64(v_1_0_0_1_0_1.AuxInt) != 15 {
+ continue
+ }
+ v_1_0_0_1_1 := v_1_0_0_1.Args[1]
+ if v_1_0_0_1_1.Op != OpConst64 || v_1_0_0_1_1.Type != typ.UInt64 {
+ continue
+ }
+ kbar := auxIntToInt64(v_1_0_0_1_1.AuxInt)
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpConst64 || v_1_0_1.Type != typ.UInt64 {
+ continue
+ }
+ k := auxIntToInt64(v_1_0_1.AuxInt)
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 || v_1_1.Type != typ.UInt64 || auxIntToInt64(v_1_1.AuxInt) != k || !(k > 0 && k < 15 && kbar == 16-k) {
+ continue
+ }
+ v.reset(OpNeq16)
+ v0 := b.NewValue0(v.Pos, OpAnd16, t)
+ v1 := b.NewValue0(v.Pos, OpConst16, t)
+ v1.AuxInt = int16ToAuxInt(1<<uint(k) - 1)
+ v0.AddArg2(n, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, t)
+ v2.AuxInt = int16ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Neq16 s:(Sub16 x y) (Const16 [0]))
+ // cond: s.Uses == 1
+ // result: (Neq16 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s := v_0
+ if s.Op != OpSub16 {
+ continue
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ if v_1.Op != OpConst16 || auxIntToInt16(v_1.AuxInt) != 0 || !(s.Uses == 1) {
+ continue
+ }
+ v.reset(OpNeq16)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y]))
+ // cond: oneBit16(y)
+ // result: (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd16 {
+ continue
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst16 || v_0_1.Type != t {
+ continue
+ }
+ y := auxIntToInt16(v_0_1.AuxInt)
+ if v_1.Op != OpConst16 || v_1.Type != t || auxIntToInt16(v_1.AuxInt) != y || !(oneBit16(y)) {
+ continue
+ }
+ v.reset(OpEq16)
+ v0 := b.NewValue0(v.Pos, OpAnd16, t)
+ v1 := b.NewValue0(v.Pos, OpConst16, t)
+ v1.AuxInt = int16ToAuxInt(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst16, t)
+ v2.AuxInt = int16ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeq32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq32 x x)
+ // result: (ConstBool [false])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (Neq32 (Const32 <t> [c]) (Add32 (Const32 <t> [d]) x))
+ // result: (Neq32 (Const32 <t> [c-d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpAdd32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpNeq32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Neq32 (Const32 [c]) (Const32 [d]))
+ // result: (ConstBool [c != d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != d)
+ return true
+ }
+ break
+ }
+ // match: (Neq32 n (Lsh32x64 (Rsh32x64 (Add32 <t> n (Rsh32Ux64 <t> (Rsh32x64 <t> n (Const64 <typ.UInt64> [31])) (Const64 <typ.UInt64> [kbar]))) (Const64 <typ.UInt64> [k])) (Const64 <typ.UInt64> [k])) )
+ // cond: k > 0 && k < 31 && kbar == 32 - k
+ // result: (Neq32 (And32 <t> n (Const32 <t> [1<<uint(k)-1])) (Const32 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpLsh32x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpRsh32x64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAdd32 {
+ continue
+ }
+ t := v_1_0_0.Type
+ _ = v_1_0_0.Args[1]
+ v_1_0_0_0 := v_1_0_0.Args[0]
+ v_1_0_0_1 := v_1_0_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0_0_0, v_1_0_0_1 = _i1+1, v_1_0_0_1, v_1_0_0_0 {
+ if n != v_1_0_0_0 || v_1_0_0_1.Op != OpRsh32Ux64 || v_1_0_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1.Args[1]
+ v_1_0_0_1_0 := v_1_0_0_1.Args[0]
+ if v_1_0_0_1_0.Op != OpRsh32x64 || v_1_0_0_1_0.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1_0.Args[1]
+ if n != v_1_0_0_1_0.Args[0] {
+ continue
+ }
+ v_1_0_0_1_0_1 := v_1_0_0_1_0.Args[1]
+ if v_1_0_0_1_0_1.Op != OpConst64 || v_1_0_0_1_0_1.Type != typ.UInt64 || auxIntToInt64(v_1_0_0_1_0_1.AuxInt) != 31 {
+ continue
+ }
+ v_1_0_0_1_1 := v_1_0_0_1.Args[1]
+ if v_1_0_0_1_1.Op != OpConst64 || v_1_0_0_1_1.Type != typ.UInt64 {
+ continue
+ }
+ kbar := auxIntToInt64(v_1_0_0_1_1.AuxInt)
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpConst64 || v_1_0_1.Type != typ.UInt64 {
+ continue
+ }
+ k := auxIntToInt64(v_1_0_1.AuxInt)
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 || v_1_1.Type != typ.UInt64 || auxIntToInt64(v_1_1.AuxInt) != k || !(k > 0 && k < 31 && kbar == 32-k) {
+ continue
+ }
+ v.reset(OpNeq32)
+ v0 := b.NewValue0(v.Pos, OpAnd32, t)
+ v1 := b.NewValue0(v.Pos, OpConst32, t)
+ v1.AuxInt = int32ToAuxInt(1<<uint(k) - 1)
+ v0.AddArg2(n, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, t)
+ v2.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Neq32 s:(Sub32 x y) (Const32 [0]))
+ // cond: s.Uses == 1
+ // result: (Neq32 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s := v_0
+ if s.Op != OpSub32 {
+ continue
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ if v_1.Op != OpConst32 || auxIntToInt32(v_1.AuxInt) != 0 || !(s.Uses == 1) {
+ continue
+ }
+ v.reset(OpNeq32)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y]))
+ // cond: oneBit32(y)
+ // result: (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd32 {
+ continue
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst32 || v_0_1.Type != t {
+ continue
+ }
+ y := auxIntToInt32(v_0_1.AuxInt)
+ if v_1.Op != OpConst32 || v_1.Type != t || auxIntToInt32(v_1.AuxInt) != y || !(oneBit32(y)) {
+ continue
+ }
+ v.reset(OpEq32)
+ v0 := b.NewValue0(v.Pos, OpAnd32, t)
+ v1 := b.NewValue0(v.Pos, OpConst32, t)
+ v1.AuxInt = int32ToAuxInt(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst32, t)
+ v2.AuxInt = int32ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeq32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Neq32F (Const32F [c]) (Const32F [d]))
+ // result: (ConstBool [c != d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32F {
+ continue
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ if v_1.Op != OpConst32F {
+ continue
+ }
+ d := auxIntToFloat32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != d)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeq64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq64 x x)
+ // result: (ConstBool [false])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (Neq64 (Const64 <t> [c]) (Add64 (Const64 <t> [d]) x))
+ // result: (Neq64 (Const64 <t> [c-d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAdd64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpNeq64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Neq64 (Const64 [c]) (Const64 [d]))
+ // result: (ConstBool [c != d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != d)
+ return true
+ }
+ break
+ }
+ // match: (Neq64 n (Lsh64x64 (Rsh64x64 (Add64 <t> n (Rsh64Ux64 <t> (Rsh64x64 <t> n (Const64 <typ.UInt64> [63])) (Const64 <typ.UInt64> [kbar]))) (Const64 <typ.UInt64> [k])) (Const64 <typ.UInt64> [k])) )
+ // cond: k > 0 && k < 63 && kbar == 64 - k
+ // result: (Neq64 (And64 <t> n (Const64 <t> [1<<uint(k)-1])) (Const64 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpLsh64x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpRsh64x64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAdd64 {
+ continue
+ }
+ t := v_1_0_0.Type
+ _ = v_1_0_0.Args[1]
+ v_1_0_0_0 := v_1_0_0.Args[0]
+ v_1_0_0_1 := v_1_0_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0_0_0, v_1_0_0_1 = _i1+1, v_1_0_0_1, v_1_0_0_0 {
+ if n != v_1_0_0_0 || v_1_0_0_1.Op != OpRsh64Ux64 || v_1_0_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1.Args[1]
+ v_1_0_0_1_0 := v_1_0_0_1.Args[0]
+ if v_1_0_0_1_0.Op != OpRsh64x64 || v_1_0_0_1_0.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1_0.Args[1]
+ if n != v_1_0_0_1_0.Args[0] {
+ continue
+ }
+ v_1_0_0_1_0_1 := v_1_0_0_1_0.Args[1]
+ if v_1_0_0_1_0_1.Op != OpConst64 || v_1_0_0_1_0_1.Type != typ.UInt64 || auxIntToInt64(v_1_0_0_1_0_1.AuxInt) != 63 {
+ continue
+ }
+ v_1_0_0_1_1 := v_1_0_0_1.Args[1]
+ if v_1_0_0_1_1.Op != OpConst64 || v_1_0_0_1_1.Type != typ.UInt64 {
+ continue
+ }
+ kbar := auxIntToInt64(v_1_0_0_1_1.AuxInt)
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpConst64 || v_1_0_1.Type != typ.UInt64 {
+ continue
+ }
+ k := auxIntToInt64(v_1_0_1.AuxInt)
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 || v_1_1.Type != typ.UInt64 || auxIntToInt64(v_1_1.AuxInt) != k || !(k > 0 && k < 63 && kbar == 64-k) {
+ continue
+ }
+ v.reset(OpNeq64)
+ v0 := b.NewValue0(v.Pos, OpAnd64, t)
+ v1 := b.NewValue0(v.Pos, OpConst64, t)
+ v1.AuxInt = int64ToAuxInt(1<<uint(k) - 1)
+ v0.AddArg2(n, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Neq64 s:(Sub64 x y) (Const64 [0]))
+ // cond: s.Uses == 1
+ // result: (Neq64 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s := v_0
+ if s.Op != OpSub64 {
+ continue
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 || !(s.Uses == 1) {
+ continue
+ }
+ v.reset(OpNeq64)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y]))
+ // cond: oneBit64(y)
+ // result: (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd64 {
+ continue
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst64 || v_0_1.Type != t {
+ continue
+ }
+ y := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 || v_1.Type != t || auxIntToInt64(v_1.AuxInt) != y || !(oneBit64(y)) {
+ continue
+ }
+ v.reset(OpEq64)
+ v0 := b.NewValue0(v.Pos, OpAnd64, t)
+ v1 := b.NewValue0(v.Pos, OpConst64, t)
+ v1.AuxInt = int64ToAuxInt(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst64, t)
+ v2.AuxInt = int64ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeq64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Neq64F (Const64F [c]) (Const64F [d]))
+ // result: (ConstBool [c != d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64F {
+ continue
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ if v_1.Op != OpConst64F {
+ continue
+ }
+ d := auxIntToFloat64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != d)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeq8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Neq8 x x)
+ // result: (ConstBool [false])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (Neq8 (Const8 <t> [c]) (Add8 (Const8 <t> [d]) x))
+ // result: (Neq8 (Const8 <t> [c-d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpAdd8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst8 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt8(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpNeq8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Neq8 (Const8 [c]) (Const8 [d]))
+ // result: (ConstBool [c != d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != d)
+ return true
+ }
+ break
+ }
+ // match: (Neq8 n (Lsh8x64 (Rsh8x64 (Add8 <t> n (Rsh8Ux64 <t> (Rsh8x64 <t> n (Const64 <typ.UInt64> [ 7])) (Const64 <typ.UInt64> [kbar]))) (Const64 <typ.UInt64> [k])) (Const64 <typ.UInt64> [k])) )
+ // cond: k > 0 && k < 7 && kbar == 8 - k
+ // result: (Neq8 (And8 <t> n (Const8 <t> [1<<uint(k)-1])) (Const8 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ n := v_0
+ if v_1.Op != OpLsh8x64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpRsh8x64 {
+ continue
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpAdd8 {
+ continue
+ }
+ t := v_1_0_0.Type
+ _ = v_1_0_0.Args[1]
+ v_1_0_0_0 := v_1_0_0.Args[0]
+ v_1_0_0_1 := v_1_0_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0_0_0, v_1_0_0_1 = _i1+1, v_1_0_0_1, v_1_0_0_0 {
+ if n != v_1_0_0_0 || v_1_0_0_1.Op != OpRsh8Ux64 || v_1_0_0_1.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1.Args[1]
+ v_1_0_0_1_0 := v_1_0_0_1.Args[0]
+ if v_1_0_0_1_0.Op != OpRsh8x64 || v_1_0_0_1_0.Type != t {
+ continue
+ }
+ _ = v_1_0_0_1_0.Args[1]
+ if n != v_1_0_0_1_0.Args[0] {
+ continue
+ }
+ v_1_0_0_1_0_1 := v_1_0_0_1_0.Args[1]
+ if v_1_0_0_1_0_1.Op != OpConst64 || v_1_0_0_1_0_1.Type != typ.UInt64 || auxIntToInt64(v_1_0_0_1_0_1.AuxInt) != 7 {
+ continue
+ }
+ v_1_0_0_1_1 := v_1_0_0_1.Args[1]
+ if v_1_0_0_1_1.Op != OpConst64 || v_1_0_0_1_1.Type != typ.UInt64 {
+ continue
+ }
+ kbar := auxIntToInt64(v_1_0_0_1_1.AuxInt)
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpConst64 || v_1_0_1.Type != typ.UInt64 {
+ continue
+ }
+ k := auxIntToInt64(v_1_0_1.AuxInt)
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 || v_1_1.Type != typ.UInt64 || auxIntToInt64(v_1_1.AuxInt) != k || !(k > 0 && k < 7 && kbar == 8-k) {
+ continue
+ }
+ v.reset(OpNeq8)
+ v0 := b.NewValue0(v.Pos, OpAnd8, t)
+ v1 := b.NewValue0(v.Pos, OpConst8, t)
+ v1.AuxInt = int8ToAuxInt(1<<uint(k) - 1)
+ v0.AddArg2(n, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, t)
+ v2.AuxInt = int8ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Neq8 s:(Sub8 x y) (Const8 [0]))
+ // cond: s.Uses == 1
+ // result: (Neq8 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ s := v_0
+ if s.Op != OpSub8 {
+ continue
+ }
+ y := s.Args[1]
+ x := s.Args[0]
+ if v_1.Op != OpConst8 || auxIntToInt8(v_1.AuxInt) != 0 || !(s.Uses == 1) {
+ continue
+ }
+ v.reset(OpNeq8)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ // match: (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y]))
+ // cond: oneBit8(y)
+ // result: (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd8 {
+ continue
+ }
+ t := v_0.Type
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst8 || v_0_1.Type != t {
+ continue
+ }
+ y := auxIntToInt8(v_0_1.AuxInt)
+ if v_1.Op != OpConst8 || v_1.Type != t || auxIntToInt8(v_1.AuxInt) != y || !(oneBit8(y)) {
+ continue
+ }
+ v.reset(OpEq8)
+ v0 := b.NewValue0(v.Pos, OpAnd8, t)
+ v1 := b.NewValue0(v.Pos, OpConst8, t)
+ v1.AuxInt = int8ToAuxInt(y)
+ v0.AddArg2(x, v1)
+ v2 := b.NewValue0(v.Pos, OpConst8, t)
+ v2.AuxInt = int8ToAuxInt(0)
+ v.AddArg2(v0, v2)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeqB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (NeqB (ConstBool [c]) (ConstBool [d]))
+ // result: (ConstBool [c != d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConstBool {
+ continue
+ }
+ c := auxIntToBool(v_0.AuxInt)
+ if v_1.Op != OpConstBool {
+ continue
+ }
+ d := auxIntToBool(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != d)
+ return true
+ }
+ break
+ }
+ // match: (NeqB (ConstBool [false]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConstBool || auxIntToBool(v_0.AuxInt) != false {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (NeqB (ConstBool [true]) x)
+ // result: (Not x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConstBool || auxIntToBool(v_0.AuxInt) != true {
+ continue
+ }
+ x := v_1
+ v.reset(OpNot)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ // match: (NeqB (Not x) (Not y))
+ // result: (NeqB x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpNot {
+ continue
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpNot {
+ continue
+ }
+ y := v_1.Args[0]
+ v.reset(OpNeqB)
+ v.AddArg2(x, y)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeqInter(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (NeqInter x y)
+ // result: (NeqPtr (ITab x) (ITab y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpNeqPtr)
+ v0 := b.NewValue0(v.Pos, OpITab, typ.Uintptr)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpITab, typ.Uintptr)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuegeneric_OpNeqPtr(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (NeqPtr x x)
+ // result: (ConstBool [false])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(false)
+ return true
+ }
+ // match: (NeqPtr (Addr {a} _) (Addr {b} _))
+ // result: (ConstBool [a != b])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAddr {
+ continue
+ }
+ a := auxToSym(v_0.Aux)
+ if v_1.Op != OpAddr {
+ continue
+ }
+ b := auxToSym(v_1.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a != b)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (Addr {a} _) (OffPtr [o] (Addr {b} _)))
+ // result: (ConstBool [a != b || o != 0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAddr {
+ continue
+ }
+ a := auxToSym(v_0.Aux)
+ if v_1.Op != OpOffPtr {
+ continue
+ }
+ o := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAddr {
+ continue
+ }
+ b := auxToSym(v_1_0.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a != b || o != 0)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (OffPtr [o1] (Addr {a} _)) (OffPtr [o2] (Addr {b} _)))
+ // result: (ConstBool [a != b || o1 != o2])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ o1 := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAddr {
+ continue
+ }
+ a := auxToSym(v_0_0.Aux)
+ if v_1.Op != OpOffPtr {
+ continue
+ }
+ o2 := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAddr {
+ continue
+ }
+ b := auxToSym(v_1_0.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a != b || o1 != o2)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (LocalAddr {a} _ _) (LocalAddr {b} _ _))
+ // result: (ConstBool [a != b])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLocalAddr {
+ continue
+ }
+ a := auxToSym(v_0.Aux)
+ if v_1.Op != OpLocalAddr {
+ continue
+ }
+ b := auxToSym(v_1.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a != b)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (LocalAddr {a} _ _) (OffPtr [o] (LocalAddr {b} _ _)))
+ // result: (ConstBool [a != b || o != 0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLocalAddr {
+ continue
+ }
+ a := auxToSym(v_0.Aux)
+ if v_1.Op != OpOffPtr {
+ continue
+ }
+ o := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpLocalAddr {
+ continue
+ }
+ b := auxToSym(v_1_0.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a != b || o != 0)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (OffPtr [o1] (LocalAddr {a} _ _)) (OffPtr [o2] (LocalAddr {b} _ _)))
+ // result: (ConstBool [a != b || o1 != o2])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ o1 := auxIntToInt64(v_0.AuxInt)
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLocalAddr {
+ continue
+ }
+ a := auxToSym(v_0_0.Aux)
+ if v_1.Op != OpOffPtr {
+ continue
+ }
+ o2 := auxIntToInt64(v_1.AuxInt)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpLocalAddr {
+ continue
+ }
+ b := auxToSym(v_1_0.Aux)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(a != b || o1 != o2)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (OffPtr [o1] p1) p2)
+ // cond: isSamePtr(p1, p2)
+ // result: (ConstBool [o1 != 0])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ o1 := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ p2 := v_1
+ if !(isSamePtr(p1, p2)) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(o1 != 0)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (OffPtr [o1] p1) (OffPtr [o2] p2))
+ // cond: isSamePtr(p1, p2)
+ // result: (ConstBool [o1 != o2])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ o1 := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ if v_1.Op != OpOffPtr {
+ continue
+ }
+ o2 := auxIntToInt64(v_1.AuxInt)
+ p2 := v_1.Args[0]
+ if !(isSamePtr(p1, p2)) {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(o1 != o2)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (Const32 [c]) (Const32 [d]))
+ // result: (ConstBool [c != d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != d)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (Const64 [c]) (Const64 [d]))
+ // result: (ConstBool [c != d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(c != d)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (LocalAddr _ _) (Addr _))
+ // result: (ConstBool [true])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLocalAddr || v_1.Op != OpAddr {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (OffPtr (LocalAddr _ _)) (Addr _))
+ // result: (ConstBool [true])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLocalAddr || v_1.Op != OpAddr {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (LocalAddr _ _) (OffPtr (Addr _)))
+ // result: (ConstBool [true])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLocalAddr || v_1.Op != OpOffPtr {
+ continue
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAddr {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (OffPtr (LocalAddr _ _)) (OffPtr (Addr _)))
+ // result: (ConstBool [true])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOffPtr {
+ continue
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLocalAddr || v_1.Op != OpOffPtr {
+ continue
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpAddr {
+ continue
+ }
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(true)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (AddPtr p1 o1) p2)
+ // cond: isSamePtr(p1, p2)
+ // result: (IsNonNil o1)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAddPtr {
+ continue
+ }
+ o1 := v_0.Args[1]
+ p1 := v_0.Args[0]
+ p2 := v_1
+ if !(isSamePtr(p1, p2)) {
+ continue
+ }
+ v.reset(OpIsNonNil)
+ v.AddArg(o1)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (Const32 [0]) p)
+ // result: (IsNonNil p)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ continue
+ }
+ p := v_1
+ v.reset(OpIsNonNil)
+ v.AddArg(p)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (Const64 [0]) p)
+ // result: (IsNonNil p)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ continue
+ }
+ p := v_1
+ v.reset(OpIsNonNil)
+ v.AddArg(p)
+ return true
+ }
+ break
+ }
+ // match: (NeqPtr (ConstNil) p)
+ // result: (IsNonNil p)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConstNil {
+ continue
+ }
+ p := v_1
+ v.reset(OpIsNonNil)
+ v.AddArg(p)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpNeqSlice(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (NeqSlice x y)
+ // result: (NeqPtr (SlicePtr x) (SlicePtr y))
+ for {
+ x := v_0
+ y := v_1
+ v.reset(OpNeqPtr)
+ v0 := b.NewValue0(v.Pos, OpSlicePtr, typ.BytePtr)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Pos, OpSlicePtr, typ.BytePtr)
+ v1.AddArg(y)
+ v.AddArg2(v0, v1)
+ return true
+ }
+}
+func rewriteValuegeneric_OpNilCheck(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ fe := b.Func.fe
+ // match: (NilCheck (GetG mem) mem)
+ // result: mem
+ for {
+ if v_0.Op != OpGetG {
+ break
+ }
+ mem := v_0.Args[0]
+ if mem != v_1 {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (NilCheck (Load (OffPtr [c] (SP)) (StaticCall {sym} _)) _)
+ // cond: isSameCall(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")
+ // result: (Invalid)
+ for {
+ if v_0.Op != OpLoad {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpOffPtr {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpSP {
+ break
+ }
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpStaticCall {
+ break
+ }
+ sym := auxToCall(v_0_1.Aux)
+ if !(isSameCall(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")) {
+ break
+ }
+ v.reset(OpInvalid)
+ return true
+ }
+ // match: (NilCheck (OffPtr (Load (OffPtr [c] (SP)) (StaticCall {sym} _))) _)
+ // cond: isSameCall(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")
+ // result: (Invalid)
+ for {
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLoad {
+ break
+ }
+ _ = v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpOffPtr {
+ break
+ }
+ c := auxIntToInt64(v_0_0_0.AuxInt)
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpSP {
+ break
+ }
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpStaticCall {
+ break
+ }
+ sym := auxToCall(v_0_0_1.Aux)
+ if !(isSameCall(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")) {
+ break
+ }
+ v.reset(OpInvalid)
+ return true
+ }
+ // match: (NilCheck (SelectN [0] call:(StaticLECall _ _)) (SelectN [1] call))
+ // cond: isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")
+ // result: (Invalid)
+ for {
+ if v_0.Op != OpSelectN || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ call := v_0.Args[0]
+ if call.Op != OpStaticLECall || len(call.Args) != 2 || v_1.Op != OpSelectN || auxIntToInt64(v_1.AuxInt) != 1 || call != v_1.Args[0] || !(isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")) {
+ break
+ }
+ v.reset(OpInvalid)
+ return true
+ }
+ // match: (NilCheck (OffPtr (SelectN [0] call:(StaticLECall _ _))) (SelectN [1] call))
+ // cond: isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")
+ // result: (Invalid)
+ for {
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelectN || auxIntToInt64(v_0_0.AuxInt) != 0 {
+ break
+ }
+ call := v_0_0.Args[0]
+ if call.Op != OpStaticLECall || len(call.Args) != 2 || v_1.Op != OpSelectN || auxIntToInt64(v_1.AuxInt) != 1 || call != v_1.Args[0] || !(isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")) {
+ break
+ }
+ v.reset(OpInvalid)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpNot(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Not (ConstBool [c]))
+ // result: (ConstBool [!c])
+ for {
+ if v_0.Op != OpConstBool {
+ break
+ }
+ c := auxIntToBool(v_0.AuxInt)
+ v.reset(OpConstBool)
+ v.AuxInt = boolToAuxInt(!c)
+ return true
+ }
+ // match: (Not (Eq64 x y))
+ // result: (Neq64 x y)
+ for {
+ if v_0.Op != OpEq64 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpNeq64)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Eq32 x y))
+ // result: (Neq32 x y)
+ for {
+ if v_0.Op != OpEq32 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpNeq32)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Eq16 x y))
+ // result: (Neq16 x y)
+ for {
+ if v_0.Op != OpEq16 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpNeq16)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Eq8 x y))
+ // result: (Neq8 x y)
+ for {
+ if v_0.Op != OpEq8 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpNeq8)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (EqB x y))
+ // result: (NeqB x y)
+ for {
+ if v_0.Op != OpEqB {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpNeqB)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (EqPtr x y))
+ // result: (NeqPtr x y)
+ for {
+ if v_0.Op != OpEqPtr {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpNeqPtr)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Eq64F x y))
+ // result: (Neq64F x y)
+ for {
+ if v_0.Op != OpEq64F {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpNeq64F)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Eq32F x y))
+ // result: (Neq32F x y)
+ for {
+ if v_0.Op != OpEq32F {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpNeq32F)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Neq64 x y))
+ // result: (Eq64 x y)
+ for {
+ if v_0.Op != OpNeq64 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpEq64)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Neq32 x y))
+ // result: (Eq32 x y)
+ for {
+ if v_0.Op != OpNeq32 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpEq32)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Neq16 x y))
+ // result: (Eq16 x y)
+ for {
+ if v_0.Op != OpNeq16 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpEq16)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Neq8 x y))
+ // result: (Eq8 x y)
+ for {
+ if v_0.Op != OpNeq8 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpEq8)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (NeqB x y))
+ // result: (EqB x y)
+ for {
+ if v_0.Op != OpNeqB {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpEqB)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (NeqPtr x y))
+ // result: (EqPtr x y)
+ for {
+ if v_0.Op != OpNeqPtr {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpEqPtr)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Neq64F x y))
+ // result: (Eq64F x y)
+ for {
+ if v_0.Op != OpNeq64F {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpEq64F)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Neq32F x y))
+ // result: (Eq32F x y)
+ for {
+ if v_0.Op != OpNeq32F {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpEq32F)
+ v.AddArg2(x, y)
+ return true
+ }
+ // match: (Not (Less64 x y))
+ // result: (Leq64 y x)
+ for {
+ if v_0.Op != OpLess64 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLeq64)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Less32 x y))
+ // result: (Leq32 y x)
+ for {
+ if v_0.Op != OpLess32 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLeq32)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Less16 x y))
+ // result: (Leq16 y x)
+ for {
+ if v_0.Op != OpLess16 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLeq16)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Less8 x y))
+ // result: (Leq8 y x)
+ for {
+ if v_0.Op != OpLess8 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLeq8)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Less64U x y))
+ // result: (Leq64U y x)
+ for {
+ if v_0.Op != OpLess64U {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLeq64U)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Less32U x y))
+ // result: (Leq32U y x)
+ for {
+ if v_0.Op != OpLess32U {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLeq32U)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Less16U x y))
+ // result: (Leq16U y x)
+ for {
+ if v_0.Op != OpLess16U {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLeq16U)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Less8U x y))
+ // result: (Leq8U y x)
+ for {
+ if v_0.Op != OpLess8U {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLeq8U)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Leq64 x y))
+ // result: (Less64 y x)
+ for {
+ if v_0.Op != OpLeq64 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLess64)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Leq32 x y))
+ // result: (Less32 y x)
+ for {
+ if v_0.Op != OpLeq32 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLess32)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Leq16 x y))
+ // result: (Less16 y x)
+ for {
+ if v_0.Op != OpLeq16 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLess16)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Leq8 x y))
+ // result: (Less8 y x)
+ for {
+ if v_0.Op != OpLeq8 {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLess8)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Leq64U x y))
+ // result: (Less64U y x)
+ for {
+ if v_0.Op != OpLeq64U {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLess64U)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Leq32U x y))
+ // result: (Less32U y x)
+ for {
+ if v_0.Op != OpLeq32U {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLess32U)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Leq16U x y))
+ // result: (Less16U y x)
+ for {
+ if v_0.Op != OpLeq16U {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLess16U)
+ v.AddArg2(y, x)
+ return true
+ }
+ // match: (Not (Leq8U x y))
+ // result: (Less8U y x)
+ for {
+ if v_0.Op != OpLeq8U {
+ break
+ }
+ y := v_0.Args[1]
+ x := v_0.Args[0]
+ v.reset(OpLess8U)
+ v.AddArg2(y, x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpOffPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (OffPtr (OffPtr p [b]) [a])
+ // result: (OffPtr p [a+b])
+ for {
+ a := auxIntToInt64(v.AuxInt)
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ b := auxIntToInt64(v_0.AuxInt)
+ p := v_0.Args[0]
+ v.reset(OpOffPtr)
+ v.AuxInt = int64ToAuxInt(a + b)
+ v.AddArg(p)
+ return true
+ }
+ // match: (OffPtr p [0])
+ // cond: v.Type.Compare(p.Type) == types.CMPeq
+ // result: p
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ p := v_0
+ if !(v.Type.Compare(p.Type) == types.CMPeq) {
+ break
+ }
+ v.copyOf(p)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpOr16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Or16 (Const16 [c]) (Const16 [d]))
+ // result: (Const16 [c|d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c | d)
+ return true
+ }
+ break
+ }
+ // match: (Or16 x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Or16 (Const16 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Or16 (Const16 [-1]) _)
+ // result: (Const16 [-1])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != -1 {
+ continue
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(-1)
+ return true
+ }
+ break
+ }
+ // match: (Or16 x (Or16 x y))
+ // result: (Or16 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpOr16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(OpOr16)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or16 (And16 x (Const16 [c2])) (Const16 <t> [c1]))
+ // cond: ^(c1 | c2) == 0
+ // result: (Or16 (Const16 <t> [c1]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd16 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst16 {
+ continue
+ }
+ c2 := auxIntToInt16(v_0_1.AuxInt)
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ t := v_1.Type
+ c1 := auxIntToInt16(v_1.AuxInt)
+ if !(^(c1 | c2) == 0) {
+ continue
+ }
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c1)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or16 (Or16 i:(Const16 <t>) z) x)
+ // cond: (z.Op != OpConst16 && x.Op != OpConst16)
+ // result: (Or16 i (Or16 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOr16 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst16 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst16 && x.Op != OpConst16) {
+ continue
+ }
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpOr16, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or16 (Const16 <t> [c]) (Or16 (Const16 <t> [d]) x))
+ // result: (Or16 (Const16 <t> [c|d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpOr16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt16(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpOr16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c | d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpOr32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Or32 (Const32 [c]) (Const32 [d]))
+ // result: (Const32 [c|d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c | d)
+ return true
+ }
+ break
+ }
+ // match: (Or32 x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Or32 (Const32 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Or32 (Const32 [-1]) _)
+ // result: (Const32 [-1])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != -1 {
+ continue
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ break
+ }
+ // match: (Or32 x (Or32 x y))
+ // result: (Or32 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpOr32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(OpOr32)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or32 (And32 x (Const32 [c2])) (Const32 <t> [c1]))
+ // cond: ^(c1 | c2) == 0
+ // result: (Or32 (Const32 <t> [c1]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd32 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst32 {
+ continue
+ }
+ c2 := auxIntToInt32(v_0_1.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ t := v_1.Type
+ c1 := auxIntToInt32(v_1.AuxInt)
+ if !(^(c1 | c2) == 0) {
+ continue
+ }
+ v.reset(OpOr32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c1)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or32 (Or32 i:(Const32 <t>) z) x)
+ // cond: (z.Op != OpConst32 && x.Op != OpConst32)
+ // result: (Or32 i (Or32 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOr32 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst32 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst32 && x.Op != OpConst32) {
+ continue
+ }
+ v.reset(OpOr32)
+ v0 := b.NewValue0(v.Pos, OpOr32, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or32 (Const32 <t> [c]) (Or32 (Const32 <t> [d]) x))
+ // result: (Or32 (Const32 <t> [c|d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpOr32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpOr32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c | d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpOr64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Or64 (Const64 [c]) (Const64 [d]))
+ // result: (Const64 [c|d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c | d)
+ return true
+ }
+ break
+ }
+ // match: (Or64 x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Or64 (Const64 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Or64 (Const64 [-1]) _)
+ // result: (Const64 [-1])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != -1 {
+ continue
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ break
+ }
+ // match: (Or64 x (Or64 x y))
+ // result: (Or64 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpOr64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(OpOr64)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or64 (And64 x (Const64 [c2])) (Const64 <t> [c1]))
+ // cond: ^(c1 | c2) == 0
+ // result: (Or64 (Const64 <t> [c1]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd64 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst64 {
+ continue
+ }
+ c2 := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ t := v_1.Type
+ c1 := auxIntToInt64(v_1.AuxInt)
+ if !(^(c1 | c2) == 0) {
+ continue
+ }
+ v.reset(OpOr64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c1)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or64 (Or64 i:(Const64 <t>) z) x)
+ // cond: (z.Op != OpConst64 && x.Op != OpConst64)
+ // result: (Or64 i (Or64 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOr64 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst64 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst64 && x.Op != OpConst64) {
+ continue
+ }
+ v.reset(OpOr64)
+ v0 := b.NewValue0(v.Pos, OpOr64, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or64 (Const64 <t> [c]) (Or64 (Const64 <t> [d]) x))
+ // result: (Or64 (Const64 <t> [c|d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpOr64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpOr64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c | d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpOr8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Or8 (Const8 [c]) (Const8 [d]))
+ // result: (Const8 [c|d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c | d)
+ return true
+ }
+ break
+ }
+ // match: (Or8 x x)
+ // result: x
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Or8 (Const8 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Or8 (Const8 [-1]) _)
+ // result: (Const8 [-1])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != -1 {
+ continue
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(-1)
+ return true
+ }
+ break
+ }
+ // match: (Or8 x (Or8 x y))
+ // result: (Or8 x y)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpOr8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.reset(OpOr8)
+ v.AddArg2(x, y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or8 (And8 x (Const8 [c2])) (Const8 <t> [c1]))
+ // cond: ^(c1 | c2) == 0
+ // result: (Or8 (Const8 <t> [c1]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpAnd8 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ x := v_0_0
+ if v_0_1.Op != OpConst8 {
+ continue
+ }
+ c2 := auxIntToInt8(v_0_1.AuxInt)
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ t := v_1.Type
+ c1 := auxIntToInt8(v_1.AuxInt)
+ if !(^(c1 | c2) == 0) {
+ continue
+ }
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c1)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or8 (Or8 i:(Const8 <t>) z) x)
+ // cond: (z.Op != OpConst8 && x.Op != OpConst8)
+ // result: (Or8 i (Or8 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpOr8 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst8 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst8 && x.Op != OpConst8) {
+ continue
+ }
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpOr8, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Or8 (Const8 <t> [c]) (Or8 (Const8 <t> [d]) x))
+ // result: (Or8 (Const8 <t> [c|d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpOr8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst8 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt8(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpOr8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c | d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpOrB(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (OrB (Less64 (Const64 [c]) x) (Less64 x (Const64 [d])))
+ // cond: c >= d
+ // result: (Less64U (Const64 <x.Type> [c-d]) (Sub64 <x.Type> x (Const64 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess64 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLess64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= d) {
+ continue
+ }
+ v.reset(OpLess64U)
+ v0 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v0.AuxInt = int64ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq64 (Const64 [c]) x) (Less64 x (Const64 [d])))
+ // cond: c >= d
+ // result: (Leq64U (Const64 <x.Type> [c-d]) (Sub64 <x.Type> x (Const64 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq64 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLess64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= d) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v0.AuxInt = int64ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less32 (Const32 [c]) x) (Less32 x (Const32 [d])))
+ // cond: c >= d
+ // result: (Less32U (Const32 <x.Type> [c-d]) (Sub32 <x.Type> x (Const32 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess32 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLess32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(c >= d) {
+ continue
+ }
+ v.reset(OpLess32U)
+ v0 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v0.AuxInt = int32ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq32 (Const32 [c]) x) (Less32 x (Const32 [d])))
+ // cond: c >= d
+ // result: (Leq32U (Const32 <x.Type> [c-d]) (Sub32 <x.Type> x (Const32 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq32 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLess32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(c >= d) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v0.AuxInt = int32ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less16 (Const16 [c]) x) (Less16 x (Const16 [d])))
+ // cond: c >= d
+ // result: (Less16U (Const16 <x.Type> [c-d]) (Sub16 <x.Type> x (Const16 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess16 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLess16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(c >= d) {
+ continue
+ }
+ v.reset(OpLess16U)
+ v0 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v0.AuxInt = int16ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq16 (Const16 [c]) x) (Less16 x (Const16 [d])))
+ // cond: c >= d
+ // result: (Leq16U (Const16 <x.Type> [c-d]) (Sub16 <x.Type> x (Const16 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq16 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLess16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(c >= d) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v0.AuxInt = int16ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less8 (Const8 [c]) x) (Less8 x (Const8 [d])))
+ // cond: c >= d
+ // result: (Less8U (Const8 <x.Type> [c-d]) (Sub8 <x.Type> x (Const8 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess8 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLess8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(c >= d) {
+ continue
+ }
+ v.reset(OpLess8U)
+ v0 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v0.AuxInt = int8ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq8 (Const8 [c]) x) (Less8 x (Const8 [d])))
+ // cond: c >= d
+ // result: (Leq8U (Const8 <x.Type> [c-d]) (Sub8 <x.Type> x (Const8 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq8 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLess8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(c >= d) {
+ continue
+ }
+ v.reset(OpLeq8U)
+ v0 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v0.AuxInt = int8ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less64 (Const64 [c]) x) (Leq64 x (Const64 [d])))
+ // cond: c >= d+1 && d+1 > d
+ // result: (Less64U (Const64 <x.Type> [c-d-1]) (Sub64 <x.Type> x (Const64 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess64 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLeq64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= d+1 && d+1 > d) {
+ continue
+ }
+ v.reset(OpLess64U)
+ v0 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v0.AuxInt = int64ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq64 (Const64 [c]) x) (Leq64 x (Const64 [d])))
+ // cond: c >= d+1 && d+1 > d
+ // result: (Leq64U (Const64 <x.Type> [c-d-1]) (Sub64 <x.Type> x (Const64 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq64 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLeq64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(c >= d+1 && d+1 > d) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v0.AuxInt = int64ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less32 (Const32 [c]) x) (Leq32 x (Const32 [d])))
+ // cond: c >= d+1 && d+1 > d
+ // result: (Less32U (Const32 <x.Type> [c-d-1]) (Sub32 <x.Type> x (Const32 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess32 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLeq32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(c >= d+1 && d+1 > d) {
+ continue
+ }
+ v.reset(OpLess32U)
+ v0 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v0.AuxInt = int32ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq32 (Const32 [c]) x) (Leq32 x (Const32 [d])))
+ // cond: c >= d+1 && d+1 > d
+ // result: (Leq32U (Const32 <x.Type> [c-d-1]) (Sub32 <x.Type> x (Const32 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq32 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLeq32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(c >= d+1 && d+1 > d) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v0.AuxInt = int32ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less16 (Const16 [c]) x) (Leq16 x (Const16 [d])))
+ // cond: c >= d+1 && d+1 > d
+ // result: (Less16U (Const16 <x.Type> [c-d-1]) (Sub16 <x.Type> x (Const16 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess16 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLeq16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(c >= d+1 && d+1 > d) {
+ continue
+ }
+ v.reset(OpLess16U)
+ v0 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v0.AuxInt = int16ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq16 (Const16 [c]) x) (Leq16 x (Const16 [d])))
+ // cond: c >= d+1 && d+1 > d
+ // result: (Leq16U (Const16 <x.Type> [c-d-1]) (Sub16 <x.Type> x (Const16 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq16 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLeq16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(c >= d+1 && d+1 > d) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v0.AuxInt = int16ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less8 (Const8 [c]) x) (Leq8 x (Const8 [d])))
+ // cond: c >= d+1 && d+1 > d
+ // result: (Less8U (Const8 <x.Type> [c-d-1]) (Sub8 <x.Type> x (Const8 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess8 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLeq8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(c >= d+1 && d+1 > d) {
+ continue
+ }
+ v.reset(OpLess8U)
+ v0 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v0.AuxInt = int8ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq8 (Const8 [c]) x) (Leq8 x (Const8 [d])))
+ // cond: c >= d+1 && d+1 > d
+ // result: (Leq8U (Const8 <x.Type> [c-d-1]) (Sub8 <x.Type> x (Const8 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq8 {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLeq8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(c >= d+1 && d+1 > d) {
+ continue
+ }
+ v.reset(OpLeq8U)
+ v0 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v0.AuxInt = int8ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less64U (Const64 [c]) x) (Less64U x (Const64 [d])))
+ // cond: uint64(c) >= uint64(d)
+ // result: (Less64U (Const64 <x.Type> [c-d]) (Sub64 <x.Type> x (Const64 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess64U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLess64U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(uint64(c) >= uint64(d)) {
+ continue
+ }
+ v.reset(OpLess64U)
+ v0 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v0.AuxInt = int64ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq64U (Const64 [c]) x) (Less64U x (Const64 [d])))
+ // cond: uint64(c) >= uint64(d)
+ // result: (Leq64U (Const64 <x.Type> [c-d]) (Sub64 <x.Type> x (Const64 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq64U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLess64U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(uint64(c) >= uint64(d)) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v0.AuxInt = int64ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less32U (Const32 [c]) x) (Less32U x (Const32 [d])))
+ // cond: uint32(c) >= uint32(d)
+ // result: (Less32U (Const32 <x.Type> [c-d]) (Sub32 <x.Type> x (Const32 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess32U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLess32U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(uint32(c) >= uint32(d)) {
+ continue
+ }
+ v.reset(OpLess32U)
+ v0 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v0.AuxInt = int32ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq32U (Const32 [c]) x) (Less32U x (Const32 [d])))
+ // cond: uint32(c) >= uint32(d)
+ // result: (Leq32U (Const32 <x.Type> [c-d]) (Sub32 <x.Type> x (Const32 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq32U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLess32U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(uint32(c) >= uint32(d)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v0.AuxInt = int32ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less16U (Const16 [c]) x) (Less16U x (Const16 [d])))
+ // cond: uint16(c) >= uint16(d)
+ // result: (Less16U (Const16 <x.Type> [c-d]) (Sub16 <x.Type> x (Const16 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess16U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLess16U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(uint16(c) >= uint16(d)) {
+ continue
+ }
+ v.reset(OpLess16U)
+ v0 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v0.AuxInt = int16ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq16U (Const16 [c]) x) (Less16U x (Const16 [d])))
+ // cond: uint16(c) >= uint16(d)
+ // result: (Leq16U (Const16 <x.Type> [c-d]) (Sub16 <x.Type> x (Const16 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq16U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLess16U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(uint16(c) >= uint16(d)) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v0.AuxInt = int16ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less8U (Const8 [c]) x) (Less8U x (Const8 [d])))
+ // cond: uint8(c) >= uint8(d)
+ // result: (Less8U (Const8 <x.Type> [c-d]) (Sub8 <x.Type> x (Const8 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess8U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLess8U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(uint8(c) >= uint8(d)) {
+ continue
+ }
+ v.reset(OpLess8U)
+ v0 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v0.AuxInt = int8ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq8U (Const8 [c]) x) (Less8U x (Const8 [d])))
+ // cond: uint8(c) >= uint8(d)
+ // result: (Leq8U (Const8 <x.Type> [c-d]) (Sub8 <x.Type> x (Const8 <x.Type> [d])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq8U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLess8U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(uint8(c) >= uint8(d)) {
+ continue
+ }
+ v.reset(OpLeq8U)
+ v0 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v0.AuxInt = int8ToAuxInt(c - d)
+ v1 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less64U (Const64 [c]) x) (Leq64U x (Const64 [d])))
+ // cond: uint64(c) >= uint64(d+1) && uint64(d+1) > uint64(d)
+ // result: (Less64U (Const64 <x.Type> [c-d-1]) (Sub64 <x.Type> x (Const64 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess64U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLeq64U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(uint64(c) >= uint64(d+1) && uint64(d+1) > uint64(d)) {
+ continue
+ }
+ v.reset(OpLess64U)
+ v0 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v0.AuxInt = int64ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq64U (Const64 [c]) x) (Leq64U x (Const64 [d])))
+ // cond: uint64(c) >= uint64(d+1) && uint64(d+1) > uint64(d)
+ // result: (Leq64U (Const64 <x.Type> [c-d-1]) (Sub64 <x.Type> x (Const64 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq64U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ if v_1.Op != OpLeq64U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1_1.AuxInt)
+ if !(uint64(c) >= uint64(d+1) && uint64(d+1) > uint64(d)) {
+ continue
+ }
+ v.reset(OpLeq64U)
+ v0 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v0.AuxInt = int64ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub64, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst64, x.Type)
+ v2.AuxInt = int64ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less32U (Const32 [c]) x) (Leq32U x (Const32 [d])))
+ // cond: uint32(c) >= uint32(d+1) && uint32(d+1) > uint32(d)
+ // result: (Less32U (Const32 <x.Type> [c-d-1]) (Sub32 <x.Type> x (Const32 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess32U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLeq32U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(uint32(c) >= uint32(d+1) && uint32(d+1) > uint32(d)) {
+ continue
+ }
+ v.reset(OpLess32U)
+ v0 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v0.AuxInt = int32ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq32U (Const32 [c]) x) (Leq32U x (Const32 [d])))
+ // cond: uint32(c) >= uint32(d+1) && uint32(d+1) > uint32(d)
+ // result: (Leq32U (Const32 <x.Type> [c-d-1]) (Sub32 <x.Type> x (Const32 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq32U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0_0.AuxInt)
+ if v_1.Op != OpLeq32U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1_1.AuxInt)
+ if !(uint32(c) >= uint32(d+1) && uint32(d+1) > uint32(d)) {
+ continue
+ }
+ v.reset(OpLeq32U)
+ v0 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v0.AuxInt = int32ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub32, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst32, x.Type)
+ v2.AuxInt = int32ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less16U (Const16 [c]) x) (Leq16U x (Const16 [d])))
+ // cond: uint16(c) >= uint16(d+1) && uint16(d+1) > uint16(d)
+ // result: (Less16U (Const16 <x.Type> [c-d-1]) (Sub16 <x.Type> x (Const16 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess16U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLeq16U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(uint16(c) >= uint16(d+1) && uint16(d+1) > uint16(d)) {
+ continue
+ }
+ v.reset(OpLess16U)
+ v0 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v0.AuxInt = int16ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq16U (Const16 [c]) x) (Leq16U x (Const16 [d])))
+ // cond: uint16(c) >= uint16(d+1) && uint16(d+1) > uint16(d)
+ // result: (Leq16U (Const16 <x.Type> [c-d-1]) (Sub16 <x.Type> x (Const16 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq16U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0_0.AuxInt)
+ if v_1.Op != OpLeq16U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1_1.AuxInt)
+ if !(uint16(c) >= uint16(d+1) && uint16(d+1) > uint16(d)) {
+ continue
+ }
+ v.reset(OpLeq16U)
+ v0 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v0.AuxInt = int16ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub16, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst16, x.Type)
+ v2.AuxInt = int16ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Less8U (Const8 [c]) x) (Leq8U x (Const8 [d])))
+ // cond: uint8(c) >= uint8(d+1) && uint8(d+1) > uint8(d)
+ // result: (Less8U (Const8 <x.Type> [c-d-1]) (Sub8 <x.Type> x (Const8 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLess8U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLeq8U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(uint8(c) >= uint8(d+1) && uint8(d+1) > uint8(d)) {
+ continue
+ }
+ v.reset(OpLess8U)
+ v0 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v0.AuxInt = int8ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ // match: (OrB (Leq8U (Const8 [c]) x) (Leq8U x (Const8 [d])))
+ // cond: uint8(c) >= uint8(d+1) && uint8(d+1) > uint8(d)
+ // result: (Leq8U (Const8 <x.Type> [c-d-1]) (Sub8 <x.Type> x (Const8 <x.Type> [d+1])))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpLeq8U {
+ continue
+ }
+ x := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0_0.AuxInt)
+ if v_1.Op != OpLeq8U {
+ continue
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ continue
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1_1.AuxInt)
+ if !(uint8(c) >= uint8(d+1) && uint8(d+1) > uint8(d)) {
+ continue
+ }
+ v.reset(OpLeq8U)
+ v0 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v0.AuxInt = int8ToAuxInt(c - d - 1)
+ v1 := b.NewValue0(v.Pos, OpSub8, x.Type)
+ v2 := b.NewValue0(v.Pos, OpConst8, x.Type)
+ v2.AuxInt = int8ToAuxInt(d + 1)
+ v1.AddArg2(x, v2)
+ v.AddArg2(v0, v1)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpPhi(v *Value) bool {
+ // match: (Phi (Const8 [c]) (Const8 [c]))
+ // result: (Const8 [c])
+ for {
+ if len(v.Args) != 2 {
+ break
+ }
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v_1 := v.Args[1]
+ if v_1.Op != OpConst8 || auxIntToInt8(v_1.AuxInt) != c {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c)
+ return true
+ }
+ // match: (Phi (Const16 [c]) (Const16 [c]))
+ // result: (Const16 [c])
+ for {
+ if len(v.Args) != 2 {
+ break
+ }
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v_1 := v.Args[1]
+ if v_1.Op != OpConst16 || auxIntToInt16(v_1.AuxInt) != c {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c)
+ return true
+ }
+ // match: (Phi (Const32 [c]) (Const32 [c]))
+ // result: (Const32 [c])
+ for {
+ if len(v.Args) != 2 {
+ break
+ }
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v_1 := v.Args[1]
+ if v_1.Op != OpConst32 || auxIntToInt32(v_1.AuxInt) != c {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c)
+ return true
+ }
+ // match: (Phi (Const64 [c]) (Const64 [c]))
+ // result: (Const64 [c])
+ for {
+ if len(v.Args) != 2 {
+ break
+ }
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v_1 := v.Args[1]
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != c {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpPtrIndex(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ typ := &b.Func.Config.Types
+ // match: (PtrIndex <t> ptr idx)
+ // cond: config.PtrSize == 4 && is32Bit(t.Elem().Size())
+ // result: (AddPtr ptr (Mul32 <typ.Int> idx (Const32 <typ.Int> [int32(t.Elem().Size())])))
+ for {
+ t := v.Type
+ ptr := v_0
+ idx := v_1
+ if !(config.PtrSize == 4 && is32Bit(t.Elem().Size())) {
+ break
+ }
+ v.reset(OpAddPtr)
+ v0 := b.NewValue0(v.Pos, OpMul32, typ.Int)
+ v1 := b.NewValue0(v.Pos, OpConst32, typ.Int)
+ v1.AuxInt = int32ToAuxInt(int32(t.Elem().Size()))
+ v0.AddArg2(idx, v1)
+ v.AddArg2(ptr, v0)
+ return true
+ }
+ // match: (PtrIndex <t> ptr idx)
+ // cond: config.PtrSize == 8
+ // result: (AddPtr ptr (Mul64 <typ.Int> idx (Const64 <typ.Int> [t.Elem().Size()])))
+ for {
+ t := v.Type
+ ptr := v_0
+ idx := v_1
+ if !(config.PtrSize == 8) {
+ break
+ }
+ v.reset(OpAddPtr)
+ v0 := b.NewValue0(v.Pos, OpMul64, typ.Int)
+ v1 := b.NewValue0(v.Pos, OpConst64, typ.Int)
+ v1.AuxInt = int64ToAuxInt(t.Elem().Size())
+ v0.AddArg2(idx, v1)
+ v.AddArg2(ptr, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRotateLeft16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RotateLeft16 x (Const16 [c]))
+ // cond: c%16 == 0
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(c%16 == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRotateLeft32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RotateLeft32 x (Const32 [c]))
+ // cond: c%32 == 0
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(c%32 == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRotateLeft64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RotateLeft64 x (Const64 [c]))
+ // cond: c%64 == 0
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(c%64 == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRotateLeft8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (RotateLeft8 x (Const8 [c]))
+ // cond: c%8 == 0
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(c%8 == 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRound32F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Round32F x:(Const32F))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpConst32F {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRound64F(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Round64F x:(Const64F))
+ // result: x
+ for {
+ x := v_0
+ if x.Op != OpConst64F {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh16Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16Ux16 <t> x (Const16 [c]))
+ // result: (Rsh16Ux64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRsh16Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16Ux16 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh16Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16Ux32 <t> x (Const32 [c]))
+ // result: (Rsh16Ux64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRsh16Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16Ux32 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh16Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16Ux64 (Const16 [c]) (Const64 [d]))
+ // result: (Const16 [int16(uint16(c) >> uint64(d))])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(int16(uint16(c) >> uint64(d)))
+ return true
+ }
+ // match: (Rsh16Ux64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Rsh16Ux64 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh16Ux64 _ (Const64 [c]))
+ // cond: uint64(c) >= 16
+ // result: (Const16 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 16) {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh16Ux64 <t> (Rsh16Ux64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Rsh16Ux64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpRsh16Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpRsh16Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16Ux64 (Rsh16x64 x _) (Const64 <t> [15]))
+ // result: (Rsh16Ux64 x (Const64 <t> [15]))
+ for {
+ if v_0.Op != OpRsh16x64 {
+ break
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpConst64 {
+ break
+ }
+ t := v_1.Type
+ if auxIntToInt64(v_1.AuxInt) != 15 {
+ break
+ }
+ v.reset(OpRsh16Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(15)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16Ux64 (Lsh16x64 (Rsh16Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
+ // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
+ // result: (Rsh16Ux64 x (Const64 <typ.UInt64> [c1-c2+c3]))
+ for {
+ if v_0.Op != OpLsh16x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpRsh16Ux64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c1 := auxIntToInt64(v_0_0_1.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c2 := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c3 := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) {
+ break
+ }
+ v.reset(OpRsh16Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(c1 - c2 + c3)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16Ux64 (Lsh16x64 x (Const64 [8])) (Const64 [8]))
+ // result: (ZeroExt8to16 (Trunc16to8 <typ.UInt8> x))
+ for {
+ if v_0.Op != OpLsh16x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 8 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 8 {
+ break
+ }
+ v.reset(OpZeroExt8to16)
+ v0 := b.NewValue0(v.Pos, OpTrunc16to8, typ.UInt8)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh16Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16Ux8 <t> x (Const8 [c]))
+ // result: (Rsh16Ux64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRsh16Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16Ux8 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh16x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16x16 <t> x (Const16 [c]))
+ // result: (Rsh16x64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRsh16x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x16 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh16x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16x32 <t> x (Const32 [c]))
+ // result: (Rsh16x64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRsh16x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x32 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh16x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh16x64 (Const16 [c]) (Const64 [d]))
+ // result: (Const16 [c >> uint64(d)])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c >> uint64(d))
+ return true
+ }
+ // match: (Rsh16x64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Rsh16x64 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh16x64 <t> (Rsh16x64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Rsh16x64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpRsh16x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpRsh16x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x64 (Lsh16x64 x (Const64 [8])) (Const64 [8]))
+ // result: (SignExt8to16 (Trunc16to8 <typ.Int8> x))
+ for {
+ if v_0.Op != OpLsh16x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 8 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 8 {
+ break
+ }
+ v.reset(OpSignExt8to16)
+ v0 := b.NewValue0(v.Pos, OpTrunc16to8, typ.Int8)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh16x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh16x8 <t> x (Const8 [c]))
+ // result: (Rsh16x64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRsh16x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh16x8 (Const16 [0]) _)
+ // result: (Const16 [0])
+ for {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh32Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux16 <t> x (Const16 [c]))
+ // result: (Rsh32Ux64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRsh32Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32Ux16 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh32Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux32 <t> x (Const32 [c]))
+ // result: (Rsh32Ux64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRsh32Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32Ux32 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh32Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32Ux64 (Const32 [c]) (Const64 [d]))
+ // result: (Const32 [int32(uint32(c) >> uint64(d))])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
+ return true
+ }
+ // match: (Rsh32Ux64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Rsh32Ux64 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh32Ux64 _ (Const64 [c]))
+ // cond: uint64(c) >= 32
+ // result: (Const32 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 32) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh32Ux64 <t> (Rsh32Ux64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Rsh32Ux64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpRsh32Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpRsh32Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32Ux64 (Rsh32x64 x _) (Const64 <t> [31]))
+ // result: (Rsh32Ux64 x (Const64 <t> [31]))
+ for {
+ if v_0.Op != OpRsh32x64 {
+ break
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpConst64 {
+ break
+ }
+ t := v_1.Type
+ if auxIntToInt64(v_1.AuxInt) != 31 {
+ break
+ }
+ v.reset(OpRsh32Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(31)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32Ux64 (Lsh32x64 (Rsh32Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
+ // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
+ // result: (Rsh32Ux64 x (Const64 <typ.UInt64> [c1-c2+c3]))
+ for {
+ if v_0.Op != OpLsh32x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpRsh32Ux64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c1 := auxIntToInt64(v_0_0_1.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c2 := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c3 := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) {
+ break
+ }
+ v.reset(OpRsh32Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(c1 - c2 + c3)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32Ux64 (Lsh32x64 x (Const64 [24])) (Const64 [24]))
+ // result: (ZeroExt8to32 (Trunc32to8 <typ.UInt8> x))
+ for {
+ if v_0.Op != OpLsh32x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 24 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 24 {
+ break
+ }
+ v.reset(OpZeroExt8to32)
+ v0 := b.NewValue0(v.Pos, OpTrunc32to8, typ.UInt8)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh32Ux64 (Lsh32x64 x (Const64 [16])) (Const64 [16]))
+ // result: (ZeroExt16to32 (Trunc32to16 <typ.UInt16> x))
+ for {
+ if v_0.Op != OpLsh32x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 16 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 16 {
+ break
+ }
+ v.reset(OpZeroExt16to32)
+ v0 := b.NewValue0(v.Pos, OpTrunc32to16, typ.UInt16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh32Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32Ux8 <t> x (Const8 [c]))
+ // result: (Rsh32Ux64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRsh32Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32Ux8 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh32x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x16 <t> x (Const16 [c]))
+ // result: (Rsh32x64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRsh32x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x16 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh32x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x32 <t> x (Const32 [c]))
+ // result: (Rsh32x64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRsh32x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x32 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh32x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh32x64 (Const32 [c]) (Const64 [d]))
+ // result: (Const32 [c >> uint64(d)])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c >> uint64(d))
+ return true
+ }
+ // match: (Rsh32x64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Rsh32x64 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh32x64 <t> (Rsh32x64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Rsh32x64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpRsh32x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpRsh32x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x64 (Lsh32x64 x (Const64 [24])) (Const64 [24]))
+ // result: (SignExt8to32 (Trunc32to8 <typ.Int8> x))
+ for {
+ if v_0.Op != OpLsh32x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 24 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 24 {
+ break
+ }
+ v.reset(OpSignExt8to32)
+ v0 := b.NewValue0(v.Pos, OpTrunc32to8, typ.Int8)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh32x64 (Lsh32x64 x (Const64 [16])) (Const64 [16]))
+ // result: (SignExt16to32 (Trunc32to16 <typ.Int16> x))
+ for {
+ if v_0.Op != OpLsh32x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 16 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 16 {
+ break
+ }
+ v.reset(OpSignExt16to32)
+ v0 := b.NewValue0(v.Pos, OpTrunc32to16, typ.Int16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh32x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh32x8 <t> x (Const8 [c]))
+ // result: (Rsh32x64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRsh32x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh32x8 (Const32 [0]) _)
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh64Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64Ux16 <t> x (Const16 [c]))
+ // result: (Rsh64Ux64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux16 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh64Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64Ux32 <t> x (Const32 [c]))
+ // result: (Rsh64Ux64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux32 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh64Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64Ux64 (Const64 [c]) (Const64 [d]))
+ // result: (Const64 [int64(uint64(c) >> uint64(d))])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(uint64(c) >> uint64(d)))
+ return true
+ }
+ // match: (Rsh64Ux64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Rsh64Ux64 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh64Ux64 _ (Const64 [c]))
+ // cond: uint64(c) >= 64
+ // result: (Const64 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 64) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh64Ux64 <t> (Rsh64Ux64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Rsh64Ux64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpRsh64Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux64 (Rsh64x64 x _) (Const64 <t> [63]))
+ // result: (Rsh64Ux64 x (Const64 <t> [63]))
+ for {
+ if v_0.Op != OpRsh64x64 {
+ break
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpConst64 {
+ break
+ }
+ t := v_1.Type
+ if auxIntToInt64(v_1.AuxInt) != 63 {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(63)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux64 (Lsh64x64 (Rsh64Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
+ // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
+ // result: (Rsh64Ux64 x (Const64 <typ.UInt64> [c1-c2+c3]))
+ for {
+ if v_0.Op != OpLsh64x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpRsh64Ux64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c1 := auxIntToInt64(v_0_0_1.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c2 := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c3 := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(c1 - c2 + c3)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux64 (Lsh64x64 x (Const64 [56])) (Const64 [56]))
+ // result: (ZeroExt8to64 (Trunc64to8 <typ.UInt8> x))
+ for {
+ if v_0.Op != OpLsh64x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 56 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 56 {
+ break
+ }
+ v.reset(OpZeroExt8to64)
+ v0 := b.NewValue0(v.Pos, OpTrunc64to8, typ.UInt8)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh64Ux64 (Lsh64x64 x (Const64 [48])) (Const64 [48]))
+ // result: (ZeroExt16to64 (Trunc64to16 <typ.UInt16> x))
+ for {
+ if v_0.Op != OpLsh64x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 48 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 48 {
+ break
+ }
+ v.reset(OpZeroExt16to64)
+ v0 := b.NewValue0(v.Pos, OpTrunc64to16, typ.UInt16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh64Ux64 (Lsh64x64 x (Const64 [32])) (Const64 [32]))
+ // result: (ZeroExt32to64 (Trunc64to32 <typ.UInt32> x))
+ for {
+ if v_0.Op != OpLsh64x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 32 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 32 {
+ break
+ }
+ v.reset(OpZeroExt32to64)
+ v0 := b.NewValue0(v.Pos, OpTrunc64to32, typ.UInt32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh64Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64Ux8 <t> x (Const8 [c]))
+ // result: (Rsh64Ux64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64Ux8 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh64x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x16 <t> x (Const16 [c]))
+ // result: (Rsh64x64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRsh64x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x16 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh64x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x32 <t> x (Const32 [c]))
+ // result: (Rsh64x64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRsh64x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x32 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh64x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh64x64 (Const64 [c]) (Const64 [d]))
+ // result: (Const64 [c >> uint64(d)])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c >> uint64(d))
+ return true
+ }
+ // match: (Rsh64x64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Rsh64x64 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh64x64 <t> (Rsh64x64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Rsh64x64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpRsh64x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpRsh64x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x64 (Lsh64x64 x (Const64 [56])) (Const64 [56]))
+ // result: (SignExt8to64 (Trunc64to8 <typ.Int8> x))
+ for {
+ if v_0.Op != OpLsh64x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 56 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 56 {
+ break
+ }
+ v.reset(OpSignExt8to64)
+ v0 := b.NewValue0(v.Pos, OpTrunc64to8, typ.Int8)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh64x64 (Lsh64x64 x (Const64 [48])) (Const64 [48]))
+ // result: (SignExt16to64 (Trunc64to16 <typ.Int16> x))
+ for {
+ if v_0.Op != OpLsh64x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 48 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 48 {
+ break
+ }
+ v.reset(OpSignExt16to64)
+ v0 := b.NewValue0(v.Pos, OpTrunc64to16, typ.Int16)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (Rsh64x64 (Lsh64x64 x (Const64 [32])) (Const64 [32]))
+ // result: (SignExt32to64 (Trunc64to32 <typ.Int32> x))
+ for {
+ if v_0.Op != OpLsh64x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 32 || v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 32 {
+ break
+ }
+ v.reset(OpSignExt32to64)
+ v0 := b.NewValue0(v.Pos, OpTrunc64to32, typ.Int32)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh64x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh64x8 <t> x (Const8 [c]))
+ // result: (Rsh64x64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRsh64x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh64x8 (Const64 [0]) _)
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh8Ux16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8Ux16 <t> x (Const16 [c]))
+ // result: (Rsh8Ux64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRsh8Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8Ux16 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh8Ux32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8Ux32 <t> x (Const32 [c]))
+ // result: (Rsh8Ux64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRsh8Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8Ux32 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh8Ux64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (Rsh8Ux64 (Const8 [c]) (Const64 [d]))
+ // result: (Const8 [int8(uint8(c) >> uint64(d))])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(int8(uint8(c) >> uint64(d)))
+ return true
+ }
+ // match: (Rsh8Ux64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Rsh8Ux64 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh8Ux64 _ (Const64 [c]))
+ // cond: uint64(c) >= 8
+ // result: (Const8 [0])
+ for {
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c) >= 8) {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh8Ux64 <t> (Rsh8Ux64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Rsh8Ux64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpRsh8Ux64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpRsh8Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8Ux64 (Rsh8x64 x _) (Const64 <t> [7] ))
+ // result: (Rsh8Ux64 x (Const64 <t> [7] ))
+ for {
+ if v_0.Op != OpRsh8x64 {
+ break
+ }
+ x := v_0.Args[0]
+ if v_1.Op != OpConst64 {
+ break
+ }
+ t := v_1.Type
+ if auxIntToInt64(v_1.AuxInt) != 7 {
+ break
+ }
+ v.reset(OpRsh8Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(7)
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8Ux64 (Lsh8x64 (Rsh8Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
+ // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
+ // result: (Rsh8Ux64 x (Const64 <typ.UInt64> [c1-c2+c3]))
+ for {
+ if v_0.Op != OpLsh8x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpRsh8Ux64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpConst64 {
+ break
+ }
+ c1 := auxIntToInt64(v_0_0_1.AuxInt)
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c2 := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ c3 := auxIntToInt64(v_1.AuxInt)
+ if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) {
+ break
+ }
+ v.reset(OpRsh8Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(c1 - c2 + c3)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh8Ux8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8Ux8 <t> x (Const8 [c]))
+ // result: (Rsh8Ux64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRsh8Ux64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8Ux8 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh8x16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x16 <t> x (Const16 [c]))
+ // result: (Rsh8x64 x (Const64 <t> [int64(uint16(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpRsh8x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x16 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh8x32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x32 <t> x (Const32 [c]))
+ // result: (Rsh8x64 x (Const64 <t> [int64(uint32(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpRsh8x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x32 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh8x64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x64 (Const8 [c]) (Const64 [d]))
+ // result: (Const8 [c >> uint64(d)])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c >> uint64(d))
+ return true
+ }
+ // match: (Rsh8x64 x (Const64 [0]))
+ // result: x
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != 0 {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ // match: (Rsh8x64 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ // match: (Rsh8x64 <t> (Rsh8x64 x (Const64 [c])) (Const64 [d]))
+ // cond: !uaddOvf(c,d)
+ // result: (Rsh8x64 x (Const64 <t> [c+d]))
+ for {
+ t := v.Type
+ if v_0.Op != OpRsh8x64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0_1.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ if !(!uaddOvf(c, d)) {
+ break
+ }
+ v.reset(OpRsh8x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c + d)
+ v.AddArg2(x, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpRsh8x8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Rsh8x8 <t> x (Const8 [c]))
+ // result: (Rsh8x64 x (Const64 <t> [int64(uint8(c))]))
+ for {
+ t := v.Type
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpRsh8x64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ v.AddArg2(x, v0)
+ return true
+ }
+ // match: (Rsh8x8 (Const8 [0]) _)
+ // result: (Const8 [0])
+ for {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSelect0(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Select0 (Div128u (Const64 [0]) lo y))
+ // result: (Div64u lo y)
+ for {
+ if v_0.Op != OpDiv128u {
+ break
+ }
+ y := v_0.Args[2]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 0 {
+ break
+ }
+ lo := v_0.Args[1]
+ v.reset(OpDiv64u)
+ v.AddArg2(lo, y)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSelect1(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Select1 (Div128u (Const64 [0]) lo y))
+ // result: (Mod64u lo y)
+ for {
+ if v_0.Op != OpDiv128u {
+ break
+ }
+ y := v_0.Args[2]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 0 {
+ break
+ }
+ lo := v_0.Args[1]
+ v.reset(OpMod64u)
+ v.AddArg2(lo, y)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSelectN(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (SelectN [0] (MakeResult a ___))
+ // result: a
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 || v_0.Op != OpMakeResult || len(v_0.Args) < 1 {
+ break
+ }
+ a := v_0.Args[0]
+ v.copyOf(a)
+ return true
+ }
+ // match: (SelectN [1] (MakeResult a b ___))
+ // result: b
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 || v_0.Op != OpMakeResult || len(v_0.Args) < 2 {
+ break
+ }
+ b := v_0.Args[1]
+ v.copyOf(b)
+ return true
+ }
+ // match: (SelectN [2] (MakeResult a b c ___))
+ // result: c
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 || v_0.Op != OpMakeResult || len(v_0.Args) < 3 {
+ break
+ }
+ c := v_0.Args[2]
+ v.copyOf(c)
+ return true
+ }
+ // match: (SelectN [0] call:(StaticLECall {sym} dst src (Const64 [sz]) mem))
+ // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
+ // result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ call := v_0
+ if call.Op != OpStaticLECall || len(call.Args) != 4 {
+ break
+ }
+ sym := auxToCall(call.Aux)
+ mem := call.Args[3]
+ dst := call.Args[0]
+ src := call.Args[1]
+ call_2 := call.Args[2]
+ if call_2.Op != OpConst64 {
+ break
+ }
+ sz := auxIntToInt64(call_2.AuxInt)
+ if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(int64(sz))
+ v.Aux = typeToAux(dst.Type.Elem())
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (SelectN [0] call:(StaticLECall {sym} dst src (Const32 [sz]) mem))
+ // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
+ // result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 {
+ break
+ }
+ call := v_0
+ if call.Op != OpStaticLECall || len(call.Args) != 4 {
+ break
+ }
+ sym := auxToCall(call.Aux)
+ mem := call.Args[3]
+ dst := call.Args[0]
+ src := call.Args[1]
+ call_2 := call.Args[2]
+ if call_2.Op != OpConst32 {
+ break
+ }
+ sz := auxIntToInt32(call_2.AuxInt)
+ if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(int64(sz))
+ v.Aux = typeToAux(dst.Type.Elem())
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSignExt16to32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SignExt16to32 (Const16 [c]))
+ // result: (Const32 [int32(c)])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ return true
+ }
+ // match: (SignExt16to32 (Trunc32to16 x:(Rsh32x64 _ (Const64 [s]))))
+ // cond: s >= 16
+ // result: x
+ for {
+ if v_0.Op != OpTrunc32to16 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh32x64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 16) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSignExt16to64(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SignExt16to64 (Const16 [c]))
+ // result: (Const64 [int64(c)])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ // match: (SignExt16to64 (Trunc64to16 x:(Rsh64x64 _ (Const64 [s]))))
+ // cond: s >= 48
+ // result: x
+ for {
+ if v_0.Op != OpTrunc64to16 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh64x64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 48) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSignExt32to64(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SignExt32to64 (Const32 [c]))
+ // result: (Const64 [int64(c)])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ // match: (SignExt32to64 (Trunc64to32 x:(Rsh64x64 _ (Const64 [s]))))
+ // cond: s >= 32
+ // result: x
+ for {
+ if v_0.Op != OpTrunc64to32 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh64x64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 32) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSignExt8to16(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SignExt8to16 (Const8 [c]))
+ // result: (Const16 [int16(c)])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ return true
+ }
+ // match: (SignExt8to16 (Trunc16to8 x:(Rsh16x64 _ (Const64 [s]))))
+ // cond: s >= 8
+ // result: x
+ for {
+ if v_0.Op != OpTrunc16to8 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh16x64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 8) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSignExt8to32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SignExt8to32 (Const8 [c]))
+ // result: (Const32 [int32(c)])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ return true
+ }
+ // match: (SignExt8to32 (Trunc32to8 x:(Rsh32x64 _ (Const64 [s]))))
+ // cond: s >= 24
+ // result: x
+ for {
+ if v_0.Op != OpTrunc32to8 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh32x64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 24) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSignExt8to64(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SignExt8to64 (Const8 [c]))
+ // result: (Const64 [int64(c)])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(c))
+ return true
+ }
+ // match: (SignExt8to64 (Trunc64to8 x:(Rsh64x64 _ (Const64 [s]))))
+ // cond: s >= 56
+ // result: x
+ for {
+ if v_0.Op != OpTrunc64to8 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh64x64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 56) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSliceCap(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SliceCap (SliceMake _ _ (Const64 <t> [c])))
+ // result: (Const64 <t> [c])
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ _ = v_0.Args[2]
+ v_0_2 := v_0.Args[2]
+ if v_0_2.Op != OpConst64 {
+ break
+ }
+ t := v_0_2.Type
+ c := auxIntToInt64(v_0_2.AuxInt)
+ v.reset(OpConst64)
+ v.Type = t
+ v.AuxInt = int64ToAuxInt(c)
+ return true
+ }
+ // match: (SliceCap (SliceMake _ _ (Const32 <t> [c])))
+ // result: (Const32 <t> [c])
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ _ = v_0.Args[2]
+ v_0_2 := v_0.Args[2]
+ if v_0_2.Op != OpConst32 {
+ break
+ }
+ t := v_0_2.Type
+ c := auxIntToInt32(v_0_2.AuxInt)
+ v.reset(OpConst32)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(c)
+ return true
+ }
+ // match: (SliceCap (SliceMake _ _ (SliceCap x)))
+ // result: (SliceCap x)
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ _ = v_0.Args[2]
+ v_0_2 := v_0.Args[2]
+ if v_0_2.Op != OpSliceCap {
+ break
+ }
+ x := v_0_2.Args[0]
+ v.reset(OpSliceCap)
+ v.AddArg(x)
+ return true
+ }
+ // match: (SliceCap (SliceMake _ _ (SliceLen x)))
+ // result: (SliceLen x)
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ _ = v_0.Args[2]
+ v_0_2 := v_0.Args[2]
+ if v_0_2.Op != OpSliceLen {
+ break
+ }
+ x := v_0_2.Args[0]
+ v.reset(OpSliceLen)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSliceLen(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SliceLen (SliceMake _ (Const64 <t> [c]) _))
+ // result: (Const64 <t> [c])
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ t := v_0_1.Type
+ c := auxIntToInt64(v_0_1.AuxInt)
+ v.reset(OpConst64)
+ v.Type = t
+ v.AuxInt = int64ToAuxInt(c)
+ return true
+ }
+ // match: (SliceLen (SliceMake _ (Const32 <t> [c]) _))
+ // result: (Const32 <t> [c])
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst32 {
+ break
+ }
+ t := v_0_1.Type
+ c := auxIntToInt32(v_0_1.AuxInt)
+ v.reset(OpConst32)
+ v.Type = t
+ v.AuxInt = int32ToAuxInt(c)
+ return true
+ }
+ // match: (SliceLen (SliceMake _ (SliceLen x) _))
+ // result: (SliceLen x)
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpSliceLen {
+ break
+ }
+ x := v_0_1.Args[0]
+ v.reset(OpSliceLen)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSlicePtr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (SlicePtr (SliceMake (SlicePtr x) _ _))
+ // result: (SlicePtr x)
+ for {
+ if v_0.Op != OpSliceMake {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSlicePtr {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpSlicePtr)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSlicemask(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Slicemask (Const32 [x]))
+ // cond: x > 0
+ // result: (Const32 [-1])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ x := auxIntToInt32(v_0.AuxInt)
+ if !(x > 0) {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(-1)
+ return true
+ }
+ // match: (Slicemask (Const32 [0]))
+ // result: (Const32 [0])
+ for {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Slicemask (Const64 [x]))
+ // cond: x > 0
+ // result: (Const64 [-1])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ x := auxIntToInt64(v_0.AuxInt)
+ if !(x > 0) {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(-1)
+ return true
+ }
+ // match: (Slicemask (Const64 [0]))
+ // result: (Const64 [0])
+ for {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSqrt(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Sqrt (Const64F [c]))
+ // cond: !math.IsNaN(math.Sqrt(c))
+ // result: (Const64F [math.Sqrt(c)])
+ for {
+ if v_0.Op != OpConst64F {
+ break
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ if !(!math.IsNaN(math.Sqrt(c))) {
+ break
+ }
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(math.Sqrt(c))
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpStaticCall(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (StaticCall {sym} s1:(Store _ (Const64 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem))))
+ // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3)
+ // result: (Move {t.Elem()} [int64(sz)] dst src mem)
+ for {
+ sym := auxToCall(v.Aux)
+ s1 := v_0
+ if s1.Op != OpStore {
+ break
+ }
+ _ = s1.Args[2]
+ s1_1 := s1.Args[1]
+ if s1_1.Op != OpConst64 {
+ break
+ }
+ sz := auxIntToInt64(s1_1.AuxInt)
+ s2 := s1.Args[2]
+ if s2.Op != OpStore {
+ break
+ }
+ _ = s2.Args[2]
+ src := s2.Args[1]
+ s3 := s2.Args[2]
+ if s3.Op != OpStore {
+ break
+ }
+ t := auxToType(s3.Aux)
+ mem := s3.Args[2]
+ dst := s3.Args[1]
+ if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(int64(sz))
+ v.Aux = typeToAux(t.Elem())
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (StaticCall {sym} s1:(Store _ (Const32 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem))))
+ // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3)
+ // result: (Move {t.Elem()} [int64(sz)] dst src mem)
+ for {
+ sym := auxToCall(v.Aux)
+ s1 := v_0
+ if s1.Op != OpStore {
+ break
+ }
+ _ = s1.Args[2]
+ s1_1 := s1.Args[1]
+ if s1_1.Op != OpConst32 {
+ break
+ }
+ sz := auxIntToInt32(s1_1.AuxInt)
+ s2 := s1.Args[2]
+ if s2.Op != OpStore {
+ break
+ }
+ _ = s2.Args[2]
+ src := s2.Args[1]
+ s3 := s2.Args[2]
+ if s3.Op != OpStore {
+ break
+ }
+ t := auxToType(s3.Aux)
+ mem := s3.Args[2]
+ dst := s3.Args[1]
+ if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(int64(sz))
+ v.Aux = typeToAux(t.Elem())
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (StaticCall {sym} x)
+ // cond: needRaceCleanup(sym, v)
+ // result: x
+ for {
+ sym := auxToCall(v.Aux)
+ x := v_0
+ if !(needRaceCleanup(sym, v)) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpStaticLECall(v *Value) bool {
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [1]) mem)
+ // cond: isSameCall(callAux, "runtime.memequal") && symIsRO(scon)
+ // result: (MakeResult (Eq8 (Load <typ.Int8> sptr mem) (Const8 <typ.Int8> [int8(read8(scon,0))])) mem)
+ for {
+ if len(v.Args) != 4 {
+ break
+ }
+ callAux := auxToCall(v.Aux)
+ mem := v.Args[3]
+ sptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpAddr {
+ break
+ }
+ scon := auxToSym(v_1.Aux)
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpSB {
+ break
+ }
+ v_2 := v.Args[2]
+ if v_2.Op != OpConst64 || auxIntToInt64(v_2.AuxInt) != 1 || !(isSameCall(callAux, "runtime.memequal") && symIsRO(scon)) {
+ break
+ }
+ v.reset(OpMakeResult)
+ v0 := b.NewValue0(v.Pos, OpEq8, typ.Bool)
+ v1 := b.NewValue0(v.Pos, OpLoad, typ.Int8)
+ v1.AddArg2(sptr, mem)
+ v2 := b.NewValue0(v.Pos, OpConst8, typ.Int8)
+ v2.AuxInt = int8ToAuxInt(int8(read8(scon, 0)))
+ v0.AddArg2(v1, v2)
+ v.AddArg2(v0, mem)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpStore(v *Value) bool {
+ v_2 := v.Args[2]
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ fe := b.Func.fe
+ // match: (Store {t1} p1 (Load <t2> p2 mem) mem)
+ // cond: isSamePtr(p1, p2) && t2.Size() == t1.Size()
+ // result: mem
+ for {
+ t1 := auxToType(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpLoad {
+ break
+ }
+ t2 := v_1.Type
+ mem := v_1.Args[1]
+ p2 := v_1.Args[0]
+ if mem != v_2 || !(isSamePtr(p1, p2) && t2.Size() == t1.Size()) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store {t1} p1 (Load <t2> p2 oldmem) mem:(Store {t3} p3 _ oldmem))
+ // cond: isSamePtr(p1, p2) && t2.Size() == t1.Size() && disjoint(p1, t1.Size(), p3, t3.Size())
+ // result: mem
+ for {
+ t1 := auxToType(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpLoad {
+ break
+ }
+ t2 := v_1.Type
+ oldmem := v_1.Args[1]
+ p2 := v_1.Args[0]
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ p3 := mem.Args[0]
+ if oldmem != mem.Args[2] || !(isSamePtr(p1, p2) && t2.Size() == t1.Size() && disjoint(p1, t1.Size(), p3, t3.Size())) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store {t1} p1 (Load <t2> p2 oldmem) mem:(Store {t3} p3 _ (Store {t4} p4 _ oldmem)))
+ // cond: isSamePtr(p1, p2) && t2.Size() == t1.Size() && disjoint(p1, t1.Size(), p3, t3.Size()) && disjoint(p1, t1.Size(), p4, t4.Size())
+ // result: mem
+ for {
+ t1 := auxToType(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpLoad {
+ break
+ }
+ t2 := v_1.Type
+ oldmem := v_1.Args[1]
+ p2 := v_1.Args[0]
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ p3 := mem.Args[0]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_2.Aux)
+ _ = mem_2.Args[2]
+ p4 := mem_2.Args[0]
+ if oldmem != mem_2.Args[2] || !(isSamePtr(p1, p2) && t2.Size() == t1.Size() && disjoint(p1, t1.Size(), p3, t3.Size()) && disjoint(p1, t1.Size(), p4, t4.Size())) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store {t1} p1 (Load <t2> p2 oldmem) mem:(Store {t3} p3 _ (Store {t4} p4 _ (Store {t5} p5 _ oldmem))))
+ // cond: isSamePtr(p1, p2) && t2.Size() == t1.Size() && disjoint(p1, t1.Size(), p3, t3.Size()) && disjoint(p1, t1.Size(), p4, t4.Size()) && disjoint(p1, t1.Size(), p5, t5.Size())
+ // result: mem
+ for {
+ t1 := auxToType(v.Aux)
+ p1 := v_0
+ if v_1.Op != OpLoad {
+ break
+ }
+ t2 := v_1.Type
+ oldmem := v_1.Args[1]
+ p2 := v_1.Args[0]
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ p3 := mem.Args[0]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_2.Aux)
+ _ = mem_2.Args[2]
+ p4 := mem_2.Args[0]
+ mem_2_2 := mem_2.Args[2]
+ if mem_2_2.Op != OpStore {
+ break
+ }
+ t5 := auxToType(mem_2_2.Aux)
+ _ = mem_2_2.Args[2]
+ p5 := mem_2_2.Args[0]
+ if oldmem != mem_2_2.Args[2] || !(isSamePtr(p1, p2) && t2.Size() == t1.Size() && disjoint(p1, t1.Size(), p3, t3.Size()) && disjoint(p1, t1.Size(), p4, t4.Size()) && disjoint(p1, t1.Size(), p5, t5.Size())) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store {t} (OffPtr [o] p1) x mem:(Zero [n] p2 _))
+ // cond: isConstZero(x) && o >= 0 && t.Size() + o <= n && isSamePtr(p1, p2)
+ // result: mem
+ for {
+ t := auxToType(v.Aux)
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ o := auxIntToInt64(v_0.AuxInt)
+ p1 := v_0.Args[0]
+ x := v_1
+ mem := v_2
+ if mem.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(mem.AuxInt)
+ p2 := mem.Args[0]
+ if !(isConstZero(x) && o >= 0 && t.Size()+o <= n && isSamePtr(p1, p2)) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store {t1} op:(OffPtr [o1] p1) x mem:(Store {t2} p2 _ (Zero [n] p3 _)))
+ // cond: isConstZero(x) && o1 >= 0 && t1.Size() + o1 <= n && isSamePtr(p1, p3) && disjoint(op, t1.Size(), p2, t2.Size())
+ // result: mem
+ for {
+ t1 := auxToType(v.Aux)
+ op := v_0
+ if op.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op.AuxInt)
+ p1 := op.Args[0]
+ x := v_1
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ p2 := mem.Args[0]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(mem_2.AuxInt)
+ p3 := mem_2.Args[0]
+ if !(isConstZero(x) && o1 >= 0 && t1.Size()+o1 <= n && isSamePtr(p1, p3) && disjoint(op, t1.Size(), p2, t2.Size())) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store {t1} op:(OffPtr [o1] p1) x mem:(Store {t2} p2 _ (Store {t3} p3 _ (Zero [n] p4 _))))
+ // cond: isConstZero(x) && o1 >= 0 && t1.Size() + o1 <= n && isSamePtr(p1, p4) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size())
+ // result: mem
+ for {
+ t1 := auxToType(v.Aux)
+ op := v_0
+ if op.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op.AuxInt)
+ p1 := op.Args[0]
+ x := v_1
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ p2 := mem.Args[0]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_2.Aux)
+ _ = mem_2.Args[2]
+ p3 := mem_2.Args[0]
+ mem_2_2 := mem_2.Args[2]
+ if mem_2_2.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(mem_2_2.AuxInt)
+ p4 := mem_2_2.Args[0]
+ if !(isConstZero(x) && o1 >= 0 && t1.Size()+o1 <= n && isSamePtr(p1, p4) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size())) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store {t1} op:(OffPtr [o1] p1) x mem:(Store {t2} p2 _ (Store {t3} p3 _ (Store {t4} p4 _ (Zero [n] p5 _)))))
+ // cond: isConstZero(x) && o1 >= 0 && t1.Size() + o1 <= n && isSamePtr(p1, p5) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size())
+ // result: mem
+ for {
+ t1 := auxToType(v.Aux)
+ op := v_0
+ if op.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op.AuxInt)
+ p1 := op.Args[0]
+ x := v_1
+ mem := v_2
+ if mem.Op != OpStore {
+ break
+ }
+ t2 := auxToType(mem.Aux)
+ _ = mem.Args[2]
+ p2 := mem.Args[0]
+ mem_2 := mem.Args[2]
+ if mem_2.Op != OpStore {
+ break
+ }
+ t3 := auxToType(mem_2.Aux)
+ _ = mem_2.Args[2]
+ p3 := mem_2.Args[0]
+ mem_2_2 := mem_2.Args[2]
+ if mem_2_2.Op != OpStore {
+ break
+ }
+ t4 := auxToType(mem_2_2.Aux)
+ _ = mem_2_2.Args[2]
+ p4 := mem_2_2.Args[0]
+ mem_2_2_2 := mem_2_2.Args[2]
+ if mem_2_2_2.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(mem_2_2_2.AuxInt)
+ p5 := mem_2_2_2.Args[0]
+ if !(isConstZero(x) && o1 >= 0 && t1.Size()+o1 <= n && isSamePtr(p1, p5) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size())) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store _ (StructMake0) mem)
+ // result: mem
+ for {
+ if v_1.Op != OpStructMake0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store dst (StructMake1 <t> f0) mem)
+ // result: (Store {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)
+ for {
+ dst := v_0
+ if v_1.Op != OpStructMake1 {
+ break
+ }
+ t := v_1.Type
+ f0 := v_1.Args[0]
+ mem := v_2
+ v.reset(OpStore)
+ v.Aux = typeToAux(t.FieldType(0))
+ v0 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
+ v0.AuxInt = int64ToAuxInt(0)
+ v0.AddArg(dst)
+ v.AddArg3(v0, f0, mem)
+ return true
+ }
+ // match: (Store dst (StructMake2 <t> f0 f1) mem)
+ // result: (Store {t.FieldType(1)} (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) f1 (Store {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem))
+ for {
+ dst := v_0
+ if v_1.Op != OpStructMake2 {
+ break
+ }
+ t := v_1.Type
+ f1 := v_1.Args[1]
+ f0 := v_1.Args[0]
+ mem := v_2
+ v.reset(OpStore)
+ v.Aux = typeToAux(t.FieldType(1))
+ v0 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(1).PtrTo())
+ v0.AuxInt = int64ToAuxInt(t.FieldOff(1))
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t.FieldType(0))
+ v2 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
+ v2.AuxInt = int64ToAuxInt(0)
+ v2.AddArg(dst)
+ v1.AddArg3(v2, f0, mem)
+ v.AddArg3(v0, f1, v1)
+ return true
+ }
+ // match: (Store dst (StructMake3 <t> f0 f1 f2) mem)
+ // result: (Store {t.FieldType(2)} (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst) f2 (Store {t.FieldType(1)} (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) f1 (Store {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)))
+ for {
+ dst := v_0
+ if v_1.Op != OpStructMake3 {
+ break
+ }
+ t := v_1.Type
+ f2 := v_1.Args[2]
+ f0 := v_1.Args[0]
+ f1 := v_1.Args[1]
+ mem := v_2
+ v.reset(OpStore)
+ v.Aux = typeToAux(t.FieldType(2))
+ v0 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(2).PtrTo())
+ v0.AuxInt = int64ToAuxInt(t.FieldOff(2))
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t.FieldType(1))
+ v2 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(1).PtrTo())
+ v2.AuxInt = int64ToAuxInt(t.FieldOff(1))
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t.FieldType(0))
+ v4 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
+ v4.AuxInt = int64ToAuxInt(0)
+ v4.AddArg(dst)
+ v3.AddArg3(v4, f0, mem)
+ v1.AddArg3(v2, f1, v3)
+ v.AddArg3(v0, f2, v1)
+ return true
+ }
+ // match: (Store dst (StructMake4 <t> f0 f1 f2 f3) mem)
+ // result: (Store {t.FieldType(3)} (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] dst) f3 (Store {t.FieldType(2)} (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst) f2 (Store {t.FieldType(1)} (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) f1 (Store {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem))))
+ for {
+ dst := v_0
+ if v_1.Op != OpStructMake4 {
+ break
+ }
+ t := v_1.Type
+ f3 := v_1.Args[3]
+ f0 := v_1.Args[0]
+ f1 := v_1.Args[1]
+ f2 := v_1.Args[2]
+ mem := v_2
+ v.reset(OpStore)
+ v.Aux = typeToAux(t.FieldType(3))
+ v0 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(3).PtrTo())
+ v0.AuxInt = int64ToAuxInt(t.FieldOff(3))
+ v0.AddArg(dst)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t.FieldType(2))
+ v2 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(2).PtrTo())
+ v2.AuxInt = int64ToAuxInt(t.FieldOff(2))
+ v2.AddArg(dst)
+ v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v3.Aux = typeToAux(t.FieldType(1))
+ v4 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(1).PtrTo())
+ v4.AuxInt = int64ToAuxInt(t.FieldOff(1))
+ v4.AddArg(dst)
+ v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v5.Aux = typeToAux(t.FieldType(0))
+ v6 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
+ v6.AuxInt = int64ToAuxInt(0)
+ v6.AddArg(dst)
+ v5.AddArg3(v6, f0, mem)
+ v3.AddArg3(v4, f1, v5)
+ v1.AddArg3(v2, f2, v3)
+ v.AddArg3(v0, f3, v1)
+ return true
+ }
+ // match: (Store {t} dst (Load src mem) mem)
+ // cond: !fe.CanSSA(t)
+ // result: (Move {t} [t.Size()] dst src mem)
+ for {
+ t := auxToType(v.Aux)
+ dst := v_0
+ if v_1.Op != OpLoad {
+ break
+ }
+ mem := v_1.Args[1]
+ src := v_1.Args[0]
+ if mem != v_2 || !(!fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(t.Size())
+ v.Aux = typeToAux(t)
+ v.AddArg3(dst, src, mem)
+ return true
+ }
+ // match: (Store {t} dst (Load src mem) (VarDef {x} mem))
+ // cond: !fe.CanSSA(t)
+ // result: (Move {t} [t.Size()] dst src (VarDef {x} mem))
+ for {
+ t := auxToType(v.Aux)
+ dst := v_0
+ if v_1.Op != OpLoad {
+ break
+ }
+ mem := v_1.Args[1]
+ src := v_1.Args[0]
+ if v_2.Op != OpVarDef {
+ break
+ }
+ x := auxToSym(v_2.Aux)
+ if mem != v_2.Args[0] || !(!fe.CanSSA(t)) {
+ break
+ }
+ v.reset(OpMove)
+ v.AuxInt = int64ToAuxInt(t.Size())
+ v.Aux = typeToAux(t)
+ v0 := b.NewValue0(v.Pos, OpVarDef, types.TypeMem)
+ v0.Aux = symToAux(x)
+ v0.AddArg(mem)
+ v.AddArg3(dst, src, v0)
+ return true
+ }
+ // match: (Store _ (ArrayMake0) mem)
+ // result: mem
+ for {
+ if v_1.Op != OpArrayMake0 {
+ break
+ }
+ mem := v_2
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store dst (ArrayMake1 e) mem)
+ // result: (Store {e.Type} dst e mem)
+ for {
+ dst := v_0
+ if v_1.Op != OpArrayMake1 {
+ break
+ }
+ e := v_1.Args[0]
+ mem := v_2
+ v.reset(OpStore)
+ v.Aux = typeToAux(e.Type)
+ v.AddArg3(dst, e, mem)
+ return true
+ }
+ // match: (Store (Load (OffPtr [c] (SP)) mem) x mem)
+ // cond: isConstZero(x) && mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize
+ // result: mem
+ for {
+ if v_0.Op != OpLoad {
+ break
+ }
+ mem := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpOffPtr {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpSP {
+ break
+ }
+ x := v_1
+ if mem != v_2 || !(isConstZero(x) && mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store (OffPtr (Load (OffPtr [c] (SP)) mem)) x mem)
+ // cond: isConstZero(x) && mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize
+ // result: mem
+ for {
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpLoad {
+ break
+ }
+ mem := v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpOffPtr {
+ break
+ }
+ c := auxIntToInt64(v_0_0_0.AuxInt)
+ v_0_0_0_0 := v_0_0_0.Args[0]
+ if v_0_0_0_0.Op != OpSP {
+ break
+ }
+ x := v_1
+ if mem != v_2 || !(isConstZero(x) && mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store (SelectN [0] call:(StaticLECall _ _)) x mem:(SelectN [1] call))
+ // cond: isConstZero(x) && isSameCall(call.Aux, "runtime.newobject")
+ // result: mem
+ for {
+ if v_0.Op != OpSelectN || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ call := v_0.Args[0]
+ if call.Op != OpStaticLECall || len(call.Args) != 2 {
+ break
+ }
+ x := v_1
+ mem := v_2
+ if mem.Op != OpSelectN || auxIntToInt64(mem.AuxInt) != 1 || call != mem.Args[0] || !(isConstZero(x) && isSameCall(call.Aux, "runtime.newobject")) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store (OffPtr (SelectN [0] call:(StaticLECall _ _))) x mem:(SelectN [1] call))
+ // cond: isConstZero(x) && isSameCall(call.Aux, "runtime.newobject")
+ // result: mem
+ for {
+ if v_0.Op != OpOffPtr {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpSelectN || auxIntToInt64(v_0_0.AuxInt) != 0 {
+ break
+ }
+ call := v_0_0.Args[0]
+ if call.Op != OpStaticLECall || len(call.Args) != 2 {
+ break
+ }
+ x := v_1
+ mem := v_2
+ if mem.Op != OpSelectN || auxIntToInt64(mem.AuxInt) != 1 || call != mem.Args[0] || !(isConstZero(x) && isSameCall(call.Aux, "runtime.newobject")) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Store {t1} op1:(OffPtr [o1] p1) d1 m2:(Store {t2} op2:(OffPtr [0] p2) d2 m3:(Move [n] p3 _ mem)))
+ // cond: m2.Uses == 1 && m3.Uses == 1 && o1 == t2.Size() && n == t2.Size() + t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && clobber(m2, m3)
+ // result: (Store {t1} op1 d1 (Store {t2} op2 d2 mem))
+ for {
+ t1 := auxToType(v.Aux)
+ op1 := v_0
+ if op1.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op1.AuxInt)
+ p1 := op1.Args[0]
+ d1 := v_1
+ m2 := v_2
+ if m2.Op != OpStore {
+ break
+ }
+ t2 := auxToType(m2.Aux)
+ _ = m2.Args[2]
+ op2 := m2.Args[0]
+ if op2.Op != OpOffPtr || auxIntToInt64(op2.AuxInt) != 0 {
+ break
+ }
+ p2 := op2.Args[0]
+ d2 := m2.Args[1]
+ m3 := m2.Args[2]
+ if m3.Op != OpMove {
+ break
+ }
+ n := auxIntToInt64(m3.AuxInt)
+ mem := m3.Args[2]
+ p3 := m3.Args[0]
+ if !(m2.Uses == 1 && m3.Uses == 1 && o1 == t2.Size() && n == t2.Size()+t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && clobber(m2, m3)) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t1)
+ v0 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v0.Aux = typeToAux(t2)
+ v0.AddArg3(op2, d2, mem)
+ v.AddArg3(op1, d1, v0)
+ return true
+ }
+ // match: (Store {t1} op1:(OffPtr [o1] p1) d1 m2:(Store {t2} op2:(OffPtr [o2] p2) d2 m3:(Store {t3} op3:(OffPtr [0] p3) d3 m4:(Move [n] p4 _ mem))))
+ // cond: m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1 && o2 == t3.Size() && o1-o2 == t2.Size() && n == t3.Size() + t2.Size() + t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && clobber(m2, m3, m4)
+ // result: (Store {t1} op1 d1 (Store {t2} op2 d2 (Store {t3} op3 d3 mem)))
+ for {
+ t1 := auxToType(v.Aux)
+ op1 := v_0
+ if op1.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op1.AuxInt)
+ p1 := op1.Args[0]
+ d1 := v_1
+ m2 := v_2
+ if m2.Op != OpStore {
+ break
+ }
+ t2 := auxToType(m2.Aux)
+ _ = m2.Args[2]
+ op2 := m2.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d2 := m2.Args[1]
+ m3 := m2.Args[2]
+ if m3.Op != OpStore {
+ break
+ }
+ t3 := auxToType(m3.Aux)
+ _ = m3.Args[2]
+ op3 := m3.Args[0]
+ if op3.Op != OpOffPtr || auxIntToInt64(op3.AuxInt) != 0 {
+ break
+ }
+ p3 := op3.Args[0]
+ d3 := m3.Args[1]
+ m4 := m3.Args[2]
+ if m4.Op != OpMove {
+ break
+ }
+ n := auxIntToInt64(m4.AuxInt)
+ mem := m4.Args[2]
+ p4 := m4.Args[0]
+ if !(m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1 && o2 == t3.Size() && o1-o2 == t2.Size() && n == t3.Size()+t2.Size()+t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && clobber(m2, m3, m4)) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t1)
+ v0 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v0.Aux = typeToAux(t2)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v1.AddArg3(op3, d3, mem)
+ v0.AddArg3(op2, d2, v1)
+ v.AddArg3(op1, d1, v0)
+ return true
+ }
+ // match: (Store {t1} op1:(OffPtr [o1] p1) d1 m2:(Store {t2} op2:(OffPtr [o2] p2) d2 m3:(Store {t3} op3:(OffPtr [o3] p3) d3 m4:(Store {t4} op4:(OffPtr [0] p4) d4 m5:(Move [n] p5 _ mem)))))
+ // cond: m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1 && m5.Uses == 1 && o3 == t4.Size() && o2-o3 == t3.Size() && o1-o2 == t2.Size() && n == t4.Size() + t3.Size() + t2.Size() + t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && clobber(m2, m3, m4, m5)
+ // result: (Store {t1} op1 d1 (Store {t2} op2 d2 (Store {t3} op3 d3 (Store {t4} op4 d4 mem))))
+ for {
+ t1 := auxToType(v.Aux)
+ op1 := v_0
+ if op1.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op1.AuxInt)
+ p1 := op1.Args[0]
+ d1 := v_1
+ m2 := v_2
+ if m2.Op != OpStore {
+ break
+ }
+ t2 := auxToType(m2.Aux)
+ _ = m2.Args[2]
+ op2 := m2.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d2 := m2.Args[1]
+ m3 := m2.Args[2]
+ if m3.Op != OpStore {
+ break
+ }
+ t3 := auxToType(m3.Aux)
+ _ = m3.Args[2]
+ op3 := m3.Args[0]
+ if op3.Op != OpOffPtr {
+ break
+ }
+ o3 := auxIntToInt64(op3.AuxInt)
+ p3 := op3.Args[0]
+ d3 := m3.Args[1]
+ m4 := m3.Args[2]
+ if m4.Op != OpStore {
+ break
+ }
+ t4 := auxToType(m4.Aux)
+ _ = m4.Args[2]
+ op4 := m4.Args[0]
+ if op4.Op != OpOffPtr || auxIntToInt64(op4.AuxInt) != 0 {
+ break
+ }
+ p4 := op4.Args[0]
+ d4 := m4.Args[1]
+ m5 := m4.Args[2]
+ if m5.Op != OpMove {
+ break
+ }
+ n := auxIntToInt64(m5.AuxInt)
+ mem := m5.Args[2]
+ p5 := m5.Args[0]
+ if !(m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1 && m5.Uses == 1 && o3 == t4.Size() && o2-o3 == t3.Size() && o1-o2 == t2.Size() && n == t4.Size()+t3.Size()+t2.Size()+t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && clobber(m2, m3, m4, m5)) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t1)
+ v0 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v0.Aux = typeToAux(t2)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v2.Aux = typeToAux(t4)
+ v2.AddArg3(op4, d4, mem)
+ v1.AddArg3(op3, d3, v2)
+ v0.AddArg3(op2, d2, v1)
+ v.AddArg3(op1, d1, v0)
+ return true
+ }
+ // match: (Store {t1} op1:(OffPtr [o1] p1) d1 m2:(Store {t2} op2:(OffPtr [0] p2) d2 m3:(Zero [n] p3 mem)))
+ // cond: m2.Uses == 1 && m3.Uses == 1 && o1 == t2.Size() && n == t2.Size() + t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && clobber(m2, m3)
+ // result: (Store {t1} op1 d1 (Store {t2} op2 d2 mem))
+ for {
+ t1 := auxToType(v.Aux)
+ op1 := v_0
+ if op1.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op1.AuxInt)
+ p1 := op1.Args[0]
+ d1 := v_1
+ m2 := v_2
+ if m2.Op != OpStore {
+ break
+ }
+ t2 := auxToType(m2.Aux)
+ _ = m2.Args[2]
+ op2 := m2.Args[0]
+ if op2.Op != OpOffPtr || auxIntToInt64(op2.AuxInt) != 0 {
+ break
+ }
+ p2 := op2.Args[0]
+ d2 := m2.Args[1]
+ m3 := m2.Args[2]
+ if m3.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(m3.AuxInt)
+ mem := m3.Args[1]
+ p3 := m3.Args[0]
+ if !(m2.Uses == 1 && m3.Uses == 1 && o1 == t2.Size() && n == t2.Size()+t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && clobber(m2, m3)) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t1)
+ v0 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v0.Aux = typeToAux(t2)
+ v0.AddArg3(op2, d2, mem)
+ v.AddArg3(op1, d1, v0)
+ return true
+ }
+ // match: (Store {t1} op1:(OffPtr [o1] p1) d1 m2:(Store {t2} op2:(OffPtr [o2] p2) d2 m3:(Store {t3} op3:(OffPtr [0] p3) d3 m4:(Zero [n] p4 mem))))
+ // cond: m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1 && o2 == t3.Size() && o1-o2 == t2.Size() && n == t3.Size() + t2.Size() + t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && clobber(m2, m3, m4)
+ // result: (Store {t1} op1 d1 (Store {t2} op2 d2 (Store {t3} op3 d3 mem)))
+ for {
+ t1 := auxToType(v.Aux)
+ op1 := v_0
+ if op1.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op1.AuxInt)
+ p1 := op1.Args[0]
+ d1 := v_1
+ m2 := v_2
+ if m2.Op != OpStore {
+ break
+ }
+ t2 := auxToType(m2.Aux)
+ _ = m2.Args[2]
+ op2 := m2.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d2 := m2.Args[1]
+ m3 := m2.Args[2]
+ if m3.Op != OpStore {
+ break
+ }
+ t3 := auxToType(m3.Aux)
+ _ = m3.Args[2]
+ op3 := m3.Args[0]
+ if op3.Op != OpOffPtr || auxIntToInt64(op3.AuxInt) != 0 {
+ break
+ }
+ p3 := op3.Args[0]
+ d3 := m3.Args[1]
+ m4 := m3.Args[2]
+ if m4.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(m4.AuxInt)
+ mem := m4.Args[1]
+ p4 := m4.Args[0]
+ if !(m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1 && o2 == t3.Size() && o1-o2 == t2.Size() && n == t3.Size()+t2.Size()+t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && clobber(m2, m3, m4)) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t1)
+ v0 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v0.Aux = typeToAux(t2)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v1.AddArg3(op3, d3, mem)
+ v0.AddArg3(op2, d2, v1)
+ v.AddArg3(op1, d1, v0)
+ return true
+ }
+ // match: (Store {t1} op1:(OffPtr [o1] p1) d1 m2:(Store {t2} op2:(OffPtr [o2] p2) d2 m3:(Store {t3} op3:(OffPtr [o3] p3) d3 m4:(Store {t4} op4:(OffPtr [0] p4) d4 m5:(Zero [n] p5 mem)))))
+ // cond: m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1 && m5.Uses == 1 && o3 == t4.Size() && o2-o3 == t3.Size() && o1-o2 == t2.Size() && n == t4.Size() + t3.Size() + t2.Size() + t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && clobber(m2, m3, m4, m5)
+ // result: (Store {t1} op1 d1 (Store {t2} op2 d2 (Store {t3} op3 d3 (Store {t4} op4 d4 mem))))
+ for {
+ t1 := auxToType(v.Aux)
+ op1 := v_0
+ if op1.Op != OpOffPtr {
+ break
+ }
+ o1 := auxIntToInt64(op1.AuxInt)
+ p1 := op1.Args[0]
+ d1 := v_1
+ m2 := v_2
+ if m2.Op != OpStore {
+ break
+ }
+ t2 := auxToType(m2.Aux)
+ _ = m2.Args[2]
+ op2 := m2.Args[0]
+ if op2.Op != OpOffPtr {
+ break
+ }
+ o2 := auxIntToInt64(op2.AuxInt)
+ p2 := op2.Args[0]
+ d2 := m2.Args[1]
+ m3 := m2.Args[2]
+ if m3.Op != OpStore {
+ break
+ }
+ t3 := auxToType(m3.Aux)
+ _ = m3.Args[2]
+ op3 := m3.Args[0]
+ if op3.Op != OpOffPtr {
+ break
+ }
+ o3 := auxIntToInt64(op3.AuxInt)
+ p3 := op3.Args[0]
+ d3 := m3.Args[1]
+ m4 := m3.Args[2]
+ if m4.Op != OpStore {
+ break
+ }
+ t4 := auxToType(m4.Aux)
+ _ = m4.Args[2]
+ op4 := m4.Args[0]
+ if op4.Op != OpOffPtr || auxIntToInt64(op4.AuxInt) != 0 {
+ break
+ }
+ p4 := op4.Args[0]
+ d4 := m4.Args[1]
+ m5 := m4.Args[2]
+ if m5.Op != OpZero {
+ break
+ }
+ n := auxIntToInt64(m5.AuxInt)
+ mem := m5.Args[1]
+ p5 := m5.Args[0]
+ if !(m2.Uses == 1 && m3.Uses == 1 && m4.Uses == 1 && m5.Uses == 1 && o3 == t4.Size() && o2-o3 == t3.Size() && o1-o2 == t2.Size() && n == t4.Size()+t3.Size()+t2.Size()+t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && clobber(m2, m3, m4, m5)) {
+ break
+ }
+ v.reset(OpStore)
+ v.Aux = typeToAux(t1)
+ v0 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v0.Aux = typeToAux(t2)
+ v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v1.Aux = typeToAux(t3)
+ v2 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
+ v2.Aux = typeToAux(t4)
+ v2.AddArg3(op4, d4, mem)
+ v1.AddArg3(op3, d3, v2)
+ v0.AddArg3(op2, d2, v1)
+ v.AddArg3(op1, d1, v0)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpStringLen(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (StringLen (StringMake _ (Const64 <t> [c])))
+ // result: (Const64 <t> [c])
+ for {
+ if v_0.Op != OpStringMake {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpConst64 {
+ break
+ }
+ t := v_0_1.Type
+ c := auxIntToInt64(v_0_1.AuxInt)
+ v.reset(OpConst64)
+ v.Type = t
+ v.AuxInt = int64ToAuxInt(c)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpStringPtr(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (StringPtr (StringMake (Addr <t> {s} base) _))
+ // result: (Addr <t> {s} base)
+ for {
+ if v_0.Op != OpStringMake {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpAddr {
+ break
+ }
+ t := v_0_0.Type
+ s := auxToSym(v_0_0.Aux)
+ base := v_0_0.Args[0]
+ v.reset(OpAddr)
+ v.Type = t
+ v.Aux = symToAux(s)
+ v.AddArg(base)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpStructSelect(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ fe := b.Func.fe
+ // match: (StructSelect (StructMake1 x))
+ // result: x
+ for {
+ if v_0.Op != OpStructMake1 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (StructSelect [0] (StructMake2 x _))
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 || v_0.Op != OpStructMake2 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (StructSelect [1] (StructMake2 _ x))
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 || v_0.Op != OpStructMake2 {
+ break
+ }
+ x := v_0.Args[1]
+ v.copyOf(x)
+ return true
+ }
+ // match: (StructSelect [0] (StructMake3 x _ _))
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 || v_0.Op != OpStructMake3 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (StructSelect [1] (StructMake3 _ x _))
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 || v_0.Op != OpStructMake3 {
+ break
+ }
+ x := v_0.Args[1]
+ v.copyOf(x)
+ return true
+ }
+ // match: (StructSelect [2] (StructMake3 _ _ x))
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 || v_0.Op != OpStructMake3 {
+ break
+ }
+ x := v_0.Args[2]
+ v.copyOf(x)
+ return true
+ }
+ // match: (StructSelect [0] (StructMake4 x _ _ _))
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 || v_0.Op != OpStructMake4 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (StructSelect [1] (StructMake4 _ x _ _))
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 1 || v_0.Op != OpStructMake4 {
+ break
+ }
+ x := v_0.Args[1]
+ v.copyOf(x)
+ return true
+ }
+ // match: (StructSelect [2] (StructMake4 _ _ x _))
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 2 || v_0.Op != OpStructMake4 {
+ break
+ }
+ x := v_0.Args[2]
+ v.copyOf(x)
+ return true
+ }
+ // match: (StructSelect [3] (StructMake4 _ _ _ x))
+ // result: x
+ for {
+ if auxIntToInt64(v.AuxInt) != 3 || v_0.Op != OpStructMake4 {
+ break
+ }
+ x := v_0.Args[3]
+ v.copyOf(x)
+ return true
+ }
+ // match: (StructSelect [i] x:(Load <t> ptr mem))
+ // cond: !fe.CanSSA(t)
+ // result: @x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
+ for {
+ i := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if x.Op != OpLoad {
+ break
+ }
+ t := x.Type
+ mem := x.Args[1]
+ ptr := x.Args[0]
+ if !(!fe.CanSSA(t)) {
+ break
+ }
+ b = x.Block
+ v0 := b.NewValue0(v.Pos, OpLoad, v.Type)
+ v.copyOf(v0)
+ v1 := b.NewValue0(v.Pos, OpOffPtr, v.Type.PtrTo())
+ v1.AuxInt = int64ToAuxInt(t.FieldOff(int(i)))
+ v1.AddArg(ptr)
+ v0.AddArg2(v1, mem)
+ return true
+ }
+ // match: (StructSelect [0] (IData x))
+ // result: (IData x)
+ for {
+ if auxIntToInt64(v.AuxInt) != 0 || v_0.Op != OpIData {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpIData)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSub16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Sub16 (Const16 [c]) (Const16 [d]))
+ // result: (Const16 [c-d])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ break
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c - d)
+ return true
+ }
+ // match: (Sub16 x (Const16 <t> [c]))
+ // cond: x.Op != OpConst16
+ // result: (Add16 (Const16 <t> [-c]) x)
+ for {
+ x := v_0
+ if v_1.Op != OpConst16 {
+ break
+ }
+ t := v_1.Type
+ c := auxIntToInt16(v_1.AuxInt)
+ if !(x.Op != OpConst16) {
+ break
+ }
+ v.reset(OpAdd16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(-c)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Sub16 <t> (Mul16 x y) (Mul16 x z))
+ // result: (Mul16 x (Sub16 <t> y z))
+ for {
+ t := v.Type
+ if v_0.Op != OpMul16 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if v_1.Op != OpMul16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ z := v_1_1
+ v.reset(OpMul16)
+ v0 := b.NewValue0(v.Pos, OpSub16, t)
+ v0.AddArg2(y, z)
+ v.AddArg2(x, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Sub16 x x)
+ // result: (Const16 [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ // match: (Sub16 (Add16 x y) x)
+ // result: y
+ for {
+ if v_0.Op != OpAdd16 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if x != v_1 {
+ continue
+ }
+ v.copyOf(y)
+ return true
+ }
+ break
+ }
+ // match: (Sub16 (Add16 x y) y)
+ // result: x
+ for {
+ if v_0.Op != OpAdd16 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if y != v_1 {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Sub16 x (Sub16 i:(Const16 <t>) z))
+ // cond: (z.Op != OpConst16 && x.Op != OpConst16)
+ // result: (Sub16 (Add16 <t> x z) i)
+ for {
+ x := v_0
+ if v_1.Op != OpSub16 {
+ break
+ }
+ z := v_1.Args[1]
+ i := v_1.Args[0]
+ if i.Op != OpConst16 {
+ break
+ }
+ t := i.Type
+ if !(z.Op != OpConst16 && x.Op != OpConst16) {
+ break
+ }
+ v.reset(OpSub16)
+ v0 := b.NewValue0(v.Pos, OpAdd16, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(v0, i)
+ return true
+ }
+ // match: (Sub16 x (Add16 z i:(Const16 <t>)))
+ // cond: (z.Op != OpConst16 && x.Op != OpConst16)
+ // result: (Sub16 (Sub16 <t> x z) i)
+ for {
+ x := v_0
+ if v_1.Op != OpAdd16 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z := v_1_0
+ i := v_1_1
+ if i.Op != OpConst16 {
+ continue
+ }
+ t := i.Type
+ if !(z.Op != OpConst16 && x.Op != OpConst16) {
+ continue
+ }
+ v.reset(OpSub16)
+ v0 := b.NewValue0(v.Pos, OpSub16, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(v0, i)
+ return true
+ }
+ break
+ }
+ // match: (Sub16 (Sub16 i:(Const16 <t>) z) x)
+ // cond: (z.Op != OpConst16 && x.Op != OpConst16)
+ // result: (Sub16 i (Add16 <t> z x))
+ for {
+ if v_0.Op != OpSub16 {
+ break
+ }
+ z := v_0.Args[1]
+ i := v_0.Args[0]
+ if i.Op != OpConst16 {
+ break
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst16 && x.Op != OpConst16) {
+ break
+ }
+ v.reset(OpSub16)
+ v0 := b.NewValue0(v.Pos, OpAdd16, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ // match: (Sub16 (Add16 z i:(Const16 <t>)) x)
+ // cond: (z.Op != OpConst16 && x.Op != OpConst16)
+ // result: (Add16 i (Sub16 <t> z x))
+ for {
+ if v_0.Op != OpAdd16 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z := v_0_0
+ i := v_0_1
+ if i.Op != OpConst16 {
+ continue
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst16 && x.Op != OpConst16) {
+ continue
+ }
+ v.reset(OpAdd16)
+ v0 := b.NewValue0(v.Pos, OpSub16, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ break
+ }
+ // match: (Sub16 (Const16 <t> [c]) (Sub16 (Const16 <t> [d]) x))
+ // result: (Add16 (Const16 <t> [c-d]) x)
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ t := v_0.Type
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpSub16 {
+ break
+ }
+ x := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst16 || v_1_0.Type != t {
+ break
+ }
+ d := auxIntToInt16(v_1_0.AuxInt)
+ v.reset(OpAdd16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Sub16 (Const16 <t> [c]) (Add16 (Const16 <t> [d]) x))
+ // result: (Sub16 (Const16 <t> [c-d]) x)
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ t := v_0.Type
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpAdd16 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt16(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpSub16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpSub32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Sub32 (Const32 [c]) (Const32 [d]))
+ // result: (Const32 [c-d])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ break
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c - d)
+ return true
+ }
+ // match: (Sub32 x (Const32 <t> [c]))
+ // cond: x.Op != OpConst32
+ // result: (Add32 (Const32 <t> [-c]) x)
+ for {
+ x := v_0
+ if v_1.Op != OpConst32 {
+ break
+ }
+ t := v_1.Type
+ c := auxIntToInt32(v_1.AuxInt)
+ if !(x.Op != OpConst32) {
+ break
+ }
+ v.reset(OpAdd32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(-c)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Sub32 <t> (Mul32 x y) (Mul32 x z))
+ // result: (Mul32 x (Sub32 <t> y z))
+ for {
+ t := v.Type
+ if v_0.Op != OpMul32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if v_1.Op != OpMul32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ z := v_1_1
+ v.reset(OpMul32)
+ v0 := b.NewValue0(v.Pos, OpSub32, t)
+ v0.AddArg2(y, z)
+ v.AddArg2(x, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Sub32 x x)
+ // result: (Const32 [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Sub32 (Add32 x y) x)
+ // result: y
+ for {
+ if v_0.Op != OpAdd32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if x != v_1 {
+ continue
+ }
+ v.copyOf(y)
+ return true
+ }
+ break
+ }
+ // match: (Sub32 (Add32 x y) y)
+ // result: x
+ for {
+ if v_0.Op != OpAdd32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if y != v_1 {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Sub32 x (Sub32 i:(Const32 <t>) z))
+ // cond: (z.Op != OpConst32 && x.Op != OpConst32)
+ // result: (Sub32 (Add32 <t> x z) i)
+ for {
+ x := v_0
+ if v_1.Op != OpSub32 {
+ break
+ }
+ z := v_1.Args[1]
+ i := v_1.Args[0]
+ if i.Op != OpConst32 {
+ break
+ }
+ t := i.Type
+ if !(z.Op != OpConst32 && x.Op != OpConst32) {
+ break
+ }
+ v.reset(OpSub32)
+ v0 := b.NewValue0(v.Pos, OpAdd32, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(v0, i)
+ return true
+ }
+ // match: (Sub32 x (Add32 z i:(Const32 <t>)))
+ // cond: (z.Op != OpConst32 && x.Op != OpConst32)
+ // result: (Sub32 (Sub32 <t> x z) i)
+ for {
+ x := v_0
+ if v_1.Op != OpAdd32 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z := v_1_0
+ i := v_1_1
+ if i.Op != OpConst32 {
+ continue
+ }
+ t := i.Type
+ if !(z.Op != OpConst32 && x.Op != OpConst32) {
+ continue
+ }
+ v.reset(OpSub32)
+ v0 := b.NewValue0(v.Pos, OpSub32, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(v0, i)
+ return true
+ }
+ break
+ }
+ // match: (Sub32 (Sub32 i:(Const32 <t>) z) x)
+ // cond: (z.Op != OpConst32 && x.Op != OpConst32)
+ // result: (Sub32 i (Add32 <t> z x))
+ for {
+ if v_0.Op != OpSub32 {
+ break
+ }
+ z := v_0.Args[1]
+ i := v_0.Args[0]
+ if i.Op != OpConst32 {
+ break
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst32 && x.Op != OpConst32) {
+ break
+ }
+ v.reset(OpSub32)
+ v0 := b.NewValue0(v.Pos, OpAdd32, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ // match: (Sub32 (Add32 z i:(Const32 <t>)) x)
+ // cond: (z.Op != OpConst32 && x.Op != OpConst32)
+ // result: (Add32 i (Sub32 <t> z x))
+ for {
+ if v_0.Op != OpAdd32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z := v_0_0
+ i := v_0_1
+ if i.Op != OpConst32 {
+ continue
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst32 && x.Op != OpConst32) {
+ continue
+ }
+ v.reset(OpAdd32)
+ v0 := b.NewValue0(v.Pos, OpSub32, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ break
+ }
+ // match: (Sub32 (Const32 <t> [c]) (Sub32 (Const32 <t> [d]) x))
+ // result: (Add32 (Const32 <t> [c-d]) x)
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpSub32 {
+ break
+ }
+ x := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ break
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ v.reset(OpAdd32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Sub32 (Const32 <t> [c]) (Add32 (Const32 <t> [d]) x))
+ // result: (Sub32 (Const32 <t> [c-d]) x)
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpAdd32 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpSub32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpSub32F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Sub32F (Const32F [c]) (Const32F [d]))
+ // cond: c-d == c-d
+ // result: (Const32F [c-d])
+ for {
+ if v_0.Op != OpConst32F {
+ break
+ }
+ c := auxIntToFloat32(v_0.AuxInt)
+ if v_1.Op != OpConst32F {
+ break
+ }
+ d := auxIntToFloat32(v_1.AuxInt)
+ if !(c-d == c-d) {
+ break
+ }
+ v.reset(OpConst32F)
+ v.AuxInt = float32ToAuxInt(c - d)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSub64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Sub64 (Const64 [c]) (Const64 [d]))
+ // result: (Const64 [c-d])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ break
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c - d)
+ return true
+ }
+ // match: (Sub64 x (Const64 <t> [c]))
+ // cond: x.Op != OpConst64
+ // result: (Add64 (Const64 <t> [-c]) x)
+ for {
+ x := v_0
+ if v_1.Op != OpConst64 {
+ break
+ }
+ t := v_1.Type
+ c := auxIntToInt64(v_1.AuxInt)
+ if !(x.Op != OpConst64) {
+ break
+ }
+ v.reset(OpAdd64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(-c)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Sub64 <t> (Mul64 x y) (Mul64 x z))
+ // result: (Mul64 x (Sub64 <t> y z))
+ for {
+ t := v.Type
+ if v_0.Op != OpMul64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if v_1.Op != OpMul64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ z := v_1_1
+ v.reset(OpMul64)
+ v0 := b.NewValue0(v.Pos, OpSub64, t)
+ v0.AddArg2(y, z)
+ v.AddArg2(x, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Sub64 x x)
+ // result: (Const64 [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Sub64 (Add64 x y) x)
+ // result: y
+ for {
+ if v_0.Op != OpAdd64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if x != v_1 {
+ continue
+ }
+ v.copyOf(y)
+ return true
+ }
+ break
+ }
+ // match: (Sub64 (Add64 x y) y)
+ // result: x
+ for {
+ if v_0.Op != OpAdd64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if y != v_1 {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Sub64 x (Sub64 i:(Const64 <t>) z))
+ // cond: (z.Op != OpConst64 && x.Op != OpConst64)
+ // result: (Sub64 (Add64 <t> x z) i)
+ for {
+ x := v_0
+ if v_1.Op != OpSub64 {
+ break
+ }
+ z := v_1.Args[1]
+ i := v_1.Args[0]
+ if i.Op != OpConst64 {
+ break
+ }
+ t := i.Type
+ if !(z.Op != OpConst64 && x.Op != OpConst64) {
+ break
+ }
+ v.reset(OpSub64)
+ v0 := b.NewValue0(v.Pos, OpAdd64, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(v0, i)
+ return true
+ }
+ // match: (Sub64 x (Add64 z i:(Const64 <t>)))
+ // cond: (z.Op != OpConst64 && x.Op != OpConst64)
+ // result: (Sub64 (Sub64 <t> x z) i)
+ for {
+ x := v_0
+ if v_1.Op != OpAdd64 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z := v_1_0
+ i := v_1_1
+ if i.Op != OpConst64 {
+ continue
+ }
+ t := i.Type
+ if !(z.Op != OpConst64 && x.Op != OpConst64) {
+ continue
+ }
+ v.reset(OpSub64)
+ v0 := b.NewValue0(v.Pos, OpSub64, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(v0, i)
+ return true
+ }
+ break
+ }
+ // match: (Sub64 (Sub64 i:(Const64 <t>) z) x)
+ // cond: (z.Op != OpConst64 && x.Op != OpConst64)
+ // result: (Sub64 i (Add64 <t> z x))
+ for {
+ if v_0.Op != OpSub64 {
+ break
+ }
+ z := v_0.Args[1]
+ i := v_0.Args[0]
+ if i.Op != OpConst64 {
+ break
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst64 && x.Op != OpConst64) {
+ break
+ }
+ v.reset(OpSub64)
+ v0 := b.NewValue0(v.Pos, OpAdd64, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ // match: (Sub64 (Add64 z i:(Const64 <t>)) x)
+ // cond: (z.Op != OpConst64 && x.Op != OpConst64)
+ // result: (Add64 i (Sub64 <t> z x))
+ for {
+ if v_0.Op != OpAdd64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z := v_0_0
+ i := v_0_1
+ if i.Op != OpConst64 {
+ continue
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst64 && x.Op != OpConst64) {
+ continue
+ }
+ v.reset(OpAdd64)
+ v0 := b.NewValue0(v.Pos, OpSub64, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ break
+ }
+ // match: (Sub64 (Const64 <t> [c]) (Sub64 (Const64 <t> [d]) x))
+ // result: (Add64 (Const64 <t> [c-d]) x)
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpSub64 {
+ break
+ }
+ x := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ break
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ v.reset(OpAdd64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Sub64 (Const64 <t> [c]) (Add64 (Const64 <t> [d]) x))
+ // result: (Sub64 (Const64 <t> [c-d]) x)
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpAdd64 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpSub64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpSub64F(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (Sub64F (Const64F [c]) (Const64F [d]))
+ // cond: c-d == c-d
+ // result: (Const64F [c-d])
+ for {
+ if v_0.Op != OpConst64F {
+ break
+ }
+ c := auxIntToFloat64(v_0.AuxInt)
+ if v_1.Op != OpConst64F {
+ break
+ }
+ d := auxIntToFloat64(v_1.AuxInt)
+ if !(c-d == c-d) {
+ break
+ }
+ v.reset(OpConst64F)
+ v.AuxInt = float64ToAuxInt(c - d)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpSub8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Sub8 (Const8 [c]) (Const8 [d]))
+ // result: (Const8 [c-d])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ break
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c - d)
+ return true
+ }
+ // match: (Sub8 x (Const8 <t> [c]))
+ // cond: x.Op != OpConst8
+ // result: (Add8 (Const8 <t> [-c]) x)
+ for {
+ x := v_0
+ if v_1.Op != OpConst8 {
+ break
+ }
+ t := v_1.Type
+ c := auxIntToInt8(v_1.AuxInt)
+ if !(x.Op != OpConst8) {
+ break
+ }
+ v.reset(OpAdd8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(-c)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Sub8 <t> (Mul8 x y) (Mul8 x z))
+ // result: (Mul8 x (Sub8 <t> y z))
+ for {
+ t := v.Type
+ if v_0.Op != OpMul8 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if v_1.Op != OpMul8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ z := v_1_1
+ v.reset(OpMul8)
+ v0 := b.NewValue0(v.Pos, OpSub8, t)
+ v0.AddArg2(y, z)
+ v.AddArg2(x, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Sub8 x x)
+ // result: (Const8 [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ // match: (Sub8 (Add8 x y) x)
+ // result: y
+ for {
+ if v_0.Op != OpAdd8 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if x != v_1 {
+ continue
+ }
+ v.copyOf(y)
+ return true
+ }
+ break
+ }
+ // match: (Sub8 (Add8 x y) y)
+ // result: x
+ for {
+ if v_0.Op != OpAdd8 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ x := v_0_0
+ y := v_0_1
+ if y != v_1 {
+ continue
+ }
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Sub8 x (Sub8 i:(Const8 <t>) z))
+ // cond: (z.Op != OpConst8 && x.Op != OpConst8)
+ // result: (Sub8 (Add8 <t> x z) i)
+ for {
+ x := v_0
+ if v_1.Op != OpSub8 {
+ break
+ }
+ z := v_1.Args[1]
+ i := v_1.Args[0]
+ if i.Op != OpConst8 {
+ break
+ }
+ t := i.Type
+ if !(z.Op != OpConst8 && x.Op != OpConst8) {
+ break
+ }
+ v.reset(OpSub8)
+ v0 := b.NewValue0(v.Pos, OpAdd8, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(v0, i)
+ return true
+ }
+ // match: (Sub8 x (Add8 z i:(Const8 <t>)))
+ // cond: (z.Op != OpConst8 && x.Op != OpConst8)
+ // result: (Sub8 (Sub8 <t> x z) i)
+ for {
+ x := v_0
+ if v_1.Op != OpAdd8 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ z := v_1_0
+ i := v_1_1
+ if i.Op != OpConst8 {
+ continue
+ }
+ t := i.Type
+ if !(z.Op != OpConst8 && x.Op != OpConst8) {
+ continue
+ }
+ v.reset(OpSub8)
+ v0 := b.NewValue0(v.Pos, OpSub8, t)
+ v0.AddArg2(x, z)
+ v.AddArg2(v0, i)
+ return true
+ }
+ break
+ }
+ // match: (Sub8 (Sub8 i:(Const8 <t>) z) x)
+ // cond: (z.Op != OpConst8 && x.Op != OpConst8)
+ // result: (Sub8 i (Add8 <t> z x))
+ for {
+ if v_0.Op != OpSub8 {
+ break
+ }
+ z := v_0.Args[1]
+ i := v_0.Args[0]
+ if i.Op != OpConst8 {
+ break
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst8 && x.Op != OpConst8) {
+ break
+ }
+ v.reset(OpSub8)
+ v0 := b.NewValue0(v.Pos, OpAdd8, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ // match: (Sub8 (Add8 z i:(Const8 <t>)) x)
+ // cond: (z.Op != OpConst8 && x.Op != OpConst8)
+ // result: (Add8 i (Sub8 <t> z x))
+ for {
+ if v_0.Op != OpAdd8 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ z := v_0_0
+ i := v_0_1
+ if i.Op != OpConst8 {
+ continue
+ }
+ t := i.Type
+ x := v_1
+ if !(z.Op != OpConst8 && x.Op != OpConst8) {
+ continue
+ }
+ v.reset(OpAdd8)
+ v0 := b.NewValue0(v.Pos, OpSub8, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ break
+ }
+ // match: (Sub8 (Const8 <t> [c]) (Sub8 (Const8 <t> [d]) x))
+ // result: (Add8 (Const8 <t> [c-d]) x)
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ t := v_0.Type
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpSub8 {
+ break
+ }
+ x := v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpConst8 || v_1_0.Type != t {
+ break
+ }
+ d := auxIntToInt8(v_1_0.AuxInt)
+ v.reset(OpAdd8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ // match: (Sub8 (Const8 <t> [c]) (Add8 (Const8 <t> [d]) x))
+ // result: (Sub8 (Const8 <t> [c-d]) x)
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ t := v_0.Type
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpAdd8 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst8 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt8(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpSub8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c - d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpTrunc16to8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc16to8 (Const16 [c]))
+ // result: (Const8 [int8(c)])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ return true
+ }
+ // match: (Trunc16to8 (ZeroExt8to16 x))
+ // result: x
+ for {
+ if v_0.Op != OpZeroExt8to16 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc16to8 (SignExt8to16 x))
+ // result: x
+ for {
+ if v_0.Op != OpSignExt8to16 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc16to8 (And16 (Const16 [y]) x))
+ // cond: y&0xFF == 0xFF
+ // result: (Trunc16to8 x)
+ for {
+ if v_0.Op != OpAnd16 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst16 {
+ continue
+ }
+ y := auxIntToInt16(v_0_0.AuxInt)
+ x := v_0_1
+ if !(y&0xFF == 0xFF) {
+ continue
+ }
+ v.reset(OpTrunc16to8)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpTrunc32to16(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc32to16 (Const32 [c]))
+ // result: (Const16 [int16(c)])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ return true
+ }
+ // match: (Trunc32to16 (ZeroExt8to32 x))
+ // result: (ZeroExt8to16 x)
+ for {
+ if v_0.Op != OpZeroExt8to32 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpZeroExt8to16)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc32to16 (ZeroExt16to32 x))
+ // result: x
+ for {
+ if v_0.Op != OpZeroExt16to32 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc32to16 (SignExt8to32 x))
+ // result: (SignExt8to16 x)
+ for {
+ if v_0.Op != OpSignExt8to32 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpSignExt8to16)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc32to16 (SignExt16to32 x))
+ // result: x
+ for {
+ if v_0.Op != OpSignExt16to32 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc32to16 (And32 (Const32 [y]) x))
+ // cond: y&0xFFFF == 0xFFFF
+ // result: (Trunc32to16 x)
+ for {
+ if v_0.Op != OpAnd32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ y := auxIntToInt32(v_0_0.AuxInt)
+ x := v_0_1
+ if !(y&0xFFFF == 0xFFFF) {
+ continue
+ }
+ v.reset(OpTrunc32to16)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpTrunc32to8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc32to8 (Const32 [c]))
+ // result: (Const8 [int8(c)])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ return true
+ }
+ // match: (Trunc32to8 (ZeroExt8to32 x))
+ // result: x
+ for {
+ if v_0.Op != OpZeroExt8to32 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc32to8 (SignExt8to32 x))
+ // result: x
+ for {
+ if v_0.Op != OpSignExt8to32 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc32to8 (And32 (Const32 [y]) x))
+ // cond: y&0xFF == 0xFF
+ // result: (Trunc32to8 x)
+ for {
+ if v_0.Op != OpAnd32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst32 {
+ continue
+ }
+ y := auxIntToInt32(v_0_0.AuxInt)
+ x := v_0_1
+ if !(y&0xFF == 0xFF) {
+ continue
+ }
+ v.reset(OpTrunc32to8)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpTrunc64to16(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc64to16 (Const64 [c]))
+ // result: (Const16 [int16(c)])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(int16(c))
+ return true
+ }
+ // match: (Trunc64to16 (ZeroExt8to64 x))
+ // result: (ZeroExt8to16 x)
+ for {
+ if v_0.Op != OpZeroExt8to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpZeroExt8to16)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc64to16 (ZeroExt16to64 x))
+ // result: x
+ for {
+ if v_0.Op != OpZeroExt16to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc64to16 (SignExt8to64 x))
+ // result: (SignExt8to16 x)
+ for {
+ if v_0.Op != OpSignExt8to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpSignExt8to16)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc64to16 (SignExt16to64 x))
+ // result: x
+ for {
+ if v_0.Op != OpSignExt16to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc64to16 (And64 (Const64 [y]) x))
+ // cond: y&0xFFFF == 0xFFFF
+ // result: (Trunc64to16 x)
+ for {
+ if v_0.Op != OpAnd64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ y := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_1
+ if !(y&0xFFFF == 0xFFFF) {
+ continue
+ }
+ v.reset(OpTrunc64to16)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpTrunc64to32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc64to32 (Const64 [c]))
+ // result: (Const32 [int32(c)])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ return true
+ }
+ // match: (Trunc64to32 (ZeroExt8to64 x))
+ // result: (ZeroExt8to32 x)
+ for {
+ if v_0.Op != OpZeroExt8to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpZeroExt8to32)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc64to32 (ZeroExt16to64 x))
+ // result: (ZeroExt16to32 x)
+ for {
+ if v_0.Op != OpZeroExt16to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpZeroExt16to32)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc64to32 (ZeroExt32to64 x))
+ // result: x
+ for {
+ if v_0.Op != OpZeroExt32to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc64to32 (SignExt8to64 x))
+ // result: (SignExt8to32 x)
+ for {
+ if v_0.Op != OpSignExt8to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpSignExt8to32)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc64to32 (SignExt16to64 x))
+ // result: (SignExt16to32 x)
+ for {
+ if v_0.Op != OpSignExt16to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpSignExt16to32)
+ v.AddArg(x)
+ return true
+ }
+ // match: (Trunc64to32 (SignExt32to64 x))
+ // result: x
+ for {
+ if v_0.Op != OpSignExt32to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc64to32 (And64 (Const64 [y]) x))
+ // cond: y&0xFFFFFFFF == 0xFFFFFFFF
+ // result: (Trunc64to32 x)
+ for {
+ if v_0.Op != OpAnd64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ y := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_1
+ if !(y&0xFFFFFFFF == 0xFFFFFFFF) {
+ continue
+ }
+ v.reset(OpTrunc64to32)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpTrunc64to8(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Trunc64to8 (Const64 [c]))
+ // result: (Const8 [int8(c)])
+ for {
+ if v_0.Op != OpConst64 {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(int8(c))
+ return true
+ }
+ // match: (Trunc64to8 (ZeroExt8to64 x))
+ // result: x
+ for {
+ if v_0.Op != OpZeroExt8to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc64to8 (SignExt8to64 x))
+ // result: x
+ for {
+ if v_0.Op != OpSignExt8to64 {
+ break
+ }
+ x := v_0.Args[0]
+ v.copyOf(x)
+ return true
+ }
+ // match: (Trunc64to8 (And64 (Const64 [y]) x))
+ // cond: y&0xFF == 0xFF
+ // result: (Trunc64to8 x)
+ for {
+ if v_0.Op != OpAnd64 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+ if v_0_0.Op != OpConst64 {
+ continue
+ }
+ y := auxIntToInt64(v_0_0.AuxInt)
+ x := v_0_1
+ if !(y&0xFF == 0xFF) {
+ continue
+ }
+ v.reset(OpTrunc64to8)
+ v.AddArg(x)
+ return true
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpXor16(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Xor16 (Const16 [c]) (Const16 [d]))
+ // result: (Const16 [c^d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpConst16 {
+ continue
+ }
+ d := auxIntToInt16(v_1.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(c ^ d)
+ return true
+ }
+ break
+ }
+ // match: (Xor16 x x)
+ // result: (Const16 [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(0)
+ return true
+ }
+ // match: (Xor16 (Const16 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 || auxIntToInt16(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Xor16 x (Xor16 x y))
+ // result: y
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpXor16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.copyOf(y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Xor16 (Xor16 i:(Const16 <t>) z) x)
+ // cond: (z.Op != OpConst16 && x.Op != OpConst16)
+ // result: (Xor16 i (Xor16 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpXor16 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst16 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst16 && x.Op != OpConst16) {
+ continue
+ }
+ v.reset(OpXor16)
+ v0 := b.NewValue0(v.Pos, OpXor16, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Xor16 (Const16 <t> [c]) (Xor16 (Const16 <t> [d]) x))
+ // result: (Xor16 (Const16 <t> [c^d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst16 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt16(v_0.AuxInt)
+ if v_1.Op != OpXor16 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst16 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt16(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpXor16)
+ v0 := b.NewValue0(v.Pos, OpConst16, t)
+ v0.AuxInt = int16ToAuxInt(c ^ d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpXor32(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Xor32 (Const32 [c]) (Const32 [d]))
+ // result: (Const32 [c^d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpConst32 {
+ continue
+ }
+ d := auxIntToInt32(v_1.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(c ^ d)
+ return true
+ }
+ break
+ }
+ // match: (Xor32 x x)
+ // result: (Const32 [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(0)
+ return true
+ }
+ // match: (Xor32 (Const32 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Xor32 x (Xor32 x y))
+ // result: y
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpXor32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.copyOf(y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Xor32 (Xor32 i:(Const32 <t>) z) x)
+ // cond: (z.Op != OpConst32 && x.Op != OpConst32)
+ // result: (Xor32 i (Xor32 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpXor32 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst32 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst32 && x.Op != OpConst32) {
+ continue
+ }
+ v.reset(OpXor32)
+ v0 := b.NewValue0(v.Pos, OpXor32, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Xor32 (Const32 <t> [c]) (Xor32 (Const32 <t> [d]) x))
+ // result: (Xor32 (Const32 <t> [c^d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst32 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt32(v_0.AuxInt)
+ if v_1.Op != OpXor32 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst32 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt32(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpXor32)
+ v0 := b.NewValue0(v.Pos, OpConst32, t)
+ v0.AuxInt = int32ToAuxInt(c ^ d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpXor64(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Xor64 (Const64 [c]) (Const64 [d]))
+ // result: (Const64 [c^d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpConst64 {
+ continue
+ }
+ d := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(c ^ d)
+ return true
+ }
+ break
+ }
+ // match: (Xor64 x x)
+ // result: (Const64 [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(0)
+ return true
+ }
+ // match: (Xor64 (Const64 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Xor64 x (Xor64 x y))
+ // result: y
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpXor64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.copyOf(y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Xor64 (Xor64 i:(Const64 <t>) z) x)
+ // cond: (z.Op != OpConst64 && x.Op != OpConst64)
+ // result: (Xor64 i (Xor64 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpXor64 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst64 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst64 && x.Op != OpConst64) {
+ continue
+ }
+ v.reset(OpXor64)
+ v0 := b.NewValue0(v.Pos, OpXor64, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Xor64 (Const64 <t> [c]) (Xor64 (Const64 <t> [d]) x))
+ // result: (Xor64 (Const64 <t> [c^d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst64 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpXor64 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst64 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpXor64)
+ v0 := b.NewValue0(v.Pos, OpConst64, t)
+ v0.AuxInt = int64ToAuxInt(c ^ d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpXor8(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (Xor8 (Const8 [c]) (Const8 [d]))
+ // result: (Const8 [c^d])
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpConst8 {
+ continue
+ }
+ d := auxIntToInt8(v_1.AuxInt)
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(c ^ d)
+ return true
+ }
+ break
+ }
+ // match: (Xor8 x x)
+ // result: (Const8 [0])
+ for {
+ x := v_0
+ if x != v_1 {
+ break
+ }
+ v.reset(OpConst8)
+ v.AuxInt = int8ToAuxInt(0)
+ return true
+ }
+ // match: (Xor8 (Const8 [0]) x)
+ // result: x
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 || auxIntToInt8(v_0.AuxInt) != 0 {
+ continue
+ }
+ x := v_1
+ v.copyOf(x)
+ return true
+ }
+ break
+ }
+ // match: (Xor8 x (Xor8 x y))
+ // result: y
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ x := v_0
+ if v_1.Op != OpXor8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if x != v_1_0 {
+ continue
+ }
+ y := v_1_1
+ v.copyOf(y)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Xor8 (Xor8 i:(Const8 <t>) z) x)
+ // cond: (z.Op != OpConst8 && x.Op != OpConst8)
+ // result: (Xor8 i (Xor8 <t> z x))
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpXor8 {
+ continue
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 {
+ i := v_0_0
+ if i.Op != OpConst8 {
+ continue
+ }
+ t := i.Type
+ z := v_0_1
+ x := v_1
+ if !(z.Op != OpConst8 && x.Op != OpConst8) {
+ continue
+ }
+ v.reset(OpXor8)
+ v0 := b.NewValue0(v.Pos, OpXor8, t)
+ v0.AddArg2(z, x)
+ v.AddArg2(i, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Xor8 (Const8 <t> [c]) (Xor8 (Const8 <t> [d]) x))
+ // result: (Xor8 (Const8 <t> [c^d]) x)
+ for {
+ for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+ if v_0.Op != OpConst8 {
+ continue
+ }
+ t := v_0.Type
+ c := auxIntToInt8(v_0.AuxInt)
+ if v_1.Op != OpXor8 {
+ continue
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ v_1_1 := v_1.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+ if v_1_0.Op != OpConst8 || v_1_0.Type != t {
+ continue
+ }
+ d := auxIntToInt8(v_1_0.AuxInt)
+ x := v_1_1
+ v.reset(OpXor8)
+ v0 := b.NewValue0(v.Pos, OpConst8, t)
+ v0.AuxInt = int8ToAuxInt(c ^ d)
+ v.AddArg2(v0, x)
+ return true
+ }
+ }
+ break
+ }
+ return false
+}
+func rewriteValuegeneric_OpZero(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ b := v.Block
+ config := b.Func.Config
+ // match: (Zero (Load (OffPtr [c] (SP)) mem) mem)
+ // cond: mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize
+ // result: mem
+ for {
+ if v_0.Op != OpLoad {
+ break
+ }
+ mem := v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpOffPtr {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpSP || mem != v_1 || !(mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero (SelectN [0] call:(StaticLECall _ _)) mem:(SelectN [1] call))
+ // cond: isSameCall(call.Aux, "runtime.newobject")
+ // result: mem
+ for {
+ if v_0.Op != OpSelectN || auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ call := v_0.Args[0]
+ if call.Op != OpStaticLECall || len(call.Args) != 2 {
+ break
+ }
+ mem := v_1
+ if mem.Op != OpSelectN || auxIntToInt64(mem.AuxInt) != 1 || call != mem.Args[0] || !(isSameCall(call.Aux, "runtime.newobject")) {
+ break
+ }
+ v.copyOf(mem)
+ return true
+ }
+ // match: (Zero {t1} [n] p1 store:(Store {t2} (OffPtr [o2] p2) _ mem))
+ // cond: isSamePtr(p1, p2) && store.Uses == 1 && n >= o2 + t2.Size() && clobber(store)
+ // result: (Zero {t1} [n] p1 mem)
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t1 := auxToType(v.Aux)
+ p1 := v_0
+ store := v_1
+ if store.Op != OpStore {
+ break
+ }
+ t2 := auxToType(store.Aux)
+ mem := store.Args[2]
+ store_0 := store.Args[0]
+ if store_0.Op != OpOffPtr {
+ break
+ }
+ o2 := auxIntToInt64(store_0.AuxInt)
+ p2 := store_0.Args[0]
+ if !(isSamePtr(p1, p2) && store.Uses == 1 && n >= o2+t2.Size() && clobber(store)) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t1)
+ v.AddArg2(p1, mem)
+ return true
+ }
+ // match: (Zero {t} [n] dst1 move:(Move {t} [n] dst2 _ mem))
+ // cond: move.Uses == 1 && isSamePtr(dst1, dst2) && clobber(move)
+ // result: (Zero {t} [n] dst1 mem)
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst1 := v_0
+ move := v_1
+ if move.Op != OpMove || auxIntToInt64(move.AuxInt) != n || auxToType(move.Aux) != t {
+ break
+ }
+ mem := move.Args[2]
+ dst2 := move.Args[0]
+ if !(move.Uses == 1 && isSamePtr(dst1, dst2) && clobber(move)) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t)
+ v.AddArg2(dst1, mem)
+ return true
+ }
+ // match: (Zero {t} [n] dst1 vardef:(VarDef {x} move:(Move {t} [n] dst2 _ mem)))
+ // cond: move.Uses == 1 && vardef.Uses == 1 && isSamePtr(dst1, dst2) && clobber(move, vardef)
+ // result: (Zero {t} [n] dst1 (VarDef {x} mem))
+ for {
+ n := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst1 := v_0
+ vardef := v_1
+ if vardef.Op != OpVarDef {
+ break
+ }
+ x := auxToSym(vardef.Aux)
+ move := vardef.Args[0]
+ if move.Op != OpMove || auxIntToInt64(move.AuxInt) != n || auxToType(move.Aux) != t {
+ break
+ }
+ mem := move.Args[2]
+ dst2 := move.Args[0]
+ if !(move.Uses == 1 && vardef.Uses == 1 && isSamePtr(dst1, dst2) && clobber(move, vardef)) {
+ break
+ }
+ v.reset(OpZero)
+ v.AuxInt = int64ToAuxInt(n)
+ v.Aux = typeToAux(t)
+ v0 := b.NewValue0(v.Pos, OpVarDef, types.TypeMem)
+ v0.Aux = symToAux(x)
+ v0.AddArg(mem)
+ v.AddArg2(dst1, v0)
+ return true
+ }
+ // match: (Zero {t} [s] dst1 zero:(Zero {t} [s] dst2 _))
+ // cond: isSamePtr(dst1, dst2)
+ // result: zero
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst1 := v_0
+ zero := v_1
+ if zero.Op != OpZero || auxIntToInt64(zero.AuxInt) != s || auxToType(zero.Aux) != t {
+ break
+ }
+ dst2 := zero.Args[0]
+ if !(isSamePtr(dst1, dst2)) {
+ break
+ }
+ v.copyOf(zero)
+ return true
+ }
+ // match: (Zero {t} [s] dst1 vardef:(VarDef (Zero {t} [s] dst2 _)))
+ // cond: isSamePtr(dst1, dst2)
+ // result: vardef
+ for {
+ s := auxIntToInt64(v.AuxInt)
+ t := auxToType(v.Aux)
+ dst1 := v_0
+ vardef := v_1
+ if vardef.Op != OpVarDef {
+ break
+ }
+ vardef_0 := vardef.Args[0]
+ if vardef_0.Op != OpZero || auxIntToInt64(vardef_0.AuxInt) != s || auxToType(vardef_0.Aux) != t {
+ break
+ }
+ dst2 := vardef_0.Args[0]
+ if !(isSamePtr(dst1, dst2)) {
+ break
+ }
+ v.copyOf(vardef)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpZeroExt16to32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ZeroExt16to32 (Const16 [c]))
+ // result: (Const32 [int32(uint16(c))])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(uint16(c)))
+ return true
+ }
+ // match: (ZeroExt16to32 (Trunc32to16 x:(Rsh32Ux64 _ (Const64 [s]))))
+ // cond: s >= 16
+ // result: x
+ for {
+ if v_0.Op != OpTrunc32to16 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh32Ux64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 16) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpZeroExt16to64(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ZeroExt16to64 (Const16 [c]))
+ // result: (Const64 [int64(uint16(c))])
+ for {
+ if v_0.Op != OpConst16 {
+ break
+ }
+ c := auxIntToInt16(v_0.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(uint16(c)))
+ return true
+ }
+ // match: (ZeroExt16to64 (Trunc64to16 x:(Rsh64Ux64 _ (Const64 [s]))))
+ // cond: s >= 48
+ // result: x
+ for {
+ if v_0.Op != OpTrunc64to16 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh64Ux64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 48) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpZeroExt32to64(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ZeroExt32to64 (Const32 [c]))
+ // result: (Const64 [int64(uint32(c))])
+ for {
+ if v_0.Op != OpConst32 {
+ break
+ }
+ c := auxIntToInt32(v_0.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(uint32(c)))
+ return true
+ }
+ // match: (ZeroExt32to64 (Trunc64to32 x:(Rsh64Ux64 _ (Const64 [s]))))
+ // cond: s >= 32
+ // result: x
+ for {
+ if v_0.Op != OpTrunc64to32 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh64Ux64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 32) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpZeroExt8to16(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ZeroExt8to16 (Const8 [c]))
+ // result: (Const16 [int16( uint8(c))])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpConst16)
+ v.AuxInt = int16ToAuxInt(int16(uint8(c)))
+ return true
+ }
+ // match: (ZeroExt8to16 (Trunc16to8 x:(Rsh16Ux64 _ (Const64 [s]))))
+ // cond: s >= 8
+ // result: x
+ for {
+ if v_0.Op != OpTrunc16to8 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh16Ux64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 8) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpZeroExt8to32(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ZeroExt8to32 (Const8 [c]))
+ // result: (Const32 [int32( uint8(c))])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpConst32)
+ v.AuxInt = int32ToAuxInt(int32(uint8(c)))
+ return true
+ }
+ // match: (ZeroExt8to32 (Trunc32to8 x:(Rsh32Ux64 _ (Const64 [s]))))
+ // cond: s >= 24
+ // result: x
+ for {
+ if v_0.Op != OpTrunc32to8 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh32Ux64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 24) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteValuegeneric_OpZeroExt8to64(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (ZeroExt8to64 (Const8 [c]))
+ // result: (Const64 [int64( uint8(c))])
+ for {
+ if v_0.Op != OpConst8 {
+ break
+ }
+ c := auxIntToInt8(v_0.AuxInt)
+ v.reset(OpConst64)
+ v.AuxInt = int64ToAuxInt(int64(uint8(c)))
+ return true
+ }
+ // match: (ZeroExt8to64 (Trunc64to8 x:(Rsh64Ux64 _ (Const64 [s]))))
+ // cond: s >= 56
+ // result: x
+ for {
+ if v_0.Op != OpTrunc64to8 {
+ break
+ }
+ x := v_0.Args[0]
+ if x.Op != OpRsh64Ux64 {
+ break
+ }
+ _ = x.Args[1]
+ x_1 := x.Args[1]
+ if x_1.Op != OpConst64 {
+ break
+ }
+ s := auxIntToInt64(x_1.AuxInt)
+ if !(s >= 56) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
+ return false
+}
+func rewriteBlockgeneric(b *Block) bool {
+ switch b.Kind {
+ case BlockIf:
+ // match: (If (Not cond) yes no)
+ // result: (If cond no yes)
+ for b.Controls[0].Op == OpNot {
+ v_0 := b.Controls[0]
+ cond := v_0.Args[0]
+ b.resetWithControl(BlockIf, cond)
+ b.swapSuccessors()
+ return true
+ }
+ // match: (If (ConstBool [c]) yes no)
+ // cond: c
+ // result: (First yes no)
+ for b.Controls[0].Op == OpConstBool {
+ v_0 := b.Controls[0]
+ c := auxIntToBool(v_0.AuxInt)
+ if !(c) {
+ break
+ }
+ b.Reset(BlockFirst)
+ return true
+ }
+ // match: (If (ConstBool [c]) yes no)
+ // cond: !c
+ // result: (First no yes)
+ for b.Controls[0].Op == OpConstBool {
+ v_0 := b.Controls[0]
+ c := auxIntToBool(v_0.AuxInt)
+ if !(!c) {
+ break
+ }
+ b.Reset(BlockFirst)
+ b.swapSuccessors()
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go
new file mode 100644
index 0000000..8facb91
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/schedule.go
@@ -0,0 +1,503 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "container/heap"
+ "sort"
+)
+
+const (
+ ScorePhi = iota // towards top of block
+ ScoreArg
+ ScoreNilCheck
+ ScoreReadTuple
+ ScoreVarDef
+ ScoreMemory
+ ScoreReadFlags
+ ScoreDefault
+ ScoreFlags
+ ScoreControl // towards bottom of block
+)
+
+type ValHeap struct {
+ a []*Value
+ score []int8
+}
+
+func (h ValHeap) Len() int { return len(h.a) }
+func (h ValHeap) Swap(i, j int) { a := h.a; a[i], a[j] = a[j], a[i] }
+
+func (h *ValHeap) Push(x interface{}) {
+ // Push and Pop use pointer receivers because they modify the slice's length,
+ // not just its contents.
+ v := x.(*Value)
+ h.a = append(h.a, v)
+}
+func (h *ValHeap) Pop() interface{} {
+ old := h.a
+ n := len(old)
+ x := old[n-1]
+ h.a = old[0 : n-1]
+ return x
+}
+func (h ValHeap) Less(i, j int) bool {
+ x := h.a[i]
+ y := h.a[j]
+ sx := h.score[x.ID]
+ sy := h.score[y.ID]
+ if c := sx - sy; c != 0 {
+ return c > 0 // higher score comes later.
+ }
+ if x.Pos != y.Pos { // Favor in-order line stepping
+ return x.Pos.After(y.Pos)
+ }
+ if x.Op != OpPhi {
+ if c := len(x.Args) - len(y.Args); c != 0 {
+ return c < 0 // smaller args comes later
+ }
+ }
+ if c := x.Uses - y.Uses; c != 0 {
+ return c < 0 // smaller uses come later
+ }
+ // These comparisons are fairly arbitrary.
+ // The goal here is stability in the face
+ // of unrelated changes elsewhere in the compiler.
+ if c := x.AuxInt - y.AuxInt; c != 0 {
+ return c > 0
+ }
+ if cmp := x.Type.Compare(y.Type); cmp != types.CMPeq {
+ return cmp == types.CMPgt
+ }
+ return x.ID > y.ID
+}
+
+func (op Op) isLoweredGetClosurePtr() bool {
+ switch op {
+ case OpAMD64LoweredGetClosurePtr, OpPPC64LoweredGetClosurePtr, OpARMLoweredGetClosurePtr, OpARM64LoweredGetClosurePtr,
+ Op386LoweredGetClosurePtr, OpMIPS64LoweredGetClosurePtr, OpS390XLoweredGetClosurePtr, OpMIPSLoweredGetClosurePtr,
+ OpRISCV64LoweredGetClosurePtr, OpWasmLoweredGetClosurePtr:
+ return true
+ }
+ return false
+}
+
+// Schedule the Values in each Block. After this phase returns, the
+// order of b.Values matters and is the order in which those values
+// will appear in the assembly output. For now it generates a
+// reasonable valid schedule using a priority queue. TODO(khr):
+// schedule smarter.
+func schedule(f *Func) {
+ // For each value, the number of times it is used in the block
+ // by values that have not been scheduled yet.
+ uses := make([]int32, f.NumValues())
+
+ // reusable priority queue
+ priq := new(ValHeap)
+
+ // "priority" for a value
+ score := make([]int8, f.NumValues())
+
+ // scheduling order. We queue values in this list in reverse order.
+ // A constant bound allows this to be stack-allocated. 64 is
+ // enough to cover almost every schedule call.
+ order := make([]*Value, 0, 64)
+
+ // maps mem values to the next live memory value
+ nextMem := make([]*Value, f.NumValues())
+ // additional pretend arguments for each Value. Used to enforce load/store ordering.
+ additionalArgs := make([][]*Value, f.NumValues())
+
+ for _, b := range f.Blocks {
+ // Compute score. Larger numbers are scheduled closer to the end of the block.
+ for _, v := range b.Values {
+ switch {
+ case v.Op.isLoweredGetClosurePtr():
+ // We also score GetLoweredClosurePtr as early as possible to ensure that the
+ // context register is not stomped. GetLoweredClosurePtr should only appear
+ // in the entry block where there are no phi functions, so there is no
+ // conflict or ambiguity here.
+ if b != f.Entry {
+ f.Fatalf("LoweredGetClosurePtr appeared outside of entry block, b=%s", b.String())
+ }
+ score[v.ID] = ScorePhi
+ case v.Op == OpAMD64LoweredNilCheck || v.Op == OpPPC64LoweredNilCheck ||
+ v.Op == OpARMLoweredNilCheck || v.Op == OpARM64LoweredNilCheck ||
+ v.Op == Op386LoweredNilCheck || v.Op == OpMIPS64LoweredNilCheck ||
+ v.Op == OpS390XLoweredNilCheck || v.Op == OpMIPSLoweredNilCheck ||
+ v.Op == OpRISCV64LoweredNilCheck || v.Op == OpWasmLoweredNilCheck:
+ // Nil checks must come before loads from the same address.
+ score[v.ID] = ScoreNilCheck
+ case v.Op == OpPhi:
+ // We want all the phis first.
+ score[v.ID] = ScorePhi
+ case v.Op == OpVarDef:
+ // We want all the vardefs next.
+ score[v.ID] = ScoreVarDef
+ case v.Op == OpArg:
+ // We want all the args as early as possible, for better debugging.
+ score[v.ID] = ScoreArg
+ case v.Type.IsMemory():
+ // Schedule stores as early as possible. This tends to
+ // reduce register pressure. It also helps make sure
+ // VARDEF ops are scheduled before the corresponding LEA.
+ score[v.ID] = ScoreMemory
+ case v.Op == OpSelect0 || v.Op == OpSelect1:
+ // Schedule the pseudo-op of reading part of a tuple
+ // immediately after the tuple-generating op, since
+ // this value is already live. This also removes its
+ // false dependency on the other part of the tuple.
+ // Also ensures tuple is never spilled.
+ score[v.ID] = ScoreReadTuple
+ case v.Type.IsFlags() || v.Type.IsTuple() && v.Type.FieldType(1).IsFlags():
+ // Schedule flag register generation as late as possible.
+ // This makes sure that we only have one live flags
+ // value at a time.
+ score[v.ID] = ScoreFlags
+ default:
+ score[v.ID] = ScoreDefault
+ // If we're reading flags, schedule earlier to keep flag lifetime short.
+ for _, a := range v.Args {
+ if a.Type.IsFlags() {
+ score[v.ID] = ScoreReadFlags
+ }
+ }
+ }
+ }
+ }
+
+ for _, b := range f.Blocks {
+ // Find store chain for block.
+ // Store chains for different blocks overwrite each other, so
+ // the calculated store chain is good only for this block.
+ for _, v := range b.Values {
+ if v.Op != OpPhi && v.Type.IsMemory() {
+ for _, w := range v.Args {
+ if w.Type.IsMemory() {
+ nextMem[w.ID] = v
+ }
+ }
+ }
+ }
+
+ // Compute uses.
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ // If a value is used by a phi, it does not induce
+ // a scheduling edge because that use is from the
+ // previous iteration.
+ continue
+ }
+ for _, w := range v.Args {
+ if w.Block == b {
+ uses[w.ID]++
+ }
+ // Any load must come before the following store.
+ if !v.Type.IsMemory() && w.Type.IsMemory() {
+ // v is a load.
+ s := nextMem[w.ID]
+ if s == nil || s.Block != b {
+ continue
+ }
+ additionalArgs[s.ID] = append(additionalArgs[s.ID], v)
+ uses[v.ID]++
+ }
+ }
+ }
+
+ for _, c := range b.ControlValues() {
+ // Force the control values to be scheduled at the end,
+ // unless they are phi values (which must be first).
+ // OpArg also goes first -- if it is stack it register allocates
+ // to a LoadReg, if it is register it is from the beginning anyway.
+ if c.Op == OpPhi || c.Op == OpArg {
+ continue
+ }
+ score[c.ID] = ScoreControl
+
+ // Schedule values dependent on the control values at the end.
+ // This reduces the number of register spills. We don't find
+ // all values that depend on the controls, just values with a
+ // direct dependency. This is cheaper and in testing there
+ // was no difference in the number of spills.
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ for _, a := range v.Args {
+ if a == c {
+ score[v.ID] = ScoreControl
+ }
+ }
+ }
+ }
+
+ }
+
+ // To put things into a priority queue
+ // The values that should come last are least.
+ priq.score = score
+ priq.a = priq.a[:0]
+
+ // Initialize priority queue with schedulable values.
+ for _, v := range b.Values {
+ if uses[v.ID] == 0 {
+ heap.Push(priq, v)
+ }
+ }
+
+ // Schedule highest priority value, update use counts, repeat.
+ order = order[:0]
+ tuples := make(map[ID][]*Value)
+ for priq.Len() > 0 {
+ // Find highest priority schedulable value.
+ // Note that schedule is assembled backwards.
+
+ v := heap.Pop(priq).(*Value)
+
+ // Add it to the schedule.
+ // Do not emit tuple-reading ops until we're ready to emit the tuple-generating op.
+ //TODO: maybe remove ReadTuple score above, if it does not help on performance
+ switch {
+ case v.Op == OpSelect0:
+ if tuples[v.Args[0].ID] == nil {
+ tuples[v.Args[0].ID] = make([]*Value, 2)
+ }
+ tuples[v.Args[0].ID][0] = v
+ case v.Op == OpSelect1:
+ if tuples[v.Args[0].ID] == nil {
+ tuples[v.Args[0].ID] = make([]*Value, 2)
+ }
+ tuples[v.Args[0].ID][1] = v
+ case v.Type.IsTuple() && tuples[v.ID] != nil:
+ if tuples[v.ID][1] != nil {
+ order = append(order, tuples[v.ID][1])
+ }
+ if tuples[v.ID][0] != nil {
+ order = append(order, tuples[v.ID][0])
+ }
+ delete(tuples, v.ID)
+ fallthrough
+ default:
+ order = append(order, v)
+ }
+
+ // Update use counts of arguments.
+ for _, w := range v.Args {
+ if w.Block != b {
+ continue
+ }
+ uses[w.ID]--
+ if uses[w.ID] == 0 {
+ // All uses scheduled, w is now schedulable.
+ heap.Push(priq, w)
+ }
+ }
+ for _, w := range additionalArgs[v.ID] {
+ uses[w.ID]--
+ if uses[w.ID] == 0 {
+ // All uses scheduled, w is now schedulable.
+ heap.Push(priq, w)
+ }
+ }
+ }
+ if len(order) != len(b.Values) {
+ f.Fatalf("schedule does not include all values in block %s", b)
+ }
+ for i := 0; i < len(b.Values); i++ {
+ b.Values[i] = order[len(b.Values)-1-i]
+ }
+ }
+
+ f.scheduled = true
+}
+
+// storeOrder orders values with respect to stores. That is,
+// if v transitively depends on store s, v is ordered after s,
+// otherwise v is ordered before s.
+// Specifically, values are ordered like
+// store1
+// NilCheck that depends on store1
+// other values that depends on store1
+// store2
+// NilCheck that depends on store2
+// other values that depends on store2
+// ...
+// The order of non-store and non-NilCheck values are undefined
+// (not necessarily dependency order). This should be cheaper
+// than a full scheduling as done above.
+// Note that simple dependency order won't work: there is no
+// dependency between NilChecks and values like IsNonNil.
+// Auxiliary data structures are passed in as arguments, so
+// that they can be allocated in the caller and be reused.
+// This function takes care of reset them.
+func storeOrder(values []*Value, sset *sparseSet, storeNumber []int32) []*Value {
+ if len(values) == 0 {
+ return values
+ }
+
+ f := values[0].Block.Func
+
+ // find all stores
+
+ // Members of values that are store values.
+ // A constant bound allows this to be stack-allocated. 64 is
+ // enough to cover almost every storeOrder call.
+ stores := make([]*Value, 0, 64)
+ hasNilCheck := false
+ sset.clear() // sset is the set of stores that are used in other values
+ for _, v := range values {
+ if v.Type.IsMemory() {
+ stores = append(stores, v)
+ if v.Op == OpInitMem || v.Op == OpPhi {
+ continue
+ }
+ sset.add(v.MemoryArg().ID) // record that v's memory arg is used
+ }
+ if v.Op == OpNilCheck {
+ hasNilCheck = true
+ }
+ }
+ if len(stores) == 0 || !hasNilCheck && f.pass.name == "nilcheckelim" {
+ // there is no store, the order does not matter
+ return values
+ }
+
+ // find last store, which is the one that is not used by other stores
+ var last *Value
+ for _, v := range stores {
+ if !sset.contains(v.ID) {
+ if last != nil {
+ f.Fatalf("two stores live simultaneously: %v and %v", v, last)
+ }
+ last = v
+ }
+ }
+
+ // We assign a store number to each value. Store number is the
+ // index of the latest store that this value transitively depends.
+ // The i-th store in the current block gets store number 3*i. A nil
+ // check that depends on the i-th store gets store number 3*i+1.
+ // Other values that depends on the i-th store gets store number 3*i+2.
+ // Special case: 0 -- unassigned, 1 or 2 -- the latest store it depends
+ // is in the previous block (or no store at all, e.g. value is Const).
+ // First we assign the number to all stores by walking back the store chain,
+ // then assign the number to other values in DFS order.
+ count := make([]int32, 3*(len(stores)+1))
+ sset.clear() // reuse sparse set to ensure that a value is pushed to stack only once
+ for n, w := len(stores), last; n > 0; n-- {
+ storeNumber[w.ID] = int32(3 * n)
+ count[3*n]++
+ sset.add(w.ID)
+ if w.Op == OpInitMem || w.Op == OpPhi {
+ if n != 1 {
+ f.Fatalf("store order is wrong: there are stores before %v", w)
+ }
+ break
+ }
+ w = w.MemoryArg()
+ }
+ var stack []*Value
+ for _, v := range values {
+ if sset.contains(v.ID) {
+ // in sset means v is a store, or already pushed to stack, or already assigned a store number
+ continue
+ }
+ stack = append(stack, v)
+ sset.add(v.ID)
+
+ for len(stack) > 0 {
+ w := stack[len(stack)-1]
+ if storeNumber[w.ID] != 0 {
+ stack = stack[:len(stack)-1]
+ continue
+ }
+ if w.Op == OpPhi {
+ // Phi value doesn't depend on store in the current block.
+ // Do this early to avoid dependency cycle.
+ storeNumber[w.ID] = 2
+ count[2]++
+ stack = stack[:len(stack)-1]
+ continue
+ }
+
+ max := int32(0) // latest store dependency
+ argsdone := true
+ for _, a := range w.Args {
+ if a.Block != w.Block {
+ continue
+ }
+ if !sset.contains(a.ID) {
+ stack = append(stack, a)
+ sset.add(a.ID)
+ argsdone = false
+ break
+ }
+ if storeNumber[a.ID]/3 > max {
+ max = storeNumber[a.ID] / 3
+ }
+ }
+ if !argsdone {
+ continue
+ }
+
+ n := 3*max + 2
+ if w.Op == OpNilCheck {
+ n = 3*max + 1
+ }
+ storeNumber[w.ID] = n
+ count[n]++
+ stack = stack[:len(stack)-1]
+ }
+ }
+
+ // convert count to prefix sum of counts: count'[i] = sum_{j<=i} count[i]
+ for i := range count {
+ if i == 0 {
+ continue
+ }
+ count[i] += count[i-1]
+ }
+ if count[len(count)-1] != int32(len(values)) {
+ f.Fatalf("storeOrder: value is missing, total count = %d, values = %v", count[len(count)-1], values)
+ }
+
+ // place values in count-indexed bins, which are in the desired store order
+ order := make([]*Value, len(values))
+ for _, v := range values {
+ s := storeNumber[v.ID]
+ order[count[s-1]] = v
+ count[s-1]++
+ }
+
+ // Order nil checks in source order. We want the first in source order to trigger.
+ // If two are on the same line, we don't really care which happens first.
+ // See issue 18169.
+ if hasNilCheck {
+ start := -1
+ for i, v := range order {
+ if v.Op == OpNilCheck {
+ if start == -1 {
+ start = i
+ }
+ } else {
+ if start != -1 {
+ sort.Sort(bySourcePos(order[start:i]))
+ start = -1
+ }
+ }
+ }
+ if start != -1 {
+ sort.Sort(bySourcePos(order[start:]))
+ }
+ }
+
+ return order
+}
+
+type bySourcePos []*Value
+
+func (s bySourcePos) Len() int { return len(s) }
+func (s bySourcePos) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s bySourcePos) Less(i, j int) bool { return s[i].Pos.Before(s[j].Pos) }
diff --git a/src/cmd/compile/internal/ssa/schedule_test.go b/src/cmd/compile/internal/ssa/schedule_test.go
new file mode 100644
index 0000000..f7177dd
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/schedule_test.go
@@ -0,0 +1,101 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "testing"
+)
+
+func TestSchedule(t *testing.T) {
+ c := testConfig(t)
+ cases := []fun{
+ c.Fun("entry",
+ Bloc("entry",
+ Valu("mem0", OpInitMem, types.TypeMem, 0, nil),
+ Valu("ptr", OpConst64, c.config.Types.Int64, 0xABCD, nil),
+ Valu("v", OpConst64, c.config.Types.Int64, 12, nil),
+ Valu("mem1", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ptr", "v", "mem0"),
+ Valu("mem2", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ptr", "v", "mem1"),
+ Valu("mem3", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ptr", "sum", "mem2"),
+ Valu("l1", OpLoad, c.config.Types.Int64, 0, nil, "ptr", "mem1"),
+ Valu("l2", OpLoad, c.config.Types.Int64, 0, nil, "ptr", "mem2"),
+ Valu("sum", OpAdd64, c.config.Types.Int64, 0, nil, "l1", "l2"),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem3"))),
+ }
+ for _, c := range cases {
+ schedule(c.f)
+ if !isSingleLiveMem(c.f) {
+ t.Error("single-live-mem restriction not enforced by schedule for func:")
+ printFunc(c.f)
+ }
+ }
+}
+
+func isSingleLiveMem(f *Func) bool {
+ for _, b := range f.Blocks {
+ var liveMem *Value
+ for _, v := range b.Values {
+ for _, w := range v.Args {
+ if w.Type.IsMemory() {
+ if liveMem == nil {
+ liveMem = w
+ continue
+ }
+ if w != liveMem {
+ return false
+ }
+ }
+ }
+ if v.Type.IsMemory() {
+ liveMem = v
+ }
+ }
+ }
+ return true
+}
+
+func TestStoreOrder(t *testing.T) {
+ // In the function below, v2 depends on v3 and v4, v4 depends on v3, and v3 depends on store v5.
+ // storeOrder did not handle this case correctly.
+ c := testConfig(t)
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem0", OpInitMem, types.TypeMem, 0, nil),
+ Valu("a", OpAdd64, c.config.Types.Int64, 0, nil, "b", "c"), // v2
+ Valu("b", OpLoad, c.config.Types.Int64, 0, nil, "ptr", "mem1"), // v3
+ Valu("c", OpNeg64, c.config.Types.Int64, 0, nil, "b"), // v4
+ Valu("mem1", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ptr", "v", "mem0"), // v5
+ Valu("mem2", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ptr", "a", "mem1"),
+ Valu("ptr", OpConst64, c.config.Types.Int64, 0xABCD, nil),
+ Valu("v", OpConst64, c.config.Types.Int64, 12, nil),
+ Goto("exit")),
+ Bloc("exit",
+ Exit("mem2")))
+
+ CheckFunc(fun.f)
+ order := storeOrder(fun.f.Blocks[0].Values, fun.f.newSparseSet(fun.f.NumValues()), make([]int32, fun.f.NumValues()))
+
+ // check that v2, v3, v4 is sorted after v5
+ var ai, bi, ci, si int
+ for i, v := range order {
+ switch v.ID {
+ case 2:
+ ai = i
+ case 3:
+ bi = i
+ case 4:
+ ci = i
+ case 5:
+ si = i
+ }
+ }
+ if ai < si || bi < si || ci < si {
+ t.Logf("Func: %s", fun.f)
+ t.Errorf("store order is wrong: got %v, want v2 v3 v4 after v5", order)
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/shift_test.go b/src/cmd/compile/internal/ssa/shift_test.go
new file mode 100644
index 0000000..3876d8d
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/shift_test.go
@@ -0,0 +1,107 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "testing"
+)
+
+func TestShiftConstAMD64(t *testing.T) {
+ c := testConfig(t)
+ fun := makeConstShiftFunc(c, 18, OpLsh64x64, c.config.Types.UInt64)
+ checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHLQconst: 1, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
+
+ fun = makeConstShiftFunc(c, 66, OpLsh64x64, c.config.Types.UInt64)
+ checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHLQconst: 0, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
+
+ fun = makeConstShiftFunc(c, 18, OpRsh64Ux64, c.config.Types.UInt64)
+ checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHRQconst: 1, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
+
+ fun = makeConstShiftFunc(c, 66, OpRsh64Ux64, c.config.Types.UInt64)
+ checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHRQconst: 0, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
+
+ fun = makeConstShiftFunc(c, 18, OpRsh64x64, c.config.Types.Int64)
+ checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SARQconst: 1, OpAMD64CMPQconst: 0})
+
+ fun = makeConstShiftFunc(c, 66, OpRsh64x64, c.config.Types.Int64)
+ checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SARQconst: 1, OpAMD64CMPQconst: 0})
+}
+
+func makeConstShiftFunc(c *Conf, amount int64, op Op, typ *types.Type) fun {
+ ptyp := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("SP", OpSP, c.config.Types.Uintptr, 0, nil),
+ Valu("argptr", OpOffPtr, ptyp, 8, nil, "SP"),
+ Valu("resptr", OpOffPtr, ptyp, 16, nil, "SP"),
+ Valu("load", OpLoad, typ, 0, nil, "argptr", "mem"),
+ Valu("c", OpConst64, c.config.Types.UInt64, amount, nil),
+ Valu("shift", op, typ, 0, nil, "load", "c"),
+ Valu("store", OpStore, types.TypeMem, 0, c.config.Types.UInt64, "resptr", "shift", "mem"),
+ Exit("store")))
+ Compile(fun.f)
+ return fun
+}
+
+func TestShiftToExtensionAMD64(t *testing.T) {
+ c := testConfig(t)
+ // Test that eligible pairs of constant shifts are converted to extensions.
+ // For example:
+ // (uint64(x) << 32) >> 32 -> uint64(uint32(x))
+ ops := map[Op]int{
+ OpAMD64SHLQconst: 0, OpAMD64SHLLconst: 0,
+ OpAMD64SHRQconst: 0, OpAMD64SHRLconst: 0,
+ OpAMD64SARQconst: 0, OpAMD64SARLconst: 0,
+ }
+ tests := [...]struct {
+ amount int64
+ left, right Op
+ typ *types.Type
+ }{
+ // unsigned
+ {56, OpLsh64x64, OpRsh64Ux64, c.config.Types.UInt64},
+ {48, OpLsh64x64, OpRsh64Ux64, c.config.Types.UInt64},
+ {32, OpLsh64x64, OpRsh64Ux64, c.config.Types.UInt64},
+ {24, OpLsh32x64, OpRsh32Ux64, c.config.Types.UInt32},
+ {16, OpLsh32x64, OpRsh32Ux64, c.config.Types.UInt32},
+ {8, OpLsh16x64, OpRsh16Ux64, c.config.Types.UInt16},
+ // signed
+ {56, OpLsh64x64, OpRsh64x64, c.config.Types.Int64},
+ {48, OpLsh64x64, OpRsh64x64, c.config.Types.Int64},
+ {32, OpLsh64x64, OpRsh64x64, c.config.Types.Int64},
+ {24, OpLsh32x64, OpRsh32x64, c.config.Types.Int32},
+ {16, OpLsh32x64, OpRsh32x64, c.config.Types.Int32},
+ {8, OpLsh16x64, OpRsh16x64, c.config.Types.Int16},
+ }
+ for _, tc := range tests {
+ fun := makeShiftExtensionFunc(c, tc.amount, tc.left, tc.right, tc.typ)
+ checkOpcodeCounts(t, fun.f, ops)
+ }
+}
+
+// makeShiftExtensionFunc generates a function containing:
+//
+// (rshift (lshift (Const64 [amount])) (Const64 [amount]))
+//
+// This may be equivalent to a sign or zero extension.
+func makeShiftExtensionFunc(c *Conf, amount int64, lshift, rshift Op, typ *types.Type) fun {
+ ptyp := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("SP", OpSP, c.config.Types.Uintptr, 0, nil),
+ Valu("argptr", OpOffPtr, ptyp, 8, nil, "SP"),
+ Valu("resptr", OpOffPtr, ptyp, 16, nil, "SP"),
+ Valu("load", OpLoad, typ, 0, nil, "argptr", "mem"),
+ Valu("c", OpConst64, c.config.Types.UInt64, amount, nil),
+ Valu("lshift", lshift, typ, 0, nil, "load", "c"),
+ Valu("rshift", rshift, typ, 0, nil, "lshift", "c"),
+ Valu("store", OpStore, types.TypeMem, 0, c.config.Types.UInt64, "resptr", "rshift", "mem"),
+ Exit("store")))
+ Compile(fun.f)
+ return fun
+}
diff --git a/src/cmd/compile/internal/ssa/shortcircuit.go b/src/cmd/compile/internal/ssa/shortcircuit.go
new file mode 100644
index 0000000..4dd86ec
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/shortcircuit.go
@@ -0,0 +1,510 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// Shortcircuit finds situations where branch directions
+// are always correlated and rewrites the CFG to take
+// advantage of that fact.
+// This optimization is useful for compiling && and || expressions.
+func shortcircuit(f *Func) {
+ // Step 1: Replace a phi arg with a constant if that arg
+ // is the control value of a preceding If block.
+ // b1:
+ // If a goto b2 else b3
+ // b2: <- b1 ...
+ // x = phi(a, ...)
+ //
+ // We can replace the "a" in the phi with the constant true.
+ var ct, cf *Value
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ continue
+ }
+ if !v.Type.IsBoolean() {
+ continue
+ }
+ for i, a := range v.Args {
+ e := b.Preds[i]
+ p := e.b
+ if p.Kind != BlockIf {
+ continue
+ }
+ if p.Controls[0] != a {
+ continue
+ }
+ if e.i == 0 {
+ if ct == nil {
+ ct = f.ConstBool(f.Config.Types.Bool, true)
+ }
+ v.SetArg(i, ct)
+ } else {
+ if cf == nil {
+ cf = f.ConstBool(f.Config.Types.Bool, false)
+ }
+ v.SetArg(i, cf)
+ }
+ }
+ }
+ }
+
+ // Step 2: Redirect control flow around known branches.
+ // p:
+ // ... goto b ...
+ // b: <- p ...
+ // v = phi(true, ...)
+ // if v goto t else u
+ // We can redirect p to go directly to t instead of b.
+ // (If v is not live after b).
+ fuse(f, fuseTypePlain|fuseTypeShortCircuit)
+}
+
+// shortcircuitBlock checks for a CFG in which an If block
+// has as its control value a Phi that has a ConstBool arg.
+// In some such cases, we can rewrite the CFG into a flatter form.
+//
+// (1) Look for a CFG of the form
+//
+// p other pred(s)
+// \ /
+// b
+// / \
+// t other succ
+//
+// in which b is an If block containing a single phi value with a single use (b's Control),
+// which has a ConstBool arg.
+// p is the predecessor corresponding to the argument slot in which the ConstBool is found.
+// t is the successor corresponding to the value of the ConstBool arg.
+//
+// Rewrite this into
+//
+// p other pred(s)
+// | /
+// | b
+// |/ \
+// t u
+//
+// and remove the appropriate phi arg(s).
+//
+// (2) Look for a CFG of the form
+//
+// p q
+// \ /
+// b
+// / \
+// t u
+//
+// in which b is as described in (1).
+// However, b may also contain other phi values.
+// The CFG will be modified as described in (1).
+// However, in order to handle those other phi values,
+// for each other phi value w, we must be able to eliminate w from b.
+// We can do that though a combination of moving w to a different block
+// and rewriting uses of w to use a different value instead.
+// See shortcircuitPhiPlan for details.
+func shortcircuitBlock(b *Block) bool {
+ if b.Kind != BlockIf {
+ return false
+ }
+ // Look for control values of the form Copy(Not(Copy(Phi(const, ...)))).
+ // Those must be the only values in the b, and they each must be used only by b.
+ // Track the negations so that we can swap successors as needed later.
+ ctl := b.Controls[0]
+ nval := 1 // the control value
+ var swap int64
+ for ctl.Uses == 1 && ctl.Block == b && (ctl.Op == OpCopy || ctl.Op == OpNot) {
+ if ctl.Op == OpNot {
+ swap = 1 ^ swap
+ }
+ ctl = ctl.Args[0]
+ nval++ // wrapper around control value
+ }
+ if ctl.Op != OpPhi || ctl.Block != b || ctl.Uses != 1 {
+ return false
+ }
+ nOtherPhi := 0
+ for _, w := range b.Values {
+ if w.Op == OpPhi && w != ctl {
+ nOtherPhi++
+ }
+ }
+ if nOtherPhi > 0 && len(b.Preds) != 2 {
+ // We rely on b having exactly two preds in shortcircuitPhiPlan
+ // to reason about the values of phis.
+ return false
+ }
+ if len(b.Values) != nval+nOtherPhi {
+ return false
+ }
+ if nOtherPhi > 0 {
+ // Check for any phi which is the argument of another phi.
+ // These cases are tricky, as substitutions done by replaceUses
+ // are no longer trivial to do in any ordering. See issue 45175.
+ m := make(map[*Value]bool, 1+nOtherPhi)
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ m[v] = true
+ }
+ }
+ for v := range m {
+ for _, a := range v.Args {
+ if a != v && m[a] {
+ return false
+ }
+ }
+ }
+ }
+
+ // Locate index of first const phi arg.
+ cidx := -1
+ for i, a := range ctl.Args {
+ if a.Op == OpConstBool {
+ cidx = i
+ break
+ }
+ }
+ if cidx == -1 {
+ return false
+ }
+
+ // p is the predecessor corresponding to cidx.
+ pe := b.Preds[cidx]
+ p := pe.b
+ pi := pe.i
+
+ // t is the "taken" branch: the successor we always go to when coming in from p.
+ ti := 1 ^ ctl.Args[cidx].AuxInt ^ swap
+ te := b.Succs[ti]
+ t := te.b
+ if p == b || t == b {
+ // This is an infinite loop; we can't remove it. See issue 33903.
+ return false
+ }
+
+ var fixPhi func(*Value, int)
+ if nOtherPhi > 0 {
+ fixPhi = shortcircuitPhiPlan(b, ctl, cidx, ti)
+ if fixPhi == nil {
+ return false
+ }
+ }
+
+ // We're committed. Update CFG and Phis.
+ // If you modify this section, update shortcircuitPhiPlan corresponding.
+
+ // Remove b's incoming edge from p.
+ b.removePred(cidx)
+ n := len(b.Preds)
+ ctl.Args[cidx].Uses--
+ ctl.Args[cidx] = ctl.Args[n]
+ ctl.Args[n] = nil
+ ctl.Args = ctl.Args[:n]
+
+ // Redirect p's outgoing edge to t.
+ p.Succs[pi] = Edge{t, len(t.Preds)}
+
+ // Fix up t to have one more predecessor.
+ t.Preds = append(t.Preds, Edge{p, pi})
+ for _, v := range t.Values {
+ if v.Op != OpPhi {
+ continue
+ }
+ v.AddArg(v.Args[te.i])
+ }
+
+ if nOtherPhi != 0 {
+ // Adjust all other phis as necessary.
+ // Use a plain for loop instead of range because fixPhi may move phis,
+ // thus modifying b.Values.
+ for i := 0; i < len(b.Values); i++ {
+ phi := b.Values[i]
+ if phi.Uses == 0 || phi == ctl || phi.Op != OpPhi {
+ continue
+ }
+ fixPhi(phi, i)
+ if phi.Block == b {
+ continue
+ }
+ // phi got moved to a different block with v.moveTo.
+ // Adjust phi values in this new block that refer
+ // to phi to refer to the corresponding phi arg instead.
+ // phi used to be evaluated prior to this block,
+ // and now it is evaluated in this block.
+ for _, v := range phi.Block.Values {
+ if v.Op != OpPhi || v == phi {
+ continue
+ }
+ for j, a := range v.Args {
+ if a == phi {
+ v.SetArg(j, phi.Args[j])
+ }
+ }
+ }
+ if phi.Uses != 0 {
+ phielimValue(phi)
+ } else {
+ phi.reset(OpInvalid)
+ }
+ i-- // v.moveTo put a new value at index i; reprocess
+ }
+
+ // We may have left behind some phi values with no uses
+ // but the wrong number of arguments. Eliminate those.
+ for _, v := range b.Values {
+ if v.Uses == 0 {
+ v.reset(OpInvalid)
+ }
+ }
+ }
+
+ if len(b.Preds) == 0 {
+ // Block is now dead.
+ b.Kind = BlockInvalid
+ }
+
+ phielimValue(ctl)
+ return true
+}
+
+// shortcircuitPhiPlan returns a function to handle non-ctl phi values in b,
+// where b is as described in shortcircuitBlock.
+// The returned function accepts a value v
+// and the index i of v in v.Block: v.Block.Values[i] == v.
+// If the returned function moves v to a different block, it will use v.moveTo.
+// cidx is the index in ctl of the ConstBool arg.
+// ti is the index in b.Succs of the always taken branch when arriving from p.
+// If shortcircuitPhiPlan returns nil, there is no plan available,
+// and the CFG modifications must not proceed.
+// The returned function assumes that shortcircuitBlock has completed its CFG modifications.
+func shortcircuitPhiPlan(b *Block, ctl *Value, cidx int, ti int64) func(*Value, int) {
+ // t is the "taken" branch: the successor we always go to when coming in from p.
+ t := b.Succs[ti].b
+ // u is the "untaken" branch: the successor we never go to when coming in from p.
+ u := b.Succs[1^ti].b
+
+ // Look for some common CFG structures
+ // in which the outbound paths from b merge,
+ // with no other preds joining them.
+ // In these cases, we can reconstruct what the value
+ // of any phi in b must be in the successor blocks.
+
+ if len(t.Preds) == 1 && len(t.Succs) == 1 &&
+ len(u.Preds) == 1 && len(u.Succs) == 1 &&
+ t.Succs[0].b == u.Succs[0].b && len(t.Succs[0].b.Preds) == 2 {
+ // p q
+ // \ /
+ // b
+ // / \
+ // t u
+ // \ /
+ // m
+ //
+ // After the CFG modifications, this will look like
+ //
+ // p q
+ // | /
+ // | b
+ // |/ \
+ // t u
+ // \ /
+ // m
+ //
+ // NB: t.Preds is (b, p), not (p, b).
+ m := t.Succs[0].b
+ return func(v *Value, i int) {
+ // Replace any uses of v in t and u with the value v must have,
+ // given that we have arrived at that block.
+ // Then move v to m and adjust its value accordingly;
+ // this handles all other uses of v.
+ argP, argQ := v.Args[cidx], v.Args[1^cidx]
+ u.replaceUses(v, argQ)
+ phi := t.Func.newValue(OpPhi, v.Type, t, v.Pos)
+ phi.AddArg2(argQ, argP)
+ t.replaceUses(v, phi)
+ if v.Uses == 0 {
+ return
+ }
+ v.moveTo(m, i)
+ // The phi in m belongs to whichever pred idx corresponds to t.
+ if m.Preds[0].b == t {
+ v.SetArgs2(phi, argQ)
+ } else {
+ v.SetArgs2(argQ, phi)
+ }
+ }
+ }
+
+ if len(t.Preds) == 2 && len(u.Preds) == 1 && len(u.Succs) == 1 && u.Succs[0].b == t {
+ // p q
+ // \ /
+ // b
+ // |\
+ // | u
+ // |/
+ // t
+ //
+ // After the CFG modifications, this will look like
+ //
+ // q
+ // /
+ // b
+ // |\
+ // p | u
+ // \|/
+ // t
+ //
+ // NB: t.Preds is (b or u, b or u, p).
+ return func(v *Value, i int) {
+ // Replace any uses of v in u. Then move v to t.
+ argP, argQ := v.Args[cidx], v.Args[1^cidx]
+ u.replaceUses(v, argQ)
+ v.moveTo(t, i)
+ v.SetArgs3(argQ, argQ, argP)
+ }
+ }
+
+ if len(u.Preds) == 2 && len(t.Preds) == 1 && len(t.Succs) == 1 && t.Succs[0].b == u {
+ // p q
+ // \ /
+ // b
+ // /|
+ // t |
+ // \|
+ // u
+ //
+ // After the CFG modifications, this will look like
+ //
+ // p q
+ // | /
+ // | b
+ // |/|
+ // t |
+ // \|
+ // u
+ //
+ // NB: t.Preds is (b, p), not (p, b).
+ return func(v *Value, i int) {
+ // Replace any uses of v in t. Then move v to u.
+ argP, argQ := v.Args[cidx], v.Args[1^cidx]
+ phi := t.Func.newValue(OpPhi, v.Type, t, v.Pos)
+ phi.AddArg2(argQ, argP)
+ t.replaceUses(v, phi)
+ if v.Uses == 0 {
+ return
+ }
+ v.moveTo(u, i)
+ v.SetArgs2(argQ, phi)
+ }
+ }
+
+ // Look for some common CFG structures
+ // in which one outbound path from b exits,
+ // with no other preds joining.
+ // In these cases, we can reconstruct what the value
+ // of any phi in b must be in the path leading to exit,
+ // and move the phi to the non-exit path.
+
+ if len(t.Preds) == 1 && len(u.Preds) == 1 && len(t.Succs) == 0 {
+ // p q
+ // \ /
+ // b
+ // / \
+ // t u
+ //
+ // where t is an Exit/Ret block.
+ //
+ // After the CFG modifications, this will look like
+ //
+ // p q
+ // | /
+ // | b
+ // |/ \
+ // t u
+ //
+ // NB: t.Preds is (b, p), not (p, b).
+ return func(v *Value, i int) {
+ // Replace any uses of v in t and x. Then move v to u.
+ argP, argQ := v.Args[cidx], v.Args[1^cidx]
+ // If there are no uses of v in t or x, this phi will be unused.
+ // That's OK; it's not worth the cost to prevent that.
+ phi := t.Func.newValue(OpPhi, v.Type, t, v.Pos)
+ phi.AddArg2(argQ, argP)
+ t.replaceUses(v, phi)
+ if v.Uses == 0 {
+ return
+ }
+ v.moveTo(u, i)
+ v.SetArgs1(argQ)
+ }
+ }
+
+ if len(u.Preds) == 1 && len(t.Preds) == 1 && len(u.Succs) == 0 {
+ // p q
+ // \ /
+ // b
+ // / \
+ // t u
+ //
+ // where u is an Exit/Ret block.
+ //
+ // After the CFG modifications, this will look like
+ //
+ // p q
+ // | /
+ // | b
+ // |/ \
+ // t u
+ //
+ // NB: t.Preds is (b, p), not (p, b).
+ return func(v *Value, i int) {
+ // Replace any uses of v in u (and x). Then move v to t.
+ argP, argQ := v.Args[cidx], v.Args[1^cidx]
+ u.replaceUses(v, argQ)
+ v.moveTo(t, i)
+ v.SetArgs2(argQ, argP)
+ }
+ }
+
+ // TODO: handle more cases; shortcircuit optimizations turn out to be reasonably high impact
+ return nil
+}
+
+// replaceUses replaces all uses of old in b with new.
+func (b *Block) replaceUses(old, new *Value) {
+ for _, v := range b.Values {
+ for i, a := range v.Args {
+ if a == old {
+ v.SetArg(i, new)
+ }
+ }
+ }
+ for i, v := range b.ControlValues() {
+ if v == old {
+ b.ReplaceControl(i, new)
+ }
+ }
+}
+
+// moveTo moves v to dst, adjusting the appropriate Block.Values slices.
+// The caller is responsible for ensuring that this is safe.
+// i is the index of v in v.Block.Values.
+func (v *Value) moveTo(dst *Block, i int) {
+ if dst.Func.scheduled {
+ v.Fatalf("moveTo after scheduling")
+ }
+ src := v.Block
+ if src.Values[i] != v {
+ v.Fatalf("moveTo bad index %d", v, i)
+ }
+ if src == dst {
+ return
+ }
+ v.Block = dst
+ dst.Values = append(dst.Values, v)
+ last := len(src.Values) - 1
+ src.Values[i] = src.Values[last]
+ src.Values[last] = nil
+ src.Values = src.Values[:last]
+}
diff --git a/src/cmd/compile/internal/ssa/shortcircuit_test.go b/src/cmd/compile/internal/ssa/shortcircuit_test.go
new file mode 100644
index 0000000..b25eeb4
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/shortcircuit_test.go
@@ -0,0 +1,53 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "testing"
+)
+
+func TestShortCircuit(t *testing.T) {
+ c := testConfig(t)
+
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, types.TypeMem, 0, nil),
+ Valu("arg1", OpArg, c.config.Types.Int64, 0, nil),
+ Valu("arg2", OpArg, c.config.Types.Int64, 0, nil),
+ Valu("arg3", OpArg, c.config.Types.Int64, 0, nil),
+ Goto("b1")),
+ Bloc("b1",
+ Valu("cmp1", OpLess64, c.config.Types.Bool, 0, nil, "arg1", "arg2"),
+ If("cmp1", "b2", "b3")),
+ Bloc("b2",
+ Valu("cmp2", OpLess64, c.config.Types.Bool, 0, nil, "arg2", "arg3"),
+ Goto("b3")),
+ Bloc("b3",
+ Valu("phi2", OpPhi, c.config.Types.Bool, 0, nil, "cmp1", "cmp2"),
+ If("phi2", "b4", "b5")),
+ Bloc("b4",
+ Valu("cmp3", OpLess64, c.config.Types.Bool, 0, nil, "arg3", "arg1"),
+ Goto("b5")),
+ Bloc("b5",
+ Valu("phi3", OpPhi, c.config.Types.Bool, 0, nil, "phi2", "cmp3"),
+ If("phi3", "b6", "b7")),
+ Bloc("b6",
+ Exit("mem")),
+ Bloc("b7",
+ Exit("mem")))
+
+ CheckFunc(fun.f)
+ shortcircuit(fun.f)
+ CheckFunc(fun.f)
+
+ for _, b := range fun.f.Blocks {
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ t.Errorf("phi %s remains", v)
+ }
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/sizeof_test.go b/src/cmd/compile/internal/ssa/sizeof_test.go
new file mode 100644
index 0000000..60ada01
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/sizeof_test.go
@@ -0,0 +1,39 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "reflect"
+ "testing"
+ "unsafe"
+)
+
+// Assert that the size of important structures do not change unexpectedly.
+
+func TestSizeof(t *testing.T) {
+ const _64bit = unsafe.Sizeof(uintptr(0)) == 8
+
+ var tests = []struct {
+ val interface{} // type as a value
+ _32bit uintptr // size on 32bit platforms
+ _64bit uintptr // size on 64bit platforms
+ }{
+ {Value{}, 72, 112},
+ {Block{}, 164, 304},
+ {LocalSlot{}, 32, 48},
+ {valState{}, 28, 40},
+ }
+
+ for _, tt := range tests {
+ want := tt._32bit
+ if _64bit {
+ want = tt._64bit
+ }
+ got := reflect.TypeOf(tt.val).Size()
+ if want != got {
+ t.Errorf("unsafe.Sizeof(%T) = %d, want %d", tt.val, got, want)
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/softfloat.go b/src/cmd/compile/internal/ssa/softfloat.go
new file mode 100644
index 0000000..a8a8f83
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/softfloat.go
@@ -0,0 +1,79 @@
+// Copyright 2017 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 (
+ "cmd/compile/internal/types"
+ "math"
+)
+
+func softfloat(f *Func) {
+ if !f.Config.SoftFloat {
+ return
+ }
+ newInt64 := false
+
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Type.IsFloat() {
+ f.unCache(v)
+ switch v.Op {
+ case OpPhi, OpLoad, OpArg:
+ if v.Type.Size() == 4 {
+ v.Type = f.Config.Types.UInt32
+ } else {
+ v.Type = f.Config.Types.UInt64
+ }
+ case OpConst32F:
+ v.Op = OpConst32
+ v.Type = f.Config.Types.UInt32
+ v.AuxInt = int64(int32(math.Float32bits(auxTo32F(v.AuxInt))))
+ case OpConst64F:
+ v.Op = OpConst64
+ v.Type = f.Config.Types.UInt64
+ case OpNeg32F:
+ arg0 := v.Args[0]
+ v.reset(OpXor32)
+ v.Type = f.Config.Types.UInt32
+ v.AddArg(arg0)
+ mask := v.Block.NewValue0(v.Pos, OpConst32, v.Type)
+ mask.AuxInt = -0x80000000
+ v.AddArg(mask)
+ case OpNeg64F:
+ arg0 := v.Args[0]
+ v.reset(OpXor64)
+ v.Type = f.Config.Types.UInt64
+ v.AddArg(arg0)
+ mask := v.Block.NewValue0(v.Pos, OpConst64, v.Type)
+ mask.AuxInt = -0x8000000000000000
+ v.AddArg(mask)
+ case OpRound32F:
+ v.Op = OpCopy
+ v.Type = f.Config.Types.UInt32
+ case OpRound64F:
+ v.Op = OpCopy
+ v.Type = f.Config.Types.UInt64
+ }
+ newInt64 = newInt64 || v.Type.Size() == 8
+ } else if (v.Op == OpStore || v.Op == OpZero || v.Op == OpMove) && v.Aux.(*types.Type).IsFloat() {
+ switch size := v.Aux.(*types.Type).Size(); size {
+ case 4:
+ v.Aux = f.Config.Types.UInt32
+ case 8:
+ v.Aux = f.Config.Types.UInt64
+ default:
+ v.Fatalf("bad float type with size %d", size)
+ }
+ }
+ }
+ }
+
+ if newInt64 && f.Config.RegSize == 4 {
+ // On 32bit arch, decompose Uint64 introduced in the switch above.
+ decomposeBuiltIn(f)
+ applyRewrite(f, rewriteBlockdec64, rewriteValuedec64, removeDeadValues)
+ }
+
+}
diff --git a/src/cmd/compile/internal/ssa/sparsemap.go b/src/cmd/compile/internal/ssa/sparsemap.go
new file mode 100644
index 0000000..f55db54
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/sparsemap.go
@@ -0,0 +1,93 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import "cmd/internal/src"
+
+// from https://research.swtch.com/sparse
+// in turn, from Briggs and Torczon
+
+type sparseEntry struct {
+ key ID
+ val int32
+ aux src.XPos
+}
+
+type sparseMap struct {
+ dense []sparseEntry
+ sparse []int32
+}
+
+// newSparseMap returns a sparseMap that can map
+// integers between 0 and n-1 to int32s.
+func newSparseMap(n int) *sparseMap {
+ return &sparseMap{dense: nil, sparse: make([]int32, n)}
+}
+
+func (s *sparseMap) cap() int {
+ return len(s.sparse)
+}
+
+func (s *sparseMap) size() int {
+ return len(s.dense)
+}
+
+func (s *sparseMap) contains(k ID) bool {
+ i := s.sparse[k]
+ return i < int32(len(s.dense)) && s.dense[i].key == k
+}
+
+// get returns the value for key k, or -1 if k does
+// not appear in the map.
+func (s *sparseMap) get(k ID) int32 {
+ i := s.sparse[k]
+ if i < int32(len(s.dense)) && s.dense[i].key == k {
+ return s.dense[i].val
+ }
+ return -1
+}
+
+func (s *sparseMap) set(k ID, v int32, a src.XPos) {
+ i := s.sparse[k]
+ if i < int32(len(s.dense)) && s.dense[i].key == k {
+ s.dense[i].val = v
+ s.dense[i].aux = a
+ return
+ }
+ s.dense = append(s.dense, sparseEntry{k, v, a})
+ s.sparse[k] = int32(len(s.dense)) - 1
+}
+
+// setBit sets the v'th bit of k's value, where 0 <= v < 32
+func (s *sparseMap) setBit(k ID, v uint) {
+ if v >= 32 {
+ panic("bit index too large.")
+ }
+ i := s.sparse[k]
+ if i < int32(len(s.dense)) && s.dense[i].key == k {
+ s.dense[i].val |= 1 << v
+ return
+ }
+ s.dense = append(s.dense, sparseEntry{k, 1 << v, src.NoXPos})
+ s.sparse[k] = int32(len(s.dense)) - 1
+}
+
+func (s *sparseMap) remove(k ID) {
+ i := s.sparse[k]
+ if i < int32(len(s.dense)) && s.dense[i].key == k {
+ y := s.dense[len(s.dense)-1]
+ s.dense[i] = y
+ s.sparse[y.key] = i
+ s.dense = s.dense[:len(s.dense)-1]
+ }
+}
+
+func (s *sparseMap) clear() {
+ s.dense = s.dense[:0]
+}
+
+func (s *sparseMap) contents() []sparseEntry {
+ return s.dense
+}
diff --git a/src/cmd/compile/internal/ssa/sparseset.go b/src/cmd/compile/internal/ssa/sparseset.go
new file mode 100644
index 0000000..395931d
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/sparseset.go
@@ -0,0 +1,79 @@
+// 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
+
+// from https://research.swtch.com/sparse
+// in turn, from Briggs and Torczon
+
+type sparseSet struct {
+ dense []ID
+ sparse []int32
+}
+
+// newSparseSet returns a sparseSet that can represent
+// integers between 0 and n-1
+func newSparseSet(n int) *sparseSet {
+ return &sparseSet{dense: nil, sparse: make([]int32, n)}
+}
+
+func (s *sparseSet) cap() int {
+ return len(s.sparse)
+}
+
+func (s *sparseSet) size() int {
+ return len(s.dense)
+}
+
+func (s *sparseSet) contains(x ID) bool {
+ i := s.sparse[x]
+ return i < int32(len(s.dense)) && s.dense[i] == x
+}
+
+func (s *sparseSet) add(x ID) {
+ i := s.sparse[x]
+ if i < int32(len(s.dense)) && s.dense[i] == x {
+ return
+ }
+ s.dense = append(s.dense, x)
+ s.sparse[x] = int32(len(s.dense)) - 1
+}
+
+func (s *sparseSet) addAll(a []ID) {
+ for _, x := range a {
+ s.add(x)
+ }
+}
+
+func (s *sparseSet) addAllValues(a []*Value) {
+ for _, v := range a {
+ s.add(v.ID)
+ }
+}
+
+func (s *sparseSet) remove(x ID) {
+ i := s.sparse[x]
+ if i < int32(len(s.dense)) && s.dense[i] == x {
+ y := s.dense[len(s.dense)-1]
+ s.dense[i] = y
+ s.sparse[y] = i
+ s.dense = s.dense[:len(s.dense)-1]
+ }
+}
+
+// pop removes an arbitrary element from the set.
+// The set must be nonempty.
+func (s *sparseSet) pop() ID {
+ x := s.dense[len(s.dense)-1]
+ s.dense = s.dense[:len(s.dense)-1]
+ return x
+}
+
+func (s *sparseSet) clear() {
+ s.dense = s.dense[:0]
+}
+
+func (s *sparseSet) contents() []ID {
+ return s.dense
+}
diff --git a/src/cmd/compile/internal/ssa/sparsetree.go b/src/cmd/compile/internal/ssa/sparsetree.go
new file mode 100644
index 0000000..1be20b2
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/sparsetree.go
@@ -0,0 +1,235 @@
+// 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"
+ "strings"
+)
+
+type SparseTreeNode struct {
+ child *Block
+ sibling *Block
+ parent *Block
+
+ // Every block has 6 numbers associated with it:
+ // entry-1, entry, entry+1, exit-1, and exit, exit+1.
+ // entry and exit are conceptually the top of the block (phi functions)
+ // entry+1 and exit-1 are conceptually the bottom of the block (ordinary defs)
+ // entry-1 and exit+1 are conceptually "just before" the block (conditions flowing in)
+ //
+ // This simplifies life if we wish to query information about x
+ // when x is both an input to and output of a block.
+ entry, exit int32
+}
+
+func (s *SparseTreeNode) String() string {
+ return fmt.Sprintf("[%d,%d]", s.entry, s.exit)
+}
+
+func (s *SparseTreeNode) Entry() int32 {
+ return s.entry
+}
+
+func (s *SparseTreeNode) Exit() int32 {
+ return s.exit
+}
+
+const (
+ // When used to lookup up definitions in a sparse tree,
+ // these adjustments to a block's entry (+adjust) and
+ // exit (-adjust) numbers allow a distinction to be made
+ // between assignments (typically branch-dependent
+ // conditionals) occurring "before" the block (e.g., as inputs
+ // to the block and its phi functions), "within" the block,
+ // and "after" the block.
+ AdjustBefore = -1 // defined before phi
+ AdjustWithin = 0 // defined by phi
+ AdjustAfter = 1 // defined within block
+)
+
+// A SparseTree is a tree of Blocks.
+// It allows rapid ancestor queries,
+// such as whether one block dominates another.
+type SparseTree []SparseTreeNode
+
+// newSparseTree creates a SparseTree from a block-to-parent map (array indexed by Block.ID)
+func newSparseTree(f *Func, parentOf []*Block) SparseTree {
+ t := make(SparseTree, f.NumBlocks())
+ for _, b := range f.Blocks {
+ n := &t[b.ID]
+ if p := parentOf[b.ID]; p != nil {
+ n.parent = p
+ n.sibling = t[p.ID].child
+ t[p.ID].child = b
+ }
+ }
+ t.numberBlock(f.Entry, 1)
+ return t
+}
+
+// newSparseOrderedTree creates a SparseTree from a block-to-parent map (array indexed by Block.ID)
+// children will appear in the reverse of their order in reverseOrder
+// in particular, if reverseOrder is a dfs-reversePostOrder, then the root-to-children
+// walk of the tree will yield a pre-order.
+func newSparseOrderedTree(f *Func, parentOf, reverseOrder []*Block) SparseTree {
+ t := make(SparseTree, f.NumBlocks())
+ for _, b := range reverseOrder {
+ n := &t[b.ID]
+ if p := parentOf[b.ID]; p != nil {
+ n.parent = p
+ n.sibling = t[p.ID].child
+ t[p.ID].child = b
+ }
+ }
+ t.numberBlock(f.Entry, 1)
+ return t
+}
+
+// treestructure provides a string description of the dominator
+// tree and flow structure of block b and all blocks that it
+// dominates.
+func (t SparseTree) treestructure(b *Block) string {
+ return t.treestructure1(b, 0)
+}
+func (t SparseTree) treestructure1(b *Block, i int) string {
+ s := "\n" + strings.Repeat("\t", i) + b.String() + "->["
+ for i, e := range b.Succs {
+ if i > 0 {
+ s += ","
+ }
+ s += e.b.String()
+ }
+ s += "]"
+ if c0 := t[b.ID].child; c0 != nil {
+ s += "("
+ for c := c0; c != nil; c = t[c.ID].sibling {
+ if c != c0 {
+ s += " "
+ }
+ s += t.treestructure1(c, i+1)
+ }
+ s += ")"
+ }
+ return s
+}
+
+// numberBlock assigns entry and exit numbers for b and b's
+// children in an in-order walk from a gappy sequence, where n
+// is the first number not yet assigned or reserved. N should
+// be larger than zero. For each entry and exit number, the
+// values one larger and smaller are reserved to indicate
+// "strictly above" and "strictly below". numberBlock returns
+// the smallest number not yet assigned or reserved (i.e., the
+// exit number of the last block visited, plus two, because
+// last.exit+1 is a reserved value.)
+//
+// examples:
+//
+// single node tree Root, call with n=1
+// entry=2 Root exit=5; returns 7
+//
+// two node tree, Root->Child, call with n=1
+// entry=2 Root exit=11; returns 13
+// entry=5 Child exit=8
+//
+// three node tree, Root->(Left, Right), call with n=1
+// entry=2 Root exit=17; returns 19
+// entry=5 Left exit=8; entry=11 Right exit=14
+//
+// This is the in-order sequence of assigned and reserved numbers
+// for the last example:
+// root left left right right root
+// 1 2e 3 | 4 5e 6 | 7 8x 9 | 10 11e 12 | 13 14x 15 | 16 17x 18
+
+func (t SparseTree) numberBlock(b *Block, n int32) int32 {
+ // reserve n for entry-1, assign n+1 to entry
+ n++
+ t[b.ID].entry = n
+ // reserve n+1 for entry+1, n+2 is next free number
+ n += 2
+ for c := t[b.ID].child; c != nil; c = t[c.ID].sibling {
+ n = t.numberBlock(c, n) // preserves n = next free number
+ }
+ // reserve n for exit-1, assign n+1 to exit
+ n++
+ t[b.ID].exit = n
+ // reserve n+1 for exit+1, n+2 is next free number, returned.
+ return n + 2
+}
+
+// Sibling returns a sibling of x in the dominator tree (i.e.,
+// a node with the same immediate dominator) or nil if there
+// are no remaining siblings in the arbitrary but repeatable
+// order chosen. Because the Child-Sibling order is used
+// to assign entry and exit numbers in the treewalk, those
+// numbers are also consistent with this order (i.e.,
+// Sibling(x) has entry number larger than x's exit number).
+func (t SparseTree) Sibling(x *Block) *Block {
+ return t[x.ID].sibling
+}
+
+// Child returns a child of x in the dominator tree, or
+// nil if there are none. The choice of first child is
+// arbitrary but repeatable.
+func (t SparseTree) Child(x *Block) *Block {
+ return t[x.ID].child
+}
+
+// isAncestorEq reports whether x is an ancestor of or equal to y.
+func (t SparseTree) IsAncestorEq(x, y *Block) bool {
+ if x == y {
+ return true
+ }
+ xx := &t[x.ID]
+ yy := &t[y.ID]
+ return xx.entry <= yy.entry && yy.exit <= xx.exit
+}
+
+// isAncestor reports whether x is a strict ancestor of y.
+func (t SparseTree) isAncestor(x, y *Block) bool {
+ if x == y {
+ return false
+ }
+ xx := &t[x.ID]
+ yy := &t[y.ID]
+ return xx.entry < yy.entry && yy.exit < xx.exit
+}
+
+// domorder returns a value for dominator-oriented sorting.
+// Block domination does not provide a total ordering,
+// but domorder two has useful properties.
+// (1) If domorder(x) > domorder(y) then x does not dominate y.
+// (2) If domorder(x) < domorder(y) and domorder(y) < domorder(z) and x does not dominate y,
+// then x does not dominate z.
+// Property (1) means that blocks sorted by domorder always have a maximal dominant block first.
+// Property (2) allows searches for dominated blocks to exit early.
+func (t SparseTree) domorder(x *Block) int32 {
+ // Here is an argument that entry(x) provides the properties documented above.
+ //
+ // Entry and exit values are assigned in a depth-first dominator tree walk.
+ // For all blocks x and y, one of the following holds:
+ //
+ // (x-dom-y) x dominates y => entry(x) < entry(y) < exit(y) < exit(x)
+ // (y-dom-x) y dominates x => entry(y) < entry(x) < exit(x) < exit(y)
+ // (x-then-y) neither x nor y dominates the other and x walked before y => entry(x) < exit(x) < entry(y) < exit(y)
+ // (y-then-x) neither x nor y dominates the other and y walked before y => entry(y) < exit(y) < entry(x) < exit(x)
+ //
+ // entry(x) > entry(y) eliminates case x-dom-y. This provides property (1) above.
+ //
+ // For property (2), assume entry(x) < entry(y) and entry(y) < entry(z) and x does not dominate y.
+ // entry(x) < entry(y) allows cases x-dom-y and x-then-y.
+ // But by supposition, x does not dominate y. So we have x-then-y.
+ //
+ // For contradiction, assume x dominates z.
+ // Then entry(x) < entry(z) < exit(z) < exit(x).
+ // But we know x-then-y, so entry(x) < exit(x) < entry(y) < exit(y).
+ // Combining those, entry(x) < entry(z) < exit(z) < exit(x) < entry(y) < exit(y).
+ // By supposition, entry(y) < entry(z), which allows cases y-dom-z and y-then-z.
+ // y-dom-z requires entry(y) < entry(z), but we have entry(z) < entry(y).
+ // y-then-z requires exit(y) < entry(z), but we have entry(z) < exit(y).
+ // We have a contradiction, so x does not dominate z, as required.
+ return t[x.ID].entry
+}
diff --git a/src/cmd/compile/internal/ssa/sparsetreemap.go b/src/cmd/compile/internal/ssa/sparsetreemap.go
new file mode 100644
index 0000000..d264675
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/sparsetreemap.go
@@ -0,0 +1,189 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import "fmt"
+
+// A SparseTreeMap encodes a subset of nodes within a tree
+// used for sparse-ancestor queries.
+//
+// Combined with a SparseTreeHelper, this supports an Insert
+// to add a tree node to the set and a Find operation to locate
+// the nearest tree ancestor of a given node such that the
+// ancestor is also in the set.
+//
+// Given a set of blocks {B1, B2, B3} within the dominator tree, established
+// by stm.Insert()ing B1, B2, B3, etc, a query at block B
+// (performed with stm.Find(stm, B, adjust, helper))
+// will return the member of the set that is the nearest strict
+// ancestor of B within the dominator tree, or nil if none exists.
+// The expected complexity of this operation is the log of the size
+// the set, given certain assumptions about sparsity (the log complexity
+// could be guaranteed with additional data structures whose constant-
+// factor overhead has not yet been justified.)
+//
+// The adjust parameter allows positioning of the insertion
+// and lookup points within a block -- one of
+// AdjustBefore, AdjustWithin, AdjustAfter,
+// where lookups at AdjustWithin can find insertions at
+// AdjustBefore in the same block, and lookups at AdjustAfter
+// can find insertions at either AdjustBefore or AdjustWithin
+// in the same block. (Note that this assumes a gappy numbering
+// such that exit number or exit number is separated from its
+// nearest neighbor by at least 3).
+//
+// The Sparse Tree lookup algorithm is described by
+// Paul F. Dietz. Maintaining order in a linked list. In
+// Proceedings of the Fourteenth Annual ACM Symposium on
+// Theory of Computing, pages 122–127, May 1982.
+// and by
+// Ben Wegbreit. Faster retrieval from context trees.
+// Communications of the ACM, 19(9):526–529, September 1976.
+type SparseTreeMap RBTint32
+
+// A SparseTreeHelper contains indexing and allocation data
+// structures common to a collection of SparseTreeMaps, as well
+// as exposing some useful control-flow-related data to other
+// packages, such as gc.
+type SparseTreeHelper struct {
+ Sdom []SparseTreeNode // indexed by block.ID
+ Po []*Block // exported data; the blocks, in a post-order
+ Dom []*Block // exported data; the dominator of this block.
+ Ponums []int32 // exported data; Po[Ponums[b.ID]] == b; the index of b in Po
+}
+
+// NewSparseTreeHelper returns a SparseTreeHelper for use
+// in the gc package, for example in phi-function placement.
+func NewSparseTreeHelper(f *Func) *SparseTreeHelper {
+ dom := f.Idom()
+ ponums := make([]int32, f.NumBlocks())
+ po := postorderWithNumbering(f, ponums)
+ return makeSparseTreeHelper(newSparseTree(f, dom), dom, po, ponums)
+}
+
+func (h *SparseTreeHelper) NewTree() *SparseTreeMap {
+ return &SparseTreeMap{}
+}
+
+func makeSparseTreeHelper(sdom SparseTree, dom, po []*Block, ponums []int32) *SparseTreeHelper {
+ helper := &SparseTreeHelper{Sdom: []SparseTreeNode(sdom),
+ Dom: dom,
+ Po: po,
+ Ponums: ponums,
+ }
+ return helper
+}
+
+// A sparseTreeMapEntry contains the data stored in a binary search
+// data structure indexed by (dominator tree walk) entry and exit numbers.
+// Each entry is added twice, once keyed by entry-1/entry/entry+1 and
+// once keyed by exit+1/exit/exit-1.
+//
+// Within a sparse tree, the two entries added bracket all their descendant
+// entries within the tree; the first insertion is keyed by entry number,
+// which comes before all the entry and exit numbers of descendants, and
+// the second insertion is keyed by exit number, which comes after all the
+// entry and exit numbers of the descendants.
+type sparseTreeMapEntry struct {
+ index *SparseTreeNode // references the entry and exit numbers for a block in the sparse tree
+ block *Block // TODO: store this in a separate index.
+ data interface{}
+ sparseParent *sparseTreeMapEntry // references the nearest ancestor of this block in the sparse tree.
+ adjust int32 // at what adjustment was this node entered into the sparse tree? The same block may be entered more than once, but at different adjustments.
+}
+
+// Insert creates a definition within b with data x.
+// adjust indicates where in the block should be inserted:
+// AdjustBefore means defined at a phi function (visible Within or After in the same block)
+// AdjustWithin means defined within the block (visible After in the same block)
+// AdjustAfter means after the block (visible within child blocks)
+func (m *SparseTreeMap) Insert(b *Block, adjust int32, x interface{}, helper *SparseTreeHelper) {
+ rbtree := (*RBTint32)(m)
+ blockIndex := &helper.Sdom[b.ID]
+ if blockIndex.entry == 0 {
+ // assert unreachable
+ return
+ }
+ // sp will be the sparse parent in this sparse tree (nearest ancestor in the larger tree that is also in this sparse tree)
+ sp := m.findEntry(b, adjust, helper)
+ entry := &sparseTreeMapEntry{index: blockIndex, block: b, data: x, sparseParent: sp, adjust: adjust}
+
+ right := blockIndex.exit - adjust
+ _ = rbtree.Insert(right, entry)
+
+ left := blockIndex.entry + adjust
+ _ = rbtree.Insert(left, entry)
+
+ // This newly inserted block may now be the sparse parent of some existing nodes (the new sparse children of this block)
+ // Iterate over nodes bracketed by this new node to correct their parent, but not over the proper sparse descendants of those nodes.
+ _, d := rbtree.Lub(left) // Lub (not EQ) of left is either right or a sparse child
+ for tme := d.(*sparseTreeMapEntry); tme != entry; tme = d.(*sparseTreeMapEntry) {
+ tme.sparseParent = entry
+ // all descendants of tme are unchanged;
+ // next sparse sibling (or right-bracketing sparse parent == entry) is first node after tme.index.exit - tme.adjust
+ _, d = rbtree.Lub(tme.index.exit - tme.adjust)
+ }
+}
+
+// Find returns the definition visible from block b, or nil if none can be found.
+// Adjust indicates where the block should be searched.
+// AdjustBefore searches before the phi functions of b.
+// AdjustWithin searches starting at the phi functions of b.
+// AdjustAfter searches starting at the exit from the block, including normal within-block definitions.
+//
+// Note that Finds are properly nested with Inserts:
+// m.Insert(b, a) followed by m.Find(b, a) will not return the result of the insert,
+// but m.Insert(b, AdjustBefore) followed by m.Find(b, AdjustWithin) will.
+//
+// Another way to think of this is that Find searches for inputs, Insert defines outputs.
+func (m *SparseTreeMap) Find(b *Block, adjust int32, helper *SparseTreeHelper) interface{} {
+ v := m.findEntry(b, adjust, helper)
+ if v == nil {
+ return nil
+ }
+ return v.data
+}
+
+func (m *SparseTreeMap) findEntry(b *Block, adjust int32, helper *SparseTreeHelper) *sparseTreeMapEntry {
+ rbtree := (*RBTint32)(m)
+ if rbtree == nil {
+ return nil
+ }
+ blockIndex := &helper.Sdom[b.ID]
+
+ // The Glb (not EQ) of this probe is either the entry-indexed end of a sparse parent
+ // or the exit-indexed end of a sparse sibling
+ _, v := rbtree.Glb(blockIndex.entry + adjust)
+
+ if v == nil {
+ return nil
+ }
+
+ otherEntry := v.(*sparseTreeMapEntry)
+ if otherEntry.index.exit >= blockIndex.exit { // otherEntry exit after blockIndex exit; therefore, brackets
+ return otherEntry
+ }
+ // otherEntry is a sparse Sibling, and shares the same sparse parent (nearest ancestor within larger tree)
+ sp := otherEntry.sparseParent
+ if sp != nil {
+ if sp.index.exit < blockIndex.exit { // no ancestor found
+ return nil
+ }
+ return sp
+ }
+ return nil
+}
+
+func (m *SparseTreeMap) String() string {
+ tree := (*RBTint32)(m)
+ return tree.String()
+}
+
+func (e *sparseTreeMapEntry) String() string {
+ if e == nil {
+ return "nil"
+ }
+ return fmt.Sprintf("(index=%v, block=%v, data=%v)->%v", e.index, e.block, e.data, e.sparseParent)
+}
diff --git a/src/cmd/compile/internal/ssa/stackalloc.go b/src/cmd/compile/internal/ssa/stackalloc.go
new file mode 100644
index 0000000..406a3c3
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/stackalloc.go
@@ -0,0 +1,420 @@
+// 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.
+
+// TODO: live at start of block instead?
+
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "fmt"
+)
+
+type stackAllocState struct {
+ f *Func
+
+ // live is the output of stackalloc.
+ // live[b.id] = live values at the end of block b.
+ live [][]ID
+
+ // The following slices are reused across multiple users
+ // of stackAllocState.
+ values []stackValState
+ interfere [][]ID // interfere[v.id] = values that interfere with v.
+ names []LocalSlot
+ slots []int
+ used []bool
+
+ nArgSlot, // Number of Values sourced to arg slot
+ nNotNeed, // Number of Values not needing a stack slot
+ nNamedSlot, // Number of Values using a named stack slot
+ nReuse, // Number of values reusing a stack slot
+ nAuto, // Number of autos allocated for stack slots.
+ nSelfInterfere int32 // Number of self-interferences
+}
+
+func newStackAllocState(f *Func) *stackAllocState {
+ s := f.Cache.stackAllocState
+ if s == nil {
+ return new(stackAllocState)
+ }
+ if s.f != nil {
+ f.fe.Fatalf(src.NoXPos, "newStackAllocState called without previous free")
+ }
+ return s
+}
+
+func putStackAllocState(s *stackAllocState) {
+ for i := range s.values {
+ s.values[i] = stackValState{}
+ }
+ for i := range s.interfere {
+ s.interfere[i] = nil
+ }
+ for i := range s.names {
+ s.names[i] = LocalSlot{}
+ }
+ for i := range s.slots {
+ s.slots[i] = 0
+ }
+ for i := range s.used {
+ s.used[i] = false
+ }
+ s.f.Cache.stackAllocState = s
+ s.f = nil
+ s.live = nil
+ s.nArgSlot, s.nNotNeed, s.nNamedSlot, s.nReuse, s.nAuto, s.nSelfInterfere = 0, 0, 0, 0, 0, 0
+}
+
+type stackValState struct {
+ typ *types.Type
+ spill *Value
+ needSlot bool
+ isArg bool
+}
+
+// stackalloc allocates storage in the stack frame for
+// all Values that did not get a register.
+// Returns a map from block ID to the stack values live at the end of that block.
+func stackalloc(f *Func, spillLive [][]ID) [][]ID {
+ if f.pass.debug > stackDebug {
+ fmt.Println("before stackalloc")
+ fmt.Println(f.String())
+ }
+ s := newStackAllocState(f)
+ s.init(f, spillLive)
+ defer putStackAllocState(s)
+
+ s.stackalloc()
+ if f.pass.stats > 0 {
+ f.LogStat("stack_alloc_stats",
+ s.nArgSlot, "arg_slots", s.nNotNeed, "slot_not_needed",
+ s.nNamedSlot, "named_slots", s.nAuto, "auto_slots",
+ s.nReuse, "reused_slots", s.nSelfInterfere, "self_interfering")
+ }
+
+ return s.live
+}
+
+func (s *stackAllocState) init(f *Func, spillLive [][]ID) {
+ s.f = f
+
+ // Initialize value information.
+ if n := f.NumValues(); cap(s.values) >= n {
+ s.values = s.values[:n]
+ } else {
+ s.values = make([]stackValState, n)
+ }
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ s.values[v.ID].typ = v.Type
+ s.values[v.ID].needSlot = !v.Type.IsMemory() && !v.Type.IsVoid() && !v.Type.IsFlags() && f.getHome(v.ID) == nil && !v.rematerializeable() && !v.OnWasmStack
+ s.values[v.ID].isArg = v.Op == OpArg
+ if f.pass.debug > stackDebug && s.values[v.ID].needSlot {
+ fmt.Printf("%s needs a stack slot\n", v)
+ }
+ if v.Op == OpStoreReg {
+ s.values[v.Args[0].ID].spill = v
+ }
+ }
+ }
+
+ // Compute liveness info for values needing a slot.
+ s.computeLive(spillLive)
+
+ // Build interference graph among values needing a slot.
+ s.buildInterferenceGraph()
+}
+
+func (s *stackAllocState) stackalloc() {
+ f := s.f
+
+ // Build map from values to their names, if any.
+ // A value may be associated with more than one name (e.g. after
+ // the assignment i=j). This step picks one name per value arbitrarily.
+ if n := f.NumValues(); cap(s.names) >= n {
+ s.names = s.names[:n]
+ } else {
+ s.names = make([]LocalSlot, n)
+ }
+ names := s.names
+ for _, name := range f.Names {
+ // Note: not "range f.NamedValues" above, because
+ // that would be nondeterministic.
+ for _, v := range f.NamedValues[name] {
+ names[v.ID] = name
+ }
+ }
+
+ // Allocate args to their assigned locations.
+ for _, v := range f.Entry.Values {
+ if v.Op != OpArg {
+ continue
+ }
+ if v.Aux == nil {
+ f.Fatalf("%s has nil Aux\n", v.LongString())
+ }
+ loc := LocalSlot{N: v.Aux.(GCNode), Type: v.Type, Off: v.AuxInt}
+ if f.pass.debug > stackDebug {
+ fmt.Printf("stackalloc %s to %s\n", v, loc)
+ }
+ f.setHome(v, loc)
+ }
+
+ // For each type, we keep track of all the stack slots we
+ // have allocated for that type.
+ // TODO: share slots among equivalent types. We would need to
+ // only share among types with the same GC signature. See the
+ // type.Equal calls below for where this matters.
+ locations := map[*types.Type][]LocalSlot{}
+
+ // Each time we assign a stack slot to a value v, we remember
+ // the slot we used via an index into locations[v.Type].
+ slots := s.slots
+ if n := f.NumValues(); cap(slots) >= n {
+ slots = slots[:n]
+ } else {
+ slots = make([]int, n)
+ s.slots = slots
+ }
+ for i := range slots {
+ slots[i] = -1
+ }
+
+ // Pick a stack slot for each value needing one.
+ var used []bool
+ if n := f.NumValues(); cap(s.used) >= n {
+ used = s.used[:n]
+ } else {
+ used = make([]bool, n)
+ s.used = used
+ }
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if !s.values[v.ID].needSlot {
+ s.nNotNeed++
+ continue
+ }
+ if v.Op == OpArg {
+ s.nArgSlot++
+ continue // already picked
+ }
+
+ // If this is a named value, try to use the name as
+ // the spill location.
+ var name LocalSlot
+ if v.Op == OpStoreReg {
+ name = names[v.Args[0].ID]
+ } else {
+ name = names[v.ID]
+ }
+ if name.N != nil && v.Type.Compare(name.Type) == types.CMPeq {
+ for _, id := range s.interfere[v.ID] {
+ h := f.getHome(id)
+ if h != nil && h.(LocalSlot).N == name.N && h.(LocalSlot).Off == name.Off {
+ // A variable can interfere with itself.
+ // It is rare, but it can happen.
+ s.nSelfInterfere++
+ goto noname
+ }
+ }
+ if f.pass.debug > stackDebug {
+ fmt.Printf("stackalloc %s to %s\n", v, name)
+ }
+ s.nNamedSlot++
+ f.setHome(v, name)
+ continue
+ }
+
+ noname:
+ // Set of stack slots we could reuse.
+ locs := locations[v.Type]
+ // Mark all positions in locs used by interfering values.
+ for i := 0; i < len(locs); i++ {
+ used[i] = false
+ }
+ for _, xid := range s.interfere[v.ID] {
+ slot := slots[xid]
+ if slot >= 0 {
+ used[slot] = true
+ }
+ }
+ // Find an unused stack slot.
+ var i int
+ for i = 0; i < len(locs); i++ {
+ if !used[i] {
+ s.nReuse++
+ break
+ }
+ }
+ // If there is no unused stack slot, allocate a new one.
+ if i == len(locs) {
+ s.nAuto++
+ locs = append(locs, LocalSlot{N: f.fe.Auto(v.Pos, v.Type), Type: v.Type, Off: 0})
+ locations[v.Type] = locs
+ }
+ // Use the stack variable at that index for v.
+ loc := locs[i]
+ if f.pass.debug > stackDebug {
+ fmt.Printf("stackalloc %s to %s\n", v, loc)
+ }
+ f.setHome(v, loc)
+ slots[v.ID] = i
+ }
+ }
+}
+
+// computeLive computes a map from block ID to a list of
+// stack-slot-needing value IDs live at the end of that block.
+// TODO: this could be quadratic if lots of variables are live across lots of
+// basic blocks. Figure out a way to make this function (or, more precisely, the user
+// of this function) require only linear size & time.
+func (s *stackAllocState) computeLive(spillLive [][]ID) {
+ s.live = make([][]ID, s.f.NumBlocks())
+ var phis []*Value
+ live := s.f.newSparseSet(s.f.NumValues())
+ defer s.f.retSparseSet(live)
+ t := s.f.newSparseSet(s.f.NumValues())
+ defer s.f.retSparseSet(t)
+
+ // Instead of iterating over f.Blocks, iterate over their postordering.
+ // Liveness information flows backward, so starting at the end
+ // increases the probability that we will stabilize quickly.
+ po := s.f.postorder()
+ for {
+ changed := false
+ for _, b := range po {
+ // Start with known live values at the end of the block
+ live.clear()
+ live.addAll(s.live[b.ID])
+
+ // Propagate backwards to the start of the block
+ phis = phis[:0]
+ for i := len(b.Values) - 1; i >= 0; i-- {
+ v := b.Values[i]
+ live.remove(v.ID)
+ if v.Op == OpPhi {
+ // Save phi for later.
+ // Note: its args might need a stack slot even though
+ // the phi itself doesn't. So don't use needSlot.
+ if !v.Type.IsMemory() && !v.Type.IsVoid() {
+ phis = append(phis, v)
+ }
+ continue
+ }
+ for _, a := range v.Args {
+ if s.values[a.ID].needSlot {
+ live.add(a.ID)
+ }
+ }
+ }
+
+ // for each predecessor of b, expand its list of live-at-end values
+ // invariant: s contains the values live at the start of b (excluding phi inputs)
+ for i, e := range b.Preds {
+ p := e.b
+ t.clear()
+ t.addAll(s.live[p.ID])
+ t.addAll(live.contents())
+ t.addAll(spillLive[p.ID])
+ for _, v := range phis {
+ a := v.Args[i]
+ if s.values[a.ID].needSlot {
+ t.add(a.ID)
+ }
+ if spill := s.values[a.ID].spill; spill != nil {
+ //TODO: remove? Subsumed by SpillUse?
+ t.add(spill.ID)
+ }
+ }
+ if t.size() == len(s.live[p.ID]) {
+ continue
+ }
+ // grow p's live set
+ s.live[p.ID] = append(s.live[p.ID][:0], t.contents()...)
+ changed = true
+ }
+ }
+
+ if !changed {
+ break
+ }
+ }
+ if s.f.pass.debug > stackDebug {
+ for _, b := range s.f.Blocks {
+ fmt.Printf("stacklive %s %v\n", b, s.live[b.ID])
+ }
+ }
+}
+
+func (f *Func) getHome(vid ID) Location {
+ if int(vid) >= len(f.RegAlloc) {
+ return nil
+ }
+ return f.RegAlloc[vid]
+}
+
+func (f *Func) setHome(v *Value, loc Location) {
+ for v.ID >= ID(len(f.RegAlloc)) {
+ f.RegAlloc = append(f.RegAlloc, nil)
+ }
+ f.RegAlloc[v.ID] = loc
+}
+
+func (s *stackAllocState) buildInterferenceGraph() {
+ f := s.f
+ if n := f.NumValues(); cap(s.interfere) >= n {
+ s.interfere = s.interfere[:n]
+ } else {
+ s.interfere = make([][]ID, n)
+ }
+ live := f.newSparseSet(f.NumValues())
+ defer f.retSparseSet(live)
+ for _, b := range f.Blocks {
+ // Propagate liveness backwards to the start of the block.
+ // Two values interfere if one is defined while the other is live.
+ live.clear()
+ live.addAll(s.live[b.ID])
+ for i := len(b.Values) - 1; i >= 0; i-- {
+ v := b.Values[i]
+ if s.values[v.ID].needSlot {
+ live.remove(v.ID)
+ for _, id := range live.contents() {
+ // Note: args can have different types and still interfere
+ // (with each other or with other values). See issue 23522.
+ if s.values[v.ID].typ.Compare(s.values[id].typ) == types.CMPeq || v.Op == OpArg || s.values[id].isArg {
+ s.interfere[v.ID] = append(s.interfere[v.ID], id)
+ s.interfere[id] = append(s.interfere[id], v.ID)
+ }
+ }
+ }
+ for _, a := range v.Args {
+ if s.values[a.ID].needSlot {
+ live.add(a.ID)
+ }
+ }
+ if v.Op == OpArg && s.values[v.ID].needSlot {
+ // OpArg is an input argument which is pre-spilled.
+ // We add back v.ID here because we want this value
+ // to appear live even before this point. Being live
+ // all the way to the start of the entry block prevents other
+ // values from being allocated to the same slot and clobbering
+ // the input value before we have a chance to load it.
+ live.add(v.ID)
+ }
+ }
+ }
+ if f.pass.debug > stackDebug {
+ for vid, i := range s.interfere {
+ if len(i) > 0 {
+ fmt.Printf("v%d interferes with", vid)
+ for _, x := range i {
+ fmt.Printf(" v%d", x)
+ }
+ fmt.Println()
+ }
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/stackframe.go b/src/cmd/compile/internal/ssa/stackframe.go
new file mode 100644
index 0000000..08be62a
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/stackframe.go
@@ -0,0 +1,10 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// stackframe calls back into the frontend to assign frame offsets.
+func stackframe(f *Func) {
+ f.fe.AllocFrame(f)
+}
diff --git a/src/cmd/compile/internal/ssa/stmtlines_test.go b/src/cmd/compile/internal/ssa/stmtlines_test.go
new file mode 100644
index 0000000..f5ff3a5
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/stmtlines_test.go
@@ -0,0 +1,132 @@
+package ssa_test
+
+import (
+ cmddwarf "cmd/internal/dwarf"
+ "debug/dwarf"
+ "debug/elf"
+ "debug/macho"
+ "debug/pe"
+ "fmt"
+ "internal/testenv"
+ "internal/xcoff"
+ "io"
+ "os"
+ "runtime"
+ "sort"
+ "testing"
+)
+
+func open(path string) (*dwarf.Data, error) {
+ if fh, err := elf.Open(path); err == nil {
+ return fh.DWARF()
+ }
+
+ if fh, err := pe.Open(path); err == nil {
+ return fh.DWARF()
+ }
+
+ if fh, err := macho.Open(path); err == nil {
+ return fh.DWARF()
+ }
+
+ if fh, err := xcoff.Open(path); err == nil {
+ return fh.DWARF()
+ }
+
+ return nil, fmt.Errorf("unrecognized executable format")
+}
+
+func must(err error) {
+ if err != nil {
+ panic(err)
+ }
+}
+
+type Line struct {
+ File string
+ Line int
+}
+
+func TestStmtLines(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ t.Skip("skipping on plan9; no DWARF symbol table in executables")
+ }
+
+ if runtime.GOOS == "aix" {
+ extld := os.Getenv("CC")
+ if extld == "" {
+ extld = "gcc"
+ }
+ enabled, err := cmddwarf.IsDWARFEnabledOnAIXLd(extld)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !enabled {
+ t.Skip("skipping on aix: no DWARF with ld version < 7.2.2 ")
+ }
+ }
+
+ lines := map[Line]bool{}
+ dw, err := open(testenv.GoToolPath(t))
+ must(err)
+ rdr := dw.Reader()
+ rdr.Seek(0)
+ for {
+ e, err := rdr.Next()
+ must(err)
+ if e == nil {
+ break
+ }
+ if e.Tag != dwarf.TagCompileUnit {
+ continue
+ }
+ pkgname, _ := e.Val(dwarf.AttrName).(string)
+ if pkgname == "runtime" {
+ continue
+ }
+ if e.Val(dwarf.AttrStmtList) == nil {
+ continue
+ }
+ lrdr, err := dw.LineReader(e)
+ must(err)
+
+ var le dwarf.LineEntry
+
+ for {
+ err := lrdr.Next(&le)
+ if err == io.EOF {
+ break
+ }
+ must(err)
+ fl := Line{le.File.Name, le.Line}
+ lines[fl] = lines[fl] || le.IsStmt
+ }
+ }
+
+ nonStmtLines := []Line{}
+ for line, isstmt := range lines {
+ if !isstmt {
+ nonStmtLines = append(nonStmtLines, line)
+ }
+ }
+
+ if runtime.GOARCH == "amd64" {
+ if len(nonStmtLines)*100 > len(lines) { // > 99% obtained on amd64, no backsliding
+ t.Errorf("Saw too many (amd64, > 1%%) lines without statement marks, total=%d, nostmt=%d ('-run TestStmtLines -v' lists failing lines)\n", len(lines), len(nonStmtLines))
+ }
+ } else if len(nonStmtLines)*100 > 2*len(lines) { // expect 98% elsewhere.
+ t.Errorf("Saw too many (not amd64, > 2%%) lines without statement marks, total=%d, nostmt=%d ('-run TestStmtLines -v' lists failing lines)\n", len(lines), len(nonStmtLines))
+ }
+ if testing.Verbose() {
+ sort.Slice(nonStmtLines, func(i, j int) bool {
+ if nonStmtLines[i].File != nonStmtLines[j].File {
+ return nonStmtLines[i].File < nonStmtLines[j].File
+ }
+ return nonStmtLines[i].Line < nonStmtLines[j].Line
+ })
+ for _, l := range nonStmtLines {
+ t.Logf("%s:%d has no DWARF is_stmt mark\n", l.File, l.Line)
+ }
+ }
+ t.Logf("total=%d, nostmt=%d\n", len(lines), len(nonStmtLines))
+}
diff --git a/src/cmd/compile/internal/ssa/testdata/hist.dlv-dbg.nexts b/src/cmd/compile/internal/ssa/testdata/hist.dlv-dbg.nexts
new file mode 100644
index 0000000..a0404e4
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/hist.dlv-dbg.nexts
@@ -0,0 +1,99 @@
+ ./testdata/hist.go
+55: func test() {
+57: l := line{point{1 + zero, 2 + zero}, point{3 + zero, 4 + zero}}
+58: tinycall() // this forces l etc to stack
+59: dx := l.end.x - l.begin.x //gdb-dbg=(l.begin.x,l.end.y)//gdb-opt=(l,dx/O,dy/O)
+60: dy := l.end.y - l.begin.y //gdb-opt=(dx,dy/O)
+61: sink = dx + dy //gdb-opt=(dx,dy)
+63: hist := make([]int, 7) //gdb-opt=(dx/O,dy/O) // TODO sink is missing if this code is in 'test' instead of 'main'
+64: var reader io.Reader = strings.NewReader(cannedInput) //gdb-dbg=(hist/A) // TODO cannedInput/A is missing if this code is in 'test' instead of 'main'
+65: if len(os.Args) > 1 {
+73: scanner := bufio.NewScanner(reader)
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+84: t := 0
+85: n := 0
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+88: continue
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+90: t += i * a
+91: n += a
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+90: t += i * a
+91: n += a
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+88: continue
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+90: t += i * a
+91: n += a
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+90: t += i * a
+91: n += a
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+88: continue
+86: for i, a := range hist {
+99: }
diff --git a/src/cmd/compile/internal/ssa/testdata/hist.dlv-opt.nexts b/src/cmd/compile/internal/ssa/testdata/hist.dlv-opt.nexts
new file mode 100644
index 0000000..2be83ce
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/hist.dlv-opt.nexts
@@ -0,0 +1,94 @@
+ ./testdata/hist.go
+55: func test() {
+57: l := line{point{1 + zero, 2 + zero}, point{3 + zero, 4 + zero}}
+58: tinycall() // this forces l etc to stack
+59: dx := l.end.x - l.begin.x //gdb-dbg=(l.begin.x,l.end.y)//gdb-opt=(l,dx/O,dy/O)
+60: dy := l.end.y - l.begin.y //gdb-opt=(dx,dy/O)
+61: sink = dx + dy //gdb-opt=(dx,dy)
+63: hist := make([]int, 7) //gdb-opt=(dx/O,dy/O) // TODO sink is missing if this code is in 'test' instead of 'main'
+64: var reader io.Reader = strings.NewReader(cannedInput) //gdb-dbg=(hist/A) // TODO cannedInput/A is missing if this code is in 'test' instead of 'main'
+65: if len(os.Args) > 1 {
+73: scanner := bufio.NewScanner(reader)
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+91: n += a
+90: t += i * a
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+91: n += a
+90: t += i * a
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+91: n += a
+90: t += i * a
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+91: n += a
+90: t += i * a
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+86: for i, a := range hist {
+99: }
diff --git a/src/cmd/compile/internal/ssa/testdata/hist.gdb-dbg.nexts b/src/cmd/compile/internal/ssa/testdata/hist.gdb-dbg.nexts
new file mode 100644
index 0000000..72df60c
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/hist.gdb-dbg.nexts
@@ -0,0 +1,123 @@
+ src/cmd/compile/internal/ssa/testdata/hist.go
+55: func test() {
+57: l := line{point{1 + zero, 2 + zero}, point{3 + zero, 4 + zero}}
+58: tinycall() // this forces l etc to stack
+59: dx := l.end.x - l.begin.x //gdb-dbg=(l.begin.x,l.end.y)//gdb-opt=(l,dx/O,dy/O)
+l.begin.x = 1
+l.end.y = 4
+60: dy := l.end.y - l.begin.y //gdb-opt=(dx,dy/O)
+61: sink = dx + dy //gdb-opt=(dx,dy)
+63: hist := make([]int, 7) //gdb-opt=(dx/O,dy/O) // TODO sink is missing if this code is in 'test' instead of 'main'
+64: var reader io.Reader = strings.NewReader(cannedInput) //gdb-dbg=(hist/A) // TODO cannedInput/A is missing if this code is in 'test' instead of 'main'
+hist = {array = <A>, len = 7, cap = 7}
+65: if len(os.Args) > 1 {
+73: scanner := bufio.NewScanner(reader)
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+i = 1
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+i = 1
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+i = 1
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+i = 2
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+i = 2
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+i = 2
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+i = 4
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+i = 4
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+i = 5
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+84: t := 0
+85: n := 0
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+88: continue
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+90: t += i * a
+91: n += a
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+n = 3
+i = 1
+t = 3
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+90: t += i * a
+91: n += a
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+n = 6
+i = 2
+t = 9
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+88: continue
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+90: t += i * a
+91: n += a
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+n = 8
+i = 4
+t = 17
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+90: t += i * a
+91: n += a
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+n = 9
+i = 5
+t = 22
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+88: continue
+86: for i, a := range hist {
+99: }
diff --git a/src/cmd/compile/internal/ssa/testdata/hist.gdb-opt.nexts b/src/cmd/compile/internal/ssa/testdata/hist.gdb-opt.nexts
new file mode 100644
index 0000000..d3a34ac
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/hist.gdb-opt.nexts
@@ -0,0 +1,143 @@
+ src/cmd/compile/internal/ssa/testdata/hist.go
+55: func test() {
+57: l := line{point{1 + zero, 2 + zero}, point{3 + zero, 4 + zero}}
+58: tinycall() // this forces l etc to stack
+59: dx := l.end.x - l.begin.x //gdb-dbg=(l.begin.x,l.end.y)//gdb-opt=(l,dx/O,dy/O)
+l = {begin = {x = 1, y = 2}, end = {x = 3, y = 4}}
+dx = <Optimized out, as expected>
+dy = <Optimized out, as expected>
+60: dy := l.end.y - l.begin.y //gdb-opt=(dx,dy/O)
+dx = 2
+dy = <Optimized out, as expected>
+61: sink = dx + dy //gdb-opt=(dx,dy)
+dx = 2
+dy = 2
+63: hist := make([]int, 7) //gdb-opt=(dx/O,dy/O) // TODO sink is missing if this code is in 'test' instead of 'main'
+dx = 2
+dy = <Optimized out, as expected>
+64: var reader io.Reader = strings.NewReader(cannedInput) //gdb-dbg=(hist/A) // TODO cannedInput/A is missing if this code is in 'test' instead of 'main'
+65: if len(os.Args) > 1 {
+73: scanner := bufio.NewScanner(reader)
+74: for scanner.Scan() { //gdb-opt=(scanner/A)
+scanner = (bufio.Scanner *) <A>
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+err = {tab = 0x0, data = 0x0}
+hist = {array = 0xc00005ae50, len = 7, cap = 7}
+i = 1
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+err = {tab = 0x0, data = 0x0}
+hist = {array = 0xc00005ae50, len = 7, cap = 7}
+i = 1
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+err = {tab = 0x0, data = 0x0}
+hist = {array = 0xc00005ae50, len = 7, cap = 7}
+i = 1
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+err = {tab = 0x0, data = 0x0}
+hist = {array = 0xc00005ae50, len = 7, cap = 7}
+i = 2
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+err = {tab = 0x0, data = 0x0}
+hist = {array = 0xc00005ae50, len = 7, cap = 7}
+i = 2
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+err = {tab = 0x0, data = 0x0}
+hist = {array = 0xc00005ae50, len = 7, cap = 7}
+i = 2
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+err = {tab = 0x0, data = 0x0}
+hist = {array = 0xc00005ae50, len = 7, cap = 7}
+i = 4
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+err = {tab = 0x0, data = 0x0}
+hist = {array = 0xc00005ae50, len = 7, cap = 7}
+i = 4
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+75: s := scanner.Text()
+76: i, err := strconv.ParseInt(s, 10, 64)
+77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+err = {tab = 0x0, data = 0x0}
+hist = {array = 0xc00005ae50, len = 7, cap = 7}
+i = 5
+81: hist = ensure(int(i), hist)
+82: hist[int(i)]++
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+a = 0
+n = 0
+t = 0
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+a = 3
+n = 0
+t = 0
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+91: n += a
+90: t += i * a
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+a = 3
+n = 3
+t = 3
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+91: n += a
+90: t += i * a
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+a = 0
+n = 6
+t = 9
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+a = 2
+n = 6
+t = 9
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+91: n += a
+90: t += i * a
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+a = 1
+n = 8
+t = 17
+92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+91: n += a
+90: t += i * a
+86: for i, a := range hist {
+87: if a == 0 { //gdb-opt=(a,n,t)
+a = 0
+n = 9
+t = 22
+86: for i, a := range hist {
+99: }
diff --git a/src/cmd/compile/internal/ssa/testdata/hist.go b/src/cmd/compile/internal/ssa/testdata/hist.go
new file mode 100644
index 0000000..f8fa6e6
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/hist.go
@@ -0,0 +1,106 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This is the input program for an end-to-end test of the DWARF produced
+// by the compiler. It is compiled with various flags, then the resulting
+// binary is "debugged" under the control of a harness. Because the compile+debug
+// step is time-consuming, the tests for different bugs are all accumulated here
+// so that their cost is only the time to "n" through the additional code.
+
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+)
+
+type point struct {
+ x, y int
+}
+
+type line struct {
+ begin, end point
+}
+
+var zero int
+var sink int
+
+//go:noinline
+func tinycall() {
+}
+
+func ensure(n int, sl []int) []int {
+ for len(sl) <= n {
+ sl = append(sl, 0)
+ }
+ return sl
+}
+
+var cannedInput string = `1
+1
+1
+2
+2
+2
+4
+4
+5
+`
+
+func test() {
+ // For #19868
+ l := line{point{1 + zero, 2 + zero}, point{3 + zero, 4 + zero}}
+ tinycall() // this forces l etc to stack
+ dx := l.end.x - l.begin.x //gdb-dbg=(l.begin.x,l.end.y)//gdb-opt=(l,dx/O,dy/O)
+ dy := l.end.y - l.begin.y //gdb-opt=(dx,dy/O)
+ sink = dx + dy //gdb-opt=(dx,dy)
+ // For #21098
+ hist := make([]int, 7) //gdb-opt=(dx/O,dy/O) // TODO sink is missing if this code is in 'test' instead of 'main'
+ var reader io.Reader = strings.NewReader(cannedInput) //gdb-dbg=(hist/A) // TODO cannedInput/A is missing if this code is in 'test' instead of 'main'
+ if len(os.Args) > 1 {
+ var err error
+ reader, err = os.Open(os.Args[1])
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "There was an error opening %s: %v\n", os.Args[1], err)
+ return
+ }
+ }
+ scanner := bufio.NewScanner(reader)
+ for scanner.Scan() { //gdb-opt=(scanner/A)
+ s := scanner.Text()
+ i, err := strconv.ParseInt(s, 10, 64)
+ if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
+ fmt.Fprintf(os.Stderr, "There was an error: %v\n", err)
+ return
+ }
+ hist = ensure(int(i), hist)
+ hist[int(i)]++
+ }
+ t := 0
+ n := 0
+ for i, a := range hist {
+ if a == 0 { //gdb-opt=(a,n,t)
+ continue
+ }
+ t += i * a
+ n += a
+ fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
+ }
+}
+
+func main() {
+ growstack() // Use stack early to prevent growth during test, which confuses gdb
+ test()
+}
+
+var snk string
+
+//go:noinline
+func growstack() {
+ snk = fmt.Sprintf("%#v,%#v,%#v", 1, true, "cat")
+}
diff --git a/src/cmd/compile/internal/ssa/testdata/i22558.dlv-dbg.nexts b/src/cmd/compile/internal/ssa/testdata/i22558.dlv-dbg.nexts
new file mode 100644
index 0000000..a00934b
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/i22558.dlv-dbg.nexts
@@ -0,0 +1,11 @@
+ ./testdata/i22558.go
+19: func test(t *thing, u *thing) {
+20: if t.next != nil {
+23: fmt.Fprintf(os.Stderr, "%s\n", t.name)
+24: u.self = u
+25: t.self = t
+26: t.next = u
+27: for _, p := range t.stuff {
+28: if isFoo(t, p) {
+29: return
+44: }
diff --git a/src/cmd/compile/internal/ssa/testdata/i22558.gdb-dbg.nexts b/src/cmd/compile/internal/ssa/testdata/i22558.gdb-dbg.nexts
new file mode 100644
index 0000000..70dfa07
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/i22558.gdb-dbg.nexts
@@ -0,0 +1,11 @@
+ src/cmd/compile/internal/ssa/testdata/i22558.go
+19: func test(t *thing, u *thing) {
+20: if t.next != nil {
+23: fmt.Fprintf(os.Stderr, "%s\n", t.name)
+24: u.self = u
+25: t.self = t
+26: t.next = u
+27: for _, p := range t.stuff {
+28: if isFoo(t, p) {
+29: return
+44: }
diff --git a/src/cmd/compile/internal/ssa/testdata/i22558.go b/src/cmd/compile/internal/ssa/testdata/i22558.go
new file mode 100644
index 0000000..8aea76c
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/i22558.go
@@ -0,0 +1,51 @@
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+type big struct {
+ pile [768]int8
+}
+
+type thing struct {
+ name string
+ next *thing
+ self *thing
+ stuff []big
+}
+
+func test(t *thing, u *thing) {
+ if t.next != nil {
+ return
+ }
+ fmt.Fprintf(os.Stderr, "%s\n", t.name)
+ u.self = u
+ t.self = t
+ t.next = u
+ for _, p := range t.stuff {
+ if isFoo(t, p) {
+ return
+ }
+ }
+}
+
+//go:noinline
+func isFoo(t *thing, b big) bool {
+ return true
+}
+
+func main() {
+ growstack() // Use stack early to prevent growth during test, which confuses gdb
+ t := &thing{name: "t", self: nil, next: nil, stuff: make([]big, 1)}
+ u := thing{name: "u", self: t, next: t, stuff: make([]big, 1)}
+ test(t, &u)
+}
+
+var snk string
+
+//go:noinline
+func growstack() {
+ snk = fmt.Sprintf("%#v,%#v,%#v", 1, true, "cat")
+}
diff --git a/src/cmd/compile/internal/ssa/testdata/i22600.dlv-dbg-race.nexts b/src/cmd/compile/internal/ssa/testdata/i22600.dlv-dbg-race.nexts
new file mode 100644
index 0000000..18a5ff9
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/i22600.dlv-dbg-race.nexts
@@ -0,0 +1,7 @@
+ ./testdata/i22600.go
+8: func test() {
+9: pwd, err := os.Getwd()
+10: if err != nil {
+14: fmt.Println(pwd)
+15: }
+20: }
diff --git a/src/cmd/compile/internal/ssa/testdata/i22600.gdb-dbg-race.nexts b/src/cmd/compile/internal/ssa/testdata/i22600.gdb-dbg-race.nexts
new file mode 100644
index 0000000..46285e2
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/i22600.gdb-dbg-race.nexts
@@ -0,0 +1,7 @@
+ src/cmd/compile/internal/ssa/testdata/i22600.go
+8: func test() {
+9: pwd, err := os.Getwd()
+10: if err != nil {
+14: fmt.Println(pwd)
+15: }
+20: }
diff --git a/src/cmd/compile/internal/ssa/testdata/i22600.go b/src/cmd/compile/internal/ssa/testdata/i22600.go
new file mode 100644
index 0000000..27f0d3d
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/i22600.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func test() {
+ pwd, err := os.Getwd()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ fmt.Println(pwd)
+}
+
+func main() {
+ growstack() // Use stack early to prevent growth during test, which confuses gdb
+ test()
+}
+
+var snk string
+
+//go:noinline
+func growstack() {
+ snk = fmt.Sprintf("%#v,%#v,%#v", 1, true, "cat")
+}
diff --git a/src/cmd/compile/internal/ssa/testdata/infloop.dlv-opt.nexts b/src/cmd/compile/internal/ssa/testdata/infloop.dlv-opt.nexts
new file mode 100644
index 0000000..0b9f06f
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/infloop.dlv-opt.nexts
@@ -0,0 +1,12 @@
+ ./testdata/infloop.go
+6: func test() {
+8: go func() {}()
+10: for {
+1: package main
+10: for {
+1: package main
+10: for {
+1: package main
+10: for {
+1: package main
+10: for {
diff --git a/src/cmd/compile/internal/ssa/testdata/infloop.gdb-opt.nexts b/src/cmd/compile/internal/ssa/testdata/infloop.gdb-opt.nexts
new file mode 100644
index 0000000..d465ad1
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/infloop.gdb-opt.nexts
@@ -0,0 +1,4 @@
+ src/cmd/compile/internal/ssa/testdata/infloop.go
+6: func test() {
+8: go func() {}()
+10: for {
diff --git a/src/cmd/compile/internal/ssa/testdata/infloop.go b/src/cmd/compile/internal/ssa/testdata/infloop.go
new file mode 100644
index 0000000..cdb374f
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/infloop.go
@@ -0,0 +1,16 @@
+package main
+
+var sink int
+
+//go:noinline
+func test() {
+ // This is for #30167, incorrect line numbers in an infinite loop
+ go func() {}()
+
+ for {
+ }
+}
+
+func main() {
+ test()
+}
diff --git a/src/cmd/compile/internal/ssa/testdata/scopes.dlv-dbg.nexts b/src/cmd/compile/internal/ssa/testdata/scopes.dlv-dbg.nexts
new file mode 100644
index 0000000..f182ff4
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/scopes.dlv-dbg.nexts
@@ -0,0 +1,56 @@
+ ./testdata/scopes.go
+22: func test() {
+23: x := id(0)
+24: y := id(0)
+25: fmt.Println(x)
+26: for i := x; i < 3; i++ {
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+26: for i := x; i < 3; i++ {
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+26: for i := x; i < 3; i++ {
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+26: for i := x; i < 3; i++ {
+30: y = x + y //gdb-dbg=(x,y)//gdb-opt=(x,y)
+31: fmt.Println(x, y)
+33: for x := 0; x <= 1; x++ { // From delve scopetest.go
+34: a := y
+35: f1(a)
+37: b := 0
+38: f2(b)
+39: if gretbool() {
+40: c := 0
+41: f3(c)
+46: f5(b)
+48: f6(a)
+33: for x := 0; x <= 1; x++ { // From delve scopetest.go
+34: a := y
+35: f1(a)
+37: b := 0
+38: f2(b)
+39: if gretbool() {
+43: c := 1.1
+44: f4(int(c))
+46: f5(b)
+48: f6(a)
+33: for x := 0; x <= 1; x++ { // From delve scopetest.go
+53: j = id(1)
+54: f = id(2)
+56: for i := 0; i <= 5; i++ {
+57: j += j * (j ^ 3) / 100
+58: if i == f {
+62: sleepytime()
+56: for i := 0; i <= 5; i++ {
+57: j += j * (j ^ 3) / 100
+58: if i == f {
+62: sleepytime()
+56: for i := 0; i <= 5; i++ {
+57: j += j * (j ^ 3) / 100
+58: if i == f {
+59: fmt.Println("foo")
+60: break
+64: helloworld()
+66: }
+15: }
diff --git a/src/cmd/compile/internal/ssa/testdata/scopes.dlv-opt.nexts b/src/cmd/compile/internal/ssa/testdata/scopes.dlv-opt.nexts
new file mode 100644
index 0000000..b5e41aa
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/scopes.dlv-opt.nexts
@@ -0,0 +1,46 @@
+ ./testdata/scopes.go
+22: func test() {
+23: x := id(0)
+24: y := id(0)
+25: fmt.Println(x)
+26: for i := x; i < 3; i++ {
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+26: for i := x; i < 3; i++ {
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+26: for i := x; i < 3; i++ {
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+26: for i := x; i < 3; i++ {
+31: fmt.Println(x, y)
+30: y = x + y //gdb-dbg=(x,y)//gdb-opt=(x,y)
+31: fmt.Println(x, y)
+33: for x := 0; x <= 1; x++ { // From delve scopetest.go
+35: f1(a)
+38: f2(b)
+39: if gretbool() {
+41: f3(c)
+46: f5(b)
+48: f6(a)
+33: for x := 0; x <= 1; x++ { // From delve scopetest.go
+35: f1(a)
+38: f2(b)
+39: if gretbool() {
+44: f4(int(c))
+46: f5(b)
+48: f6(a)
+33: for x := 0; x <= 1; x++ { // From delve scopetest.go
+53: j = id(1)
+54: f = id(2)
+56: for i := 0; i <= 5; i++ {
+58: if i == f {
+62: sleepytime()
+56: for i := 0; i <= 5; i++ {
+58: if i == f {
+62: sleepytime()
+56: for i := 0; i <= 5; i++ {
+58: if i == f {
+59: fmt.Println("foo")
+64: helloworld()
+15: }
diff --git a/src/cmd/compile/internal/ssa/testdata/scopes.gdb-dbg.nexts b/src/cmd/compile/internal/ssa/testdata/scopes.gdb-dbg.nexts
new file mode 100644
index 0000000..6eb4903
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/scopes.gdb-dbg.nexts
@@ -0,0 +1,64 @@
+ src/cmd/compile/internal/ssa/testdata/scopes.go
+22: func test() {
+23: x := id(0)
+24: y := id(0)
+25: fmt.Println(x)
+0:
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+x = 0
+y = 0
+26: for i := x; i < 3; i++ {
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+x = 1
+y = 0
+26: for i := x; i < 3; i++ {
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+x = 4
+y = 1
+26: for i := x; i < 3; i++ {
+30: y = x + y //gdb-dbg=(x,y)//gdb-opt=(x,y)
+x = 0
+y = 5
+31: fmt.Println(x, y)
+0: 5
+34: a := y
+35: f1(a)
+37: b := 0
+38: f2(b)
+39: if gretbool() {
+40: c := 0
+41: f3(c)
+46: f5(b)
+48: f6(a)
+33: for x := 0; x <= 1; x++ { // From delve scopetest.go
+34: a := y
+35: f1(a)
+37: b := 0
+38: f2(b)
+39: if gretbool() {
+43: c := 1.1
+44: f4(int(c))
+46: f5(b)
+48: f6(a)
+33: for x := 0; x <= 1; x++ { // From delve scopetest.go
+53: j = id(1)
+54: f = id(2)
+56: for i := 0; i <= 5; i++ {
+57: j += j * (j ^ 3) / 100
+58: if i == f {
+62: sleepytime()
+56: for i := 0; i <= 5; i++ {
+57: j += j * (j ^ 3) / 100
+58: if i == f {
+62: sleepytime()
+56: for i := 0; i <= 5; i++ {
+57: j += j * (j ^ 3) / 100
+58: if i == f {
+59: fmt.Println("foo")
+60: break
+64: helloworld()
+66: }
+15: }
diff --git a/src/cmd/compile/internal/ssa/testdata/scopes.gdb-opt.nexts b/src/cmd/compile/internal/ssa/testdata/scopes.gdb-opt.nexts
new file mode 100644
index 0000000..5a186b5
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/scopes.gdb-opt.nexts
@@ -0,0 +1,55 @@
+ src/cmd/compile/internal/ssa/testdata/scopes.go
+22: func test() {
+23: x := id(0)
+24: y := id(0)
+25: fmt.Println(x)
+0:
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+x = 0
+y = 0
+26: for i := x; i < 3; i++ {
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+x = 1
+y = 0
+26: for i := x; i < 3; i++ {
+27: x := i * i
+28: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+x = 4
+y = 1
+26: for i := x; i < 3; i++ {
+31: fmt.Println(x, y)
+30: y = x + y //gdb-dbg=(x,y)//gdb-opt=(x,y)
+x = 0
+y = 5
+31: fmt.Println(x, y)
+0: 5
+35: f1(a)
+38: f2(b)
+39: if gretbool() {
+41: f3(c)
+46: f5(b)
+48: f6(a)
+33: for x := 0; x <= 1; x++ { // From delve scopetest.go
+35: f1(a)
+38: f2(b)
+39: if gretbool() {
+44: f4(int(c))
+46: f5(b)
+48: f6(a)
+33: for x := 0; x <= 1; x++ { // From delve scopetest.go
+53: j = id(1)
+54: f = id(2)
+56: for i := 0; i <= 5; i++ {
+58: if i == f {
+62: sleepytime()
+56: for i := 0; i <= 5; i++ {
+58: if i == f {
+62: sleepytime()
+56: for i := 0; i <= 5; i++ {
+58: if i == f {
+59: fmt.Println("foo")
+64: helloworld()
+66: }
+15: }
diff --git a/src/cmd/compile/internal/ssa/testdata/scopes.go b/src/cmd/compile/internal/ssa/testdata/scopes.go
new file mode 100644
index 0000000..e93d699
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/testdata/scopes.go
@@ -0,0 +1,107 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "time"
+)
+
+func main() {
+ growstack() // Use stack early to prevent growth during test, which confuses gdb
+ test()
+}
+
+//go:noinline
+func id(x int) int {
+ return x
+}
+
+func test() {
+ x := id(0)
+ y := id(0)
+ fmt.Println(x)
+ for i := x; i < 3; i++ {
+ x := i * i
+ y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
+ }
+ y = x + y //gdb-dbg=(x,y)//gdb-opt=(x,y)
+ fmt.Println(x, y)
+
+ for x := 0; x <= 1; x++ { // From delve scopetest.go
+ a := y
+ f1(a)
+ {
+ b := 0
+ f2(b)
+ if gretbool() {
+ c := 0
+ f3(c)
+ } else {
+ c := 1.1
+ f4(int(c))
+ }
+ f5(b)
+ }
+ f6(a)
+ }
+
+ { // From delve testnextprog.go
+ var (
+ j = id(1)
+ f = id(2)
+ )
+ for i := 0; i <= 5; i++ {
+ j += j * (j ^ 3) / 100
+ if i == f {
+ fmt.Println("foo")
+ break
+ }
+ sleepytime()
+ }
+ helloworld()
+ }
+}
+
+func sleepytime() {
+ time.Sleep(5 * time.Millisecond)
+}
+
+func helloworld() {
+ fmt.Println("Hello, World!")
+}
+
+//go:noinline
+func f1(x int) {}
+
+//go:noinline
+func f2(x int) {}
+
+//go:noinline
+func f3(x int) {}
+
+//go:noinline
+func f4(x int) {}
+
+//go:noinline
+func f5(x int) {}
+
+//go:noinline
+func f6(x int) {}
+
+var boolvar = true
+
+func gretbool() bool {
+ x := boolvar
+ boolvar = !boolvar
+ return x
+}
+
+var sink string
+
+//go:noinline
+func growstack() {
+ sink = fmt.Sprintf("%#v,%#v,%#v", 1, true, "cat")
+}
diff --git a/src/cmd/compile/internal/ssa/tighten.go b/src/cmd/compile/internal/ssa/tighten.go
new file mode 100644
index 0000000..5dfc453
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/tighten.go
@@ -0,0 +1,164 @@
+// 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
+
+// tighten moves Values closer to the Blocks in which they are used.
+// This can reduce the amount of register spilling required,
+// if it doesn't also create more live values.
+// A Value can be moved to any block that
+// dominates all blocks in which it is used.
+func tighten(f *Func) {
+ canMove := make([]bool, f.NumValues())
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op.isLoweredGetClosurePtr() {
+ // Must stay in the entry block.
+ continue
+ }
+ switch v.Op {
+ case OpPhi, OpArg, OpSelect0, OpSelect1:
+ // Phis need to stay in their block.
+ // Arg must stay in the entry block.
+ // Tuple selectors must stay with the tuple generator.
+ continue
+ }
+ if v.MemoryArg() != nil {
+ // We can't move values which have a memory arg - it might
+ // make two memory values live across a block boundary.
+ continue
+ }
+ // Count arguments which will need a register.
+ narg := 0
+ for _, a := range v.Args {
+ if !a.rematerializeable() {
+ narg++
+ }
+ }
+ if narg >= 2 && !v.Type.IsFlags() {
+ // Don't move values with more than one input, as that may
+ // increase register pressure.
+ // We make an exception for flags, as we want flag generators
+ // moved next to uses (because we only have 1 flag register).
+ continue
+ }
+ canMove[v.ID] = true
+ }
+ }
+
+ // Build data structure for fast least-common-ancestor queries.
+ lca := makeLCArange(f)
+
+ // For each moveable value, record the block that dominates all uses found so far.
+ target := make([]*Block, f.NumValues())
+
+ // Grab loop information.
+ // We use this to make sure we don't tighten a value into a (deeper) loop.
+ idom := f.Idom()
+ loops := f.loopnest()
+ loops.calculateDepths()
+
+ changed := true
+ for changed {
+ changed = false
+
+ // Reset target
+ for i := range target {
+ target[i] = nil
+ }
+
+ // Compute target locations (for moveable values only).
+ // target location = the least common ancestor of all uses in the dominator tree.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ for i, a := range v.Args {
+ if !canMove[a.ID] {
+ continue
+ }
+ use := b
+ if v.Op == OpPhi {
+ use = b.Preds[i].b
+ }
+ if target[a.ID] == nil {
+ target[a.ID] = use
+ } else {
+ target[a.ID] = lca.find(target[a.ID], use)
+ }
+ }
+ }
+ for _, c := range b.ControlValues() {
+ if !canMove[c.ID] {
+ continue
+ }
+ if target[c.ID] == nil {
+ target[c.ID] = b
+ } else {
+ target[c.ID] = lca.find(target[c.ID], b)
+ }
+ }
+ }
+
+ // If the target location is inside a loop,
+ // move the target location up to just before the loop head.
+ for _, b := range f.Blocks {
+ origloop := loops.b2l[b.ID]
+ for _, v := range b.Values {
+ t := target[v.ID]
+ if t == nil {
+ continue
+ }
+ targetloop := loops.b2l[t.ID]
+ for targetloop != nil && (origloop == nil || targetloop.depth > origloop.depth) {
+ t = idom[targetloop.header.ID]
+ target[v.ID] = t
+ targetloop = loops.b2l[t.ID]
+ }
+ }
+ }
+
+ // Move values to target locations.
+ for _, b := range f.Blocks {
+ for i := 0; i < len(b.Values); i++ {
+ v := b.Values[i]
+ t := target[v.ID]
+ if t == nil || t == b {
+ // v is not moveable, or is already in correct place.
+ continue
+ }
+ // Move v to the block which dominates its uses.
+ t.Values = append(t.Values, v)
+ v.Block = t
+ last := len(b.Values) - 1
+ b.Values[i] = b.Values[last]
+ b.Values[last] = nil
+ b.Values = b.Values[:last]
+ changed = true
+ i--
+ }
+ }
+ }
+}
+
+// phiTighten moves constants closer to phi users.
+// This pass avoids having lots of constants live for lots of the program.
+// See issue 16407.
+func phiTighten(f *Func) {
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ continue
+ }
+ for i, a := range v.Args {
+ if !a.rematerializeable() {
+ continue // not a constant we can move around
+ }
+ if a.Block == b.Preds[i].b {
+ continue // already in the right place
+ }
+ // Make a copy of a, put in predecessor block.
+ v.SetArg(i, a.copyInto(b.Preds[i].b))
+ }
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/trim.go b/src/cmd/compile/internal/ssa/trim.go
new file mode 100644
index 0000000..c930a20
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/trim.go
@@ -0,0 +1,172 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import "cmd/internal/src"
+
+// trim removes blocks with no code in them.
+// These blocks were inserted to remove critical edges.
+func trim(f *Func) {
+ n := 0
+ for _, b := range f.Blocks {
+ if !trimmableBlock(b) {
+ f.Blocks[n] = b
+ n++
+ continue
+ }
+
+ bPos := b.Pos
+ bIsStmt := bPos.IsStmt() == src.PosIsStmt
+
+ // Splice b out of the graph. NOTE: `mergePhi` depends on the
+ // order, in which the predecessors edges are merged here.
+ p, i := b.Preds[0].b, b.Preds[0].i
+ s, j := b.Succs[0].b, b.Succs[0].i
+ ns := len(s.Preds)
+ p.Succs[i] = Edge{s, j}
+ s.Preds[j] = Edge{p, i}
+
+ for _, e := range b.Preds[1:] {
+ p, i := e.b, e.i
+ p.Succs[i] = Edge{s, len(s.Preds)}
+ s.Preds = append(s.Preds, Edge{p, i})
+ }
+
+ // Attempt to preserve a statement boundary
+ if bIsStmt {
+ sawStmt := false
+ for _, v := range s.Values {
+ if isPoorStatementOp(v.Op) {
+ continue
+ }
+ if v.Pos.SameFileAndLine(bPos) {
+ v.Pos = v.Pos.WithIsStmt()
+ }
+ sawStmt = true
+ break
+ }
+ if !sawStmt && s.Pos.SameFileAndLine(bPos) {
+ s.Pos = s.Pos.WithIsStmt()
+ }
+ }
+ // If `s` had more than one predecessor, update its phi-ops to
+ // account for the merge.
+ if ns > 1 {
+ for _, v := range s.Values {
+ if v.Op == OpPhi {
+ mergePhi(v, j, b)
+ }
+
+ }
+ // Remove the phi-ops from `b` if they were merged into the
+ // phi-ops of `s`.
+ k := 0
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ if v.Uses == 0 {
+ v.resetArgs()
+ continue
+ }
+ // Pad the arguments of the remaining phi-ops so
+ // they match the new predecessor count of `s`.
+ // Since s did not have a Phi op corresponding to
+ // the phi op in b, the other edges coming into s
+ // must be loopback edges from s, so v is the right
+ // argument to v!
+ args := make([]*Value, len(v.Args))
+ copy(args, v.Args)
+ v.resetArgs()
+ for x := 0; x < j; x++ {
+ v.AddArg(v)
+ }
+ v.AddArg(args[0])
+ for x := j + 1; x < ns; x++ {
+ v.AddArg(v)
+ }
+ for _, a := range args[1:] {
+ v.AddArg(a)
+ }
+ }
+ b.Values[k] = v
+ k++
+ }
+ b.Values = b.Values[:k]
+ }
+
+ // Merge the blocks' values.
+ for _, v := range b.Values {
+ v.Block = s
+ }
+ k := len(b.Values)
+ m := len(s.Values)
+ for i := 0; i < k; i++ {
+ s.Values = append(s.Values, nil)
+ }
+ copy(s.Values[k:], s.Values[:m])
+ copy(s.Values, b.Values)
+ }
+ if n < len(f.Blocks) {
+ f.invalidateCFG()
+ tail := f.Blocks[n:]
+ for i := range tail {
+ tail[i] = nil
+ }
+ f.Blocks = f.Blocks[:n]
+ }
+}
+
+// emptyBlock reports whether the block does not contain actual
+// instructions
+func emptyBlock(b *Block) bool {
+ for _, v := range b.Values {
+ if v.Op != OpPhi {
+ return false
+ }
+ }
+ return true
+}
+
+// trimmableBlock reports whether the block can be trimmed from the CFG,
+// subject to the following criteria:
+// - it should not be the first block
+// - it should be BlockPlain
+// - it should not loop back to itself
+// - it either is the single predecessor of the successor block or
+// contains no actual instructions
+func trimmableBlock(b *Block) bool {
+ if b.Kind != BlockPlain || b == b.Func.Entry {
+ return false
+ }
+ s := b.Succs[0].b
+ return s != b && (len(s.Preds) == 1 || emptyBlock(b))
+}
+
+// mergePhi adjusts the number of `v`s arguments to account for merge
+// of `b`, which was `i`th predecessor of the `v`s block.
+func mergePhi(v *Value, i int, b *Block) {
+ u := v.Args[i]
+ if u.Block == b {
+ if u.Op != OpPhi {
+ b.Func.Fatalf("value %s is not a phi operation", u.LongString())
+ }
+ // If the original block contained u = φ(u0, u1, ..., un) and
+ // the current phi is
+ // v = φ(v0, v1, ..., u, ..., vk)
+ // then the merged phi is
+ // v = φ(v0, v1, ..., u0, ..., vk, u1, ..., un)
+ v.SetArg(i, u.Args[0])
+ v.AddArgs(u.Args[1:]...)
+ } else {
+ // If the original block contained u = φ(u0, u1, ..., un) and
+ // the current phi is
+ // v = φ(v0, v1, ..., vi, ..., vk)
+ // i.e. it does not use a value from the predecessor block,
+ // then the merged phi is
+ // v = φ(v0, v1, ..., vk, vi, vi, ...)
+ for j := 1; j < len(b.Preds); j++ {
+ v.AddArg(v.Args[i])
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/tuple.go b/src/cmd/compile/internal/ssa/tuple.go
new file mode 100644
index 0000000..38deabf
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/tuple.go
@@ -0,0 +1,59 @@
+// Copyright 2020 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
+
+// tightenTupleSelectors ensures that tuple selectors (Select0 and
+// Select1 ops) are in the same block as their tuple generator. The
+// function also ensures that there are no duplicate tuple selectors.
+// These properties are expected by the scheduler but may not have
+// been maintained by the optimization pipeline up to this point.
+//
+// See issues 16741 and 39472.
+func tightenTupleSelectors(f *Func) {
+ selectors := make(map[struct {
+ id ID
+ op Op
+ }]*Value)
+ for _, b := range f.Blocks {
+ for _, selector := range b.Values {
+ if selector.Op != OpSelect0 && selector.Op != OpSelect1 {
+ continue
+ }
+
+ // Get the tuple generator to use as a key for de-duplication.
+ tuple := selector.Args[0]
+ if !tuple.Type.IsTuple() {
+ f.Fatalf("arg of tuple selector %s is not a tuple: %s", selector.String(), tuple.LongString())
+ }
+
+ // If there is a pre-existing selector in the target block then
+ // use that. Do this even if the selector is already in the
+ // target block to avoid duplicate tuple selectors.
+ key := struct {
+ id ID
+ op Op
+ }{tuple.ID, selector.Op}
+ if t := selectors[key]; t != nil {
+ if selector != t {
+ selector.copyOf(t)
+ }
+ continue
+ }
+
+ // If the selector is in the wrong block copy it into the target
+ // block.
+ if selector.Block != tuple.Block {
+ t := selector.copyInto(tuple.Block)
+ selector.copyOf(t)
+ selectors[key] = t
+ continue
+ }
+
+ // The selector is in the target block. Add it to the map so it
+ // cannot be duplicated.
+ selectors[key] = selector
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go
new file mode 100644
index 0000000..edc43aa
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/value.go
@@ -0,0 +1,494 @@
+// 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 (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "fmt"
+ "math"
+ "sort"
+ "strings"
+)
+
+// A Value represents a value in the SSA representation of the program.
+// The ID and Type fields must not be modified. The remainder may be modified
+// if they preserve the value of the Value (e.g. changing a (mul 2 x) to an (add x x)).
+type Value struct {
+ // A unique identifier for the value. For performance we allocate these IDs
+ // densely starting at 1. There is no guarantee that there won't be occasional holes, though.
+ ID ID
+
+ // The operation that computes this value. See op.go.
+ Op Op
+
+ // The type of this value. Normally this will be a Go type, but there
+ // are a few other pseudo-types, see ../types/type.go.
+ Type *types.Type
+
+ // Auxiliary info for this value. The type of this information depends on the opcode and type.
+ // AuxInt is used for integer values, Aux is used for other values.
+ // Floats are stored in AuxInt using math.Float64bits(f).
+ // Unused portions of AuxInt are filled by sign-extending the used portion,
+ // even if the represented value is unsigned.
+ // Users of AuxInt which interpret AuxInt as unsigned (e.g. shifts) must be careful.
+ // Use Value.AuxUnsigned to get the zero-extended value of AuxInt.
+ AuxInt int64
+ Aux interface{}
+
+ // Arguments of this value
+ Args []*Value
+
+ // Containing basic block
+ Block *Block
+
+ // Source position
+ Pos src.XPos
+
+ // Use count. Each appearance in Value.Args and Block.Controls counts once.
+ Uses int32
+
+ // wasm: Value stays on the WebAssembly stack. This value will not get a "register" (WebAssembly variable)
+ // nor a slot on Go stack, and the generation of this value is delayed to its use time.
+ OnWasmStack bool
+
+ // Is this value in the per-function constant cache? If so, remove from cache before changing it or recycling it.
+ InCache bool
+
+ // Storage for the first three args
+ argstorage [3]*Value
+}
+
+// Examples:
+// Opcode aux args
+// OpAdd nil 2
+// OpConst string 0 string constant
+// OpConst int64 0 int64 constant
+// OpAddcq int64 1 amd64 op: v = arg[0] + constant
+
+// short form print. Just v#.
+func (v *Value) String() string {
+ if v == nil {
+ return "nil" // should never happen, but not panicking helps with debugging
+ }
+ return fmt.Sprintf("v%d", v.ID)
+}
+
+func (v *Value) AuxInt8() int8 {
+ if opcodeTable[v.Op].auxType != auxInt8 {
+ v.Fatalf("op %s doesn't have an int8 aux field", v.Op)
+ }
+ return int8(v.AuxInt)
+}
+
+func (v *Value) AuxInt16() int16 {
+ if opcodeTable[v.Op].auxType != auxInt16 {
+ v.Fatalf("op %s doesn't have an int16 aux field", v.Op)
+ }
+ return int16(v.AuxInt)
+}
+
+func (v *Value) AuxInt32() int32 {
+ if opcodeTable[v.Op].auxType != auxInt32 {
+ v.Fatalf("op %s doesn't have an int32 aux field", v.Op)
+ }
+ return int32(v.AuxInt)
+}
+
+// AuxUnsigned returns v.AuxInt as an unsigned value for OpConst*.
+// v.AuxInt is always sign-extended to 64 bits, even if the
+// represented value is unsigned. This undoes that sign extension.
+func (v *Value) AuxUnsigned() uint64 {
+ c := v.AuxInt
+ switch v.Op {
+ case OpConst64:
+ return uint64(c)
+ case OpConst32:
+ return uint64(uint32(c))
+ case OpConst16:
+ return uint64(uint16(c))
+ case OpConst8:
+ return uint64(uint8(c))
+ }
+ v.Fatalf("op %s isn't OpConst*", v.Op)
+ return 0
+}
+
+func (v *Value) AuxFloat() float64 {
+ if opcodeTable[v.Op].auxType != auxFloat32 && opcodeTable[v.Op].auxType != auxFloat64 {
+ v.Fatalf("op %s doesn't have a float aux field", v.Op)
+ }
+ return math.Float64frombits(uint64(v.AuxInt))
+}
+func (v *Value) AuxValAndOff() ValAndOff {
+ if opcodeTable[v.Op].auxType != auxSymValAndOff {
+ v.Fatalf("op %s doesn't have a ValAndOff aux field", v.Op)
+ }
+ return ValAndOff(v.AuxInt)
+}
+
+func (v *Value) AuxArm64BitField() arm64BitField {
+ if opcodeTable[v.Op].auxType != auxARM64BitField {
+ v.Fatalf("op %s doesn't have a ValAndOff aux field", v.Op)
+ }
+ return arm64BitField(v.AuxInt)
+}
+
+// long form print. v# = opcode <type> [aux] args [: reg] (names)
+func (v *Value) LongString() string {
+ s := fmt.Sprintf("v%d = %s", v.ID, v.Op)
+ s += " <" + v.Type.String() + ">"
+ s += v.auxString()
+ for _, a := range v.Args {
+ s += fmt.Sprintf(" %v", a)
+ }
+ var r []Location
+ if v.Block != nil {
+ r = v.Block.Func.RegAlloc
+ }
+ if int(v.ID) < len(r) && r[v.ID] != nil {
+ s += " : " + r[v.ID].String()
+ }
+ var names []string
+ if v.Block != nil {
+ for name, values := range v.Block.Func.NamedValues {
+ for _, value := range values {
+ if value == v {
+ names = append(names, name.String())
+ break // drop duplicates.
+ }
+ }
+ }
+ }
+ if len(names) != 0 {
+ sort.Strings(names) // Otherwise a source of variation in debugging output.
+ s += " (" + strings.Join(names, ", ") + ")"
+ }
+ return s
+}
+
+func (v *Value) auxString() string {
+ switch opcodeTable[v.Op].auxType {
+ case auxBool:
+ if v.AuxInt == 0 {
+ return " [false]"
+ } else {
+ return " [true]"
+ }
+ case auxInt8:
+ return fmt.Sprintf(" [%d]", v.AuxInt8())
+ case auxInt16:
+ return fmt.Sprintf(" [%d]", v.AuxInt16())
+ case auxInt32:
+ return fmt.Sprintf(" [%d]", v.AuxInt32())
+ case auxInt64, auxInt128:
+ return fmt.Sprintf(" [%d]", v.AuxInt)
+ case auxARM64BitField:
+ lsb := v.AuxArm64BitField().getARM64BFlsb()
+ width := v.AuxArm64BitField().getARM64BFwidth()
+ return fmt.Sprintf(" [lsb=%d,width=%d]", lsb, width)
+ case auxFloat32, auxFloat64:
+ return fmt.Sprintf(" [%g]", v.AuxFloat())
+ case auxString:
+ return fmt.Sprintf(" {%q}", v.Aux)
+ case auxSym, auxCall, auxTyp:
+ if v.Aux != nil {
+ return fmt.Sprintf(" {%v}", v.Aux)
+ }
+ case auxSymOff, auxCallOff, auxTypSize:
+ s := ""
+ if v.Aux != nil {
+ s = fmt.Sprintf(" {%v}", v.Aux)
+ }
+ if v.AuxInt != 0 {
+ s += fmt.Sprintf(" [%v]", v.AuxInt)
+ }
+ return s
+ case auxSymValAndOff:
+ s := ""
+ if v.Aux != nil {
+ s = fmt.Sprintf(" {%v}", v.Aux)
+ }
+ return s + fmt.Sprintf(" [%s]", v.AuxValAndOff())
+ case auxCCop:
+ return fmt.Sprintf(" {%s}", Op(v.AuxInt))
+ case auxS390XCCMask, auxS390XRotateParams:
+ return fmt.Sprintf(" {%v}", v.Aux)
+ case auxFlagConstant:
+ return fmt.Sprintf("[%s]", flagConstant(v.AuxInt))
+ }
+ return ""
+}
+
+// If/when midstack inlining is enabled (-l=4), the compiler gets both larger and slower.
+// Not-inlining this method is a help (*Value.reset and *Block.NewValue0 are similar).
+//go:noinline
+func (v *Value) AddArg(w *Value) {
+ if v.Args == nil {
+ v.resetArgs() // use argstorage
+ }
+ v.Args = append(v.Args, w)
+ w.Uses++
+}
+
+//go:noinline
+func (v *Value) AddArg2(w1, w2 *Value) {
+ if v.Args == nil {
+ v.resetArgs() // use argstorage
+ }
+ v.Args = append(v.Args, w1, w2)
+ w1.Uses++
+ w2.Uses++
+}
+
+//go:noinline
+func (v *Value) AddArg3(w1, w2, w3 *Value) {
+ if v.Args == nil {
+ v.resetArgs() // use argstorage
+ }
+ v.Args = append(v.Args, w1, w2, w3)
+ w1.Uses++
+ w2.Uses++
+ w3.Uses++
+}
+
+//go:noinline
+func (v *Value) AddArg4(w1, w2, w3, w4 *Value) {
+ v.Args = append(v.Args, w1, w2, w3, w4)
+ w1.Uses++
+ w2.Uses++
+ w3.Uses++
+ w4.Uses++
+}
+
+//go:noinline
+func (v *Value) AddArg5(w1, w2, w3, w4, w5 *Value) {
+ v.Args = append(v.Args, w1, w2, w3, w4, w5)
+ w1.Uses++
+ w2.Uses++
+ w3.Uses++
+ w4.Uses++
+ w5.Uses++
+}
+
+//go:noinline
+func (v *Value) AddArg6(w1, w2, w3, w4, w5, w6 *Value) {
+ v.Args = append(v.Args, w1, w2, w3, w4, w5, w6)
+ w1.Uses++
+ w2.Uses++
+ w3.Uses++
+ w4.Uses++
+ w5.Uses++
+ w6.Uses++
+}
+
+func (v *Value) AddArgs(a ...*Value) {
+ if v.Args == nil {
+ v.resetArgs() // use argstorage
+ }
+ v.Args = append(v.Args, a...)
+ for _, x := range a {
+ x.Uses++
+ }
+}
+func (v *Value) SetArg(i int, w *Value) {
+ v.Args[i].Uses--
+ v.Args[i] = w
+ w.Uses++
+}
+func (v *Value) RemoveArg(i int) {
+ v.Args[i].Uses--
+ copy(v.Args[i:], v.Args[i+1:])
+ v.Args[len(v.Args)-1] = nil // aid GC
+ v.Args = v.Args[:len(v.Args)-1]
+}
+func (v *Value) SetArgs1(a *Value) {
+ v.resetArgs()
+ v.AddArg(a)
+}
+func (v *Value) SetArgs2(a, b *Value) {
+ v.resetArgs()
+ v.AddArg(a)
+ v.AddArg(b)
+}
+func (v *Value) SetArgs3(a, b, c *Value) {
+ v.resetArgs()
+ v.AddArg(a)
+ v.AddArg(b)
+ v.AddArg(c)
+}
+
+func (v *Value) resetArgs() {
+ for _, a := range v.Args {
+ a.Uses--
+ }
+ v.argstorage[0] = nil
+ v.argstorage[1] = nil
+ v.argstorage[2] = nil
+ v.Args = v.argstorage[:0]
+}
+
+// reset is called from most rewrite rules.
+// Allowing it to be inlined increases the size
+// of cmd/compile by almost 10%, and slows it down.
+//go:noinline
+func (v *Value) reset(op Op) {
+ if v.InCache {
+ v.Block.Func.unCache(v)
+ }
+ v.Op = op
+ v.resetArgs()
+ v.AuxInt = 0
+ v.Aux = nil
+}
+
+// copyOf is called from rewrite rules.
+// It modifies v to be (Copy a).
+//go:noinline
+func (v *Value) copyOf(a *Value) {
+ if v == a {
+ return
+ }
+ if v.InCache {
+ v.Block.Func.unCache(v)
+ }
+ v.Op = OpCopy
+ v.resetArgs()
+ v.AddArg(a)
+ v.AuxInt = 0
+ v.Aux = nil
+ v.Type = a.Type
+}
+
+// copyInto makes a new value identical to v and adds it to the end of b.
+// unlike copyIntoWithXPos this does not check for v.Pos being a statement.
+func (v *Value) copyInto(b *Block) *Value {
+ c := b.NewValue0(v.Pos.WithNotStmt(), v.Op, v.Type) // Lose the position, this causes line number churn otherwise.
+ c.Aux = v.Aux
+ c.AuxInt = v.AuxInt
+ c.AddArgs(v.Args...)
+ for _, a := range v.Args {
+ if a.Type.IsMemory() {
+ v.Fatalf("can't move a value with a memory arg %s", v.LongString())
+ }
+ }
+ return c
+}
+
+// copyIntoWithXPos makes a new value identical to v and adds it to the end of b.
+// The supplied position is used as the position of the new value.
+// Because this is used for rematerialization, check for case that (rematerialized)
+// input to value with position 'pos' carried a statement mark, and that the supplied
+// position (of the instruction using the rematerialized value) is not marked, and
+// preserve that mark if its line matches the supplied position.
+func (v *Value) copyIntoWithXPos(b *Block, pos src.XPos) *Value {
+ if v.Pos.IsStmt() == src.PosIsStmt && pos.IsStmt() != src.PosIsStmt && v.Pos.SameFileAndLine(pos) {
+ pos = pos.WithIsStmt()
+ }
+ c := b.NewValue0(pos, v.Op, v.Type)
+ c.Aux = v.Aux
+ c.AuxInt = v.AuxInt
+ c.AddArgs(v.Args...)
+ for _, a := range v.Args {
+ if a.Type.IsMemory() {
+ v.Fatalf("can't move a value with a memory arg %s", v.LongString())
+ }
+ }
+ return c
+}
+
+func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) }
+func (v *Value) Log() bool { return v.Block.Log() }
+func (v *Value) Fatalf(msg string, args ...interface{}) {
+ v.Block.Func.fe.Fatalf(v.Pos, msg, args...)
+}
+
+// isGenericIntConst reports whether v is a generic integer constant.
+func (v *Value) isGenericIntConst() bool {
+ return v != nil && (v.Op == OpConst64 || v.Op == OpConst32 || v.Op == OpConst16 || v.Op == OpConst8)
+}
+
+// Reg returns the register assigned to v, in cmd/internal/obj/$ARCH numbering.
+func (v *Value) Reg() int16 {
+ reg := v.Block.Func.RegAlloc[v.ID]
+ if reg == nil {
+ v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
+ }
+ return reg.(*Register).objNum
+}
+
+// Reg0 returns the register assigned to the first output of v, in cmd/internal/obj/$ARCH numbering.
+func (v *Value) Reg0() int16 {
+ reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[0]
+ if reg == nil {
+ v.Fatalf("nil first register for value: %s\n%s\n", v.LongString(), v.Block.Func)
+ }
+ return reg.(*Register).objNum
+}
+
+// Reg1 returns the register assigned to the second output of v, in cmd/internal/obj/$ARCH numbering.
+func (v *Value) Reg1() int16 {
+ reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[1]
+ if reg == nil {
+ v.Fatalf("nil second register for value: %s\n%s\n", v.LongString(), v.Block.Func)
+ }
+ return reg.(*Register).objNum
+}
+
+func (v *Value) RegName() string {
+ reg := v.Block.Func.RegAlloc[v.ID]
+ if reg == nil {
+ v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
+ }
+ return reg.(*Register).name
+}
+
+// MemoryArg returns the memory argument for the Value.
+// The returned value, if non-nil, will be memory-typed (or a tuple with a memory-typed second part).
+// Otherwise, nil is returned.
+func (v *Value) MemoryArg() *Value {
+ if v.Op == OpPhi {
+ v.Fatalf("MemoryArg on Phi")
+ }
+ na := len(v.Args)
+ if na == 0 {
+ return nil
+ }
+ if m := v.Args[na-1]; m.Type.IsMemory() {
+ return m
+ }
+ return nil
+}
+
+// LackingPos indicates whether v is a value that is unlikely to have a correct
+// position assigned to it. Ignoring such values leads to more user-friendly positions
+// assigned to nearby values and the blocks containing them.
+func (v *Value) LackingPos() bool {
+ // The exact definition of LackingPos is somewhat heuristically defined and may change
+ // in the future, for example if some of these operations are generated more carefully
+ // with respect to their source position.
+ return v.Op == OpVarDef || v.Op == OpVarKill || v.Op == OpVarLive || v.Op == OpPhi ||
+ (v.Op == OpFwdRef || v.Op == OpCopy) && v.Type == types.TypeMem
+}
+
+// removeable reports whether the value v can be removed from the SSA graph entirely
+// if its use count drops to 0.
+func (v *Value) removeable() bool {
+ if v.Type.IsVoid() {
+ // Void ops, like nil pointer checks, must stay.
+ return false
+ }
+ if v.Type.IsMemory() {
+ // All memory ops aren't needed here, but we do need
+ // to keep calls at least (because they might have
+ // syncronization operations we can't see).
+ return false
+ }
+ if v.Op.HasSideEffects() {
+ // These are mostly synchronization operations.
+ return false
+ }
+ return true
+}
diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go
new file mode 100644
index 0000000..849c9e8
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/writebarrier.go
@@ -0,0 +1,616 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "cmd/internal/obj"
+ "cmd/internal/objabi"
+ "cmd/internal/src"
+ "fmt"
+)
+
+// A ZeroRegion records parts of an object which are known to be zero.
+// A ZeroRegion only applies to a single memory state.
+// Each bit in mask is set if the corresponding pointer-sized word of
+// the base object is known to be zero.
+// In other words, if mask & (1<<i) != 0, then [base+i*ptrSize, base+(i+1)*ptrSize)
+// is known to be zero.
+type ZeroRegion struct {
+ base *Value
+ mask uint64
+}
+
+// needwb reports whether we need write barrier for store op v.
+// v must be Store/Move/Zero.
+// zeroes provides known zero information (keyed by ID of memory-type values).
+func needwb(v *Value, zeroes map[ID]ZeroRegion) bool {
+ t, ok := v.Aux.(*types.Type)
+ if !ok {
+ v.Fatalf("store aux is not a type: %s", v.LongString())
+ }
+ if !t.HasPointers() {
+ return false
+ }
+ if IsStackAddr(v.Args[0]) {
+ return false // write on stack doesn't need write barrier
+ }
+ if v.Op == OpMove && IsReadOnlyGlobalAddr(v.Args[1]) && IsNewObject(v.Args[0], v.MemoryArg()) {
+ // Copying data from readonly memory into a fresh object doesn't need a write barrier.
+ return false
+ }
+ if v.Op == OpStore && IsGlobalAddr(v.Args[1]) {
+ // Storing pointers to non-heap locations into zeroed memory doesn't need a write barrier.
+ ptr := v.Args[0]
+ var off int64
+ size := v.Aux.(*types.Type).Size()
+ for ptr.Op == OpOffPtr {
+ off += ptr.AuxInt
+ ptr = ptr.Args[0]
+ }
+ ptrSize := v.Block.Func.Config.PtrSize
+ if off%ptrSize != 0 || size%ptrSize != 0 {
+ v.Fatalf("unaligned pointer write")
+ }
+ if off < 0 || off+size > 64*ptrSize {
+ // write goes off end of tracked offsets
+ return true
+ }
+ z := zeroes[v.MemoryArg().ID]
+ if ptr != z.base {
+ return true
+ }
+ for i := off; i < off+size; i += ptrSize {
+ if z.mask>>uint(i/ptrSize)&1 == 0 {
+ return true // not known to be zero
+ }
+ }
+ // All written locations are known to be zero - write barrier not needed.
+ return false
+ }
+ return true
+}
+
+// writebarrier pass inserts write barriers for store ops (Store, Move, Zero)
+// when necessary (the condition above). It rewrites store ops to branches
+// and runtime calls, like
+//
+// if writeBarrier.enabled {
+// gcWriteBarrier(ptr, val) // Not a regular Go call
+// } else {
+// *ptr = val
+// }
+//
+// A sequence of WB stores for many pointer fields of a single type will
+// be emitted together, with a single branch.
+func writebarrier(f *Func) {
+ if !f.fe.UseWriteBarrier() {
+ return
+ }
+
+ var sb, sp, wbaddr, const0 *Value
+ var typedmemmove, typedmemclr, gcWriteBarrier *obj.LSym
+ var stores, after []*Value
+ var sset *sparseSet
+ var storeNumber []int32
+
+ zeroes := f.computeZeroMap()
+ for _, b := range f.Blocks { // range loop is safe since the blocks we added contain no stores to expand
+ // first, identify all the stores that need to insert a write barrier.
+ // mark them with WB ops temporarily. record presence of WB ops.
+ nWBops := 0 // count of temporarily created WB ops remaining to be rewritten in the current block
+ for _, v := range b.Values {
+ switch v.Op {
+ case OpStore, OpMove, OpZero:
+ if needwb(v, zeroes) {
+ switch v.Op {
+ case OpStore:
+ v.Op = OpStoreWB
+ case OpMove:
+ v.Op = OpMoveWB
+ case OpZero:
+ v.Op = OpZeroWB
+ }
+ nWBops++
+ }
+ }
+ }
+ if nWBops == 0 {
+ continue
+ }
+
+ if wbaddr == nil {
+ // lazily initialize global values for write barrier test and calls
+ // find SB and SP values in entry block
+ initpos := f.Entry.Pos
+ sp, sb = f.spSb()
+ wbsym := f.fe.Syslook("writeBarrier")
+ wbaddr = f.Entry.NewValue1A(initpos, OpAddr, f.Config.Types.UInt32Ptr, wbsym, sb)
+ gcWriteBarrier = f.fe.Syslook("gcWriteBarrier")
+ typedmemmove = f.fe.Syslook("typedmemmove")
+ typedmemclr = f.fe.Syslook("typedmemclr")
+ const0 = f.ConstInt32(f.Config.Types.UInt32, 0)
+
+ // allocate auxiliary data structures for computing store order
+ sset = f.newSparseSet(f.NumValues())
+ defer f.retSparseSet(sset)
+ storeNumber = make([]int32, f.NumValues())
+ }
+
+ // order values in store order
+ b.Values = storeOrder(b.Values, sset, storeNumber)
+
+ firstSplit := true
+ again:
+ // find the start and end of the last contiguous WB store sequence.
+ // a branch will be inserted there. values after it will be moved
+ // to a new block.
+ var last *Value
+ var start, end int
+ values := b.Values
+ FindSeq:
+ for i := len(values) - 1; i >= 0; i-- {
+ w := values[i]
+ switch w.Op {
+ case OpStoreWB, OpMoveWB, OpZeroWB:
+ start = i
+ if last == nil {
+ last = w
+ end = i + 1
+ }
+ case OpVarDef, OpVarLive, OpVarKill:
+ continue
+ default:
+ if last == nil {
+ continue
+ }
+ break FindSeq
+ }
+ }
+ stores = append(stores[:0], b.Values[start:end]...) // copy to avoid aliasing
+ after = append(after[:0], b.Values[end:]...)
+ b.Values = b.Values[:start]
+
+ // find the memory before the WB stores
+ mem := stores[0].MemoryArg()
+ pos := stores[0].Pos
+ bThen := f.NewBlock(BlockPlain)
+ bElse := f.NewBlock(BlockPlain)
+ bEnd := f.NewBlock(b.Kind)
+ bThen.Pos = pos
+ bElse.Pos = pos
+ bEnd.Pos = b.Pos
+ b.Pos = pos
+
+ // set up control flow for end block
+ bEnd.CopyControls(b)
+ bEnd.Likely = b.Likely
+ for _, e := range b.Succs {
+ bEnd.Succs = append(bEnd.Succs, e)
+ e.b.Preds[e.i].b = bEnd
+ }
+
+ // set up control flow for write barrier test
+ // load word, test word, avoiding partial register write from load byte.
+ cfgtypes := &f.Config.Types
+ flag := b.NewValue2(pos, OpLoad, cfgtypes.UInt32, wbaddr, mem)
+ flag = b.NewValue2(pos, OpNeq32, cfgtypes.Bool, flag, const0)
+ b.Kind = BlockIf
+ b.SetControl(flag)
+ b.Likely = BranchUnlikely
+ b.Succs = b.Succs[:0]
+ b.AddEdgeTo(bThen)
+ b.AddEdgeTo(bElse)
+ // TODO: For OpStoreWB and the buffered write barrier,
+ // we could move the write out of the write barrier,
+ // which would lead to fewer branches. We could do
+ // something similar to OpZeroWB, since the runtime
+ // could provide just the barrier half and then we
+ // could unconditionally do an OpZero (which could
+ // also generate better zeroing code). OpMoveWB is
+ // trickier and would require changing how
+ // cgoCheckMemmove works.
+ bThen.AddEdgeTo(bEnd)
+ bElse.AddEdgeTo(bEnd)
+
+ // for each write barrier store, append write barrier version to bThen
+ // and simple store version to bElse
+ memThen := mem
+ memElse := mem
+
+ // If the source of a MoveWB is volatile (will be clobbered by a
+ // function call), we need to copy it to a temporary location, as
+ // marshaling the args of typedmemmove might clobber the value we're
+ // trying to move.
+ // Look for volatile source, copy it to temporary before we emit any
+ // call.
+ // It is unlikely to have more than one of them. Just do a linear
+ // search instead of using a map.
+ type volatileCopy struct {
+ src *Value // address of original volatile value
+ tmp *Value // address of temporary we've copied the volatile value into
+ }
+ var volatiles []volatileCopy
+ copyLoop:
+ for _, w := range stores {
+ if w.Op == OpMoveWB {
+ val := w.Args[1]
+ if isVolatile(val) {
+ for _, c := range volatiles {
+ if val == c.src {
+ continue copyLoop // already copied
+ }
+ }
+
+ t := val.Type.Elem()
+ tmp := f.fe.Auto(w.Pos, t)
+ memThen = bThen.NewValue1A(w.Pos, OpVarDef, types.TypeMem, tmp, memThen)
+ tmpaddr := bThen.NewValue2A(w.Pos, OpLocalAddr, t.PtrTo(), tmp, sp, memThen)
+ siz := t.Size()
+ memThen = bThen.NewValue3I(w.Pos, OpMove, types.TypeMem, siz, tmpaddr, val, memThen)
+ memThen.Aux = t
+ volatiles = append(volatiles, volatileCopy{val, tmpaddr})
+ }
+ }
+ }
+
+ for _, w := range stores {
+ ptr := w.Args[0]
+ pos := w.Pos
+
+ var fn *obj.LSym
+ var typ *obj.LSym
+ var val *Value
+ switch w.Op {
+ case OpStoreWB:
+ val = w.Args[1]
+ nWBops--
+ case OpMoveWB:
+ fn = typedmemmove
+ val = w.Args[1]
+ typ = w.Aux.(*types.Type).Symbol()
+ nWBops--
+ case OpZeroWB:
+ fn = typedmemclr
+ typ = w.Aux.(*types.Type).Symbol()
+ nWBops--
+ case OpVarDef, OpVarLive, OpVarKill:
+ }
+
+ // then block: emit write barrier call
+ switch w.Op {
+ case OpStoreWB, OpMoveWB, OpZeroWB:
+ if w.Op == OpStoreWB {
+ memThen = bThen.NewValue3A(pos, OpWB, types.TypeMem, gcWriteBarrier, ptr, val, memThen)
+ } else {
+ srcval := val
+ if w.Op == OpMoveWB && isVolatile(srcval) {
+ for _, c := range volatiles {
+ if srcval == c.src {
+ srcval = c.tmp
+ break
+ }
+ }
+ }
+ memThen = wbcall(pos, bThen, fn, typ, ptr, srcval, memThen, sp, sb)
+ }
+ // Note that we set up a writebarrier function call.
+ f.fe.SetWBPos(pos)
+ case OpVarDef, OpVarLive, OpVarKill:
+ memThen = bThen.NewValue1A(pos, w.Op, types.TypeMem, w.Aux, memThen)
+ }
+
+ // else block: normal store
+ switch w.Op {
+ case OpStoreWB:
+ memElse = bElse.NewValue3A(pos, OpStore, types.TypeMem, w.Aux, ptr, val, memElse)
+ case OpMoveWB:
+ memElse = bElse.NewValue3I(pos, OpMove, types.TypeMem, w.AuxInt, ptr, val, memElse)
+ memElse.Aux = w.Aux
+ case OpZeroWB:
+ memElse = bElse.NewValue2I(pos, OpZero, types.TypeMem, w.AuxInt, ptr, memElse)
+ memElse.Aux = w.Aux
+ case OpVarDef, OpVarLive, OpVarKill:
+ memElse = bElse.NewValue1A(pos, w.Op, types.TypeMem, w.Aux, memElse)
+ }
+ }
+
+ // mark volatile temps dead
+ for _, c := range volatiles {
+ tmpNode := c.tmp.Aux
+ memThen = bThen.NewValue1A(memThen.Pos, OpVarKill, types.TypeMem, tmpNode, memThen)
+ }
+
+ // merge memory
+ // Splice memory Phi into the last memory of the original sequence,
+ // which may be used in subsequent blocks. Other memories in the
+ // sequence must be dead after this block since there can be only
+ // one memory live.
+ bEnd.Values = append(bEnd.Values, last)
+ last.Block = bEnd
+ last.reset(OpPhi)
+ last.Pos = last.Pos.WithNotStmt()
+ last.Type = types.TypeMem
+ last.AddArg(memThen)
+ last.AddArg(memElse)
+ for _, w := range stores {
+ if w != last {
+ w.resetArgs()
+ }
+ }
+ for _, w := range stores {
+ if w != last {
+ f.freeValue(w)
+ }
+ }
+
+ // put values after the store sequence into the end block
+ bEnd.Values = append(bEnd.Values, after...)
+ for _, w := range after {
+ w.Block = bEnd
+ }
+
+ // Preemption is unsafe between loading the write
+ // barrier-enabled flag and performing the write
+ // because that would allow a GC phase transition,
+ // which would invalidate the flag. Remember the
+ // conditional block so liveness analysis can disable
+ // safe-points. This is somewhat subtle because we're
+ // splitting b bottom-up.
+ if firstSplit {
+ // Add b itself.
+ b.Func.WBLoads = append(b.Func.WBLoads, b)
+ firstSplit = false
+ } else {
+ // We've already split b, so we just pushed a
+ // write barrier test into bEnd.
+ b.Func.WBLoads = append(b.Func.WBLoads, bEnd)
+ }
+
+ // if we have more stores in this block, do this block again
+ if nWBops > 0 {
+ goto again
+ }
+ }
+}
+
+// computeZeroMap returns a map from an ID of a memory value to
+// a set of locations that are known to be zeroed at that memory value.
+func (f *Func) computeZeroMap() map[ID]ZeroRegion {
+ ptrSize := f.Config.PtrSize
+ // Keep track of which parts of memory are known to be zero.
+ // This helps with removing write barriers for various initialization patterns.
+ // This analysis is conservative. We only keep track, for each memory state, of
+ // which of the first 64 words of a single object are known to be zero.
+ zeroes := map[ID]ZeroRegion{}
+ // Find new objects.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op != OpLoad {
+ continue
+ }
+ mem := v.MemoryArg()
+ if IsNewObject(v, mem) {
+ nptr := v.Type.Elem().Size() / ptrSize
+ if nptr > 64 {
+ nptr = 64
+ }
+ zeroes[mem.ID] = ZeroRegion{base: v, mask: 1<<uint(nptr) - 1}
+ }
+ }
+ }
+ // Find stores to those new objects.
+ for {
+ changed := false
+ for _, b := range f.Blocks {
+ // Note: iterating forwards helps convergence, as values are
+ // typically (but not always!) in store order.
+ for _, v := range b.Values {
+ if v.Op != OpStore {
+ continue
+ }
+ z, ok := zeroes[v.MemoryArg().ID]
+ if !ok {
+ continue
+ }
+ ptr := v.Args[0]
+ var off int64
+ size := v.Aux.(*types.Type).Size()
+ for ptr.Op == OpOffPtr {
+ off += ptr.AuxInt
+ ptr = ptr.Args[0]
+ }
+ if ptr != z.base {
+ // Different base object - we don't know anything.
+ // We could even be writing to the base object we know
+ // about, but through an aliased but offset pointer.
+ // So we have to throw all the zero information we have away.
+ continue
+ }
+ // Round to cover any partially written pointer slots.
+ // Pointer writes should never be unaligned like this, but non-pointer
+ // writes to pointer-containing types will do this.
+ if d := off % ptrSize; d != 0 {
+ off -= d
+ size += d
+ }
+ if d := size % ptrSize; d != 0 {
+ size += ptrSize - d
+ }
+ // Clip to the 64 words that we track.
+ min := off
+ max := off + size
+ if min < 0 {
+ min = 0
+ }
+ if max > 64*ptrSize {
+ max = 64 * ptrSize
+ }
+ // Clear bits for parts that we are writing (and hence
+ // will no longer necessarily be zero).
+ for i := min; i < max; i += ptrSize {
+ bit := i / ptrSize
+ z.mask &^= 1 << uint(bit)
+ }
+ if z.mask == 0 {
+ // No more known zeros - don't bother keeping.
+ continue
+ }
+ // Save updated known zero contents for new store.
+ if zeroes[v.ID] != z {
+ zeroes[v.ID] = z
+ changed = true
+ }
+ }
+ }
+ if !changed {
+ break
+ }
+ }
+ if f.pass.debug > 0 {
+ fmt.Printf("func %s\n", f.Name)
+ for mem, z := range zeroes {
+ fmt.Printf(" memory=v%d ptr=%v zeromask=%b\n", mem, z.base, z.mask)
+ }
+ }
+ return zeroes
+}
+
+// wbcall emits write barrier runtime call in b, returns memory.
+func wbcall(pos src.XPos, b *Block, fn, typ *obj.LSym, ptr, val, mem, sp, sb *Value) *Value {
+ config := b.Func.Config
+
+ // put arguments on stack
+ off := config.ctxt.FixedFrameSize()
+
+ var ACArgs []Param
+ if typ != nil { // for typedmemmove
+ taddr := b.NewValue1A(pos, OpAddr, b.Func.Config.Types.Uintptr, typ, sb)
+ off = round(off, taddr.Type.Alignment())
+ arg := b.NewValue1I(pos, OpOffPtr, taddr.Type.PtrTo(), off, sp)
+ mem = b.NewValue3A(pos, OpStore, types.TypeMem, ptr.Type, arg, taddr, mem)
+ ACArgs = append(ACArgs, Param{Type: b.Func.Config.Types.Uintptr, Offset: int32(off)})
+ off += taddr.Type.Size()
+ }
+
+ off = round(off, ptr.Type.Alignment())
+ arg := b.NewValue1I(pos, OpOffPtr, ptr.Type.PtrTo(), off, sp)
+ mem = b.NewValue3A(pos, OpStore, types.TypeMem, ptr.Type, arg, ptr, mem)
+ ACArgs = append(ACArgs, Param{Type: ptr.Type, Offset: int32(off)})
+ off += ptr.Type.Size()
+
+ if val != nil {
+ off = round(off, val.Type.Alignment())
+ arg = b.NewValue1I(pos, OpOffPtr, val.Type.PtrTo(), off, sp)
+ mem = b.NewValue3A(pos, OpStore, types.TypeMem, val.Type, arg, val, mem)
+ ACArgs = append(ACArgs, Param{Type: val.Type, Offset: int32(off)})
+ off += val.Type.Size()
+ }
+ off = round(off, config.PtrSize)
+
+ // issue call
+ mem = b.NewValue1A(pos, OpStaticCall, types.TypeMem, StaticAuxCall(fn, ACArgs, nil), mem)
+ mem.AuxInt = off - config.ctxt.FixedFrameSize()
+ return mem
+}
+
+// round to a multiple of r, r is a power of 2
+func round(o int64, r int64) int64 {
+ return (o + r - 1) &^ (r - 1)
+}
+
+// IsStackAddr reports whether v is known to be an address of a stack slot.
+func IsStackAddr(v *Value) bool {
+ for v.Op == OpOffPtr || v.Op == OpAddPtr || v.Op == OpPtrIndex || v.Op == OpCopy {
+ v = v.Args[0]
+ }
+ switch v.Op {
+ case OpSP, OpLocalAddr, OpSelectNAddr:
+ return true
+ }
+ return false
+}
+
+// IsGlobalAddr reports whether v is known to be an address of a global (or nil).
+func IsGlobalAddr(v *Value) bool {
+ if v.Op == OpAddr && v.Args[0].Op == OpSB {
+ return true // address of a global
+ }
+ if v.Op == OpConstNil {
+ return true
+ }
+ if v.Op == OpLoad && IsReadOnlyGlobalAddr(v.Args[0]) {
+ return true // loading from a read-only global - the resulting address can't be a heap address.
+ }
+ return false
+}
+
+// IsReadOnlyGlobalAddr reports whether v is known to be an address of a read-only global.
+func IsReadOnlyGlobalAddr(v *Value) bool {
+ if v.Op == OpConstNil {
+ // Nil pointers are read only. See issue 33438.
+ return true
+ }
+ if v.Op == OpAddr && v.Aux.(*obj.LSym).Type == objabi.SRODATA {
+ return true
+ }
+ return false
+}
+
+// IsNewObject reports whether v is a pointer to a freshly allocated & zeroed object at memory state mem.
+func IsNewObject(v *Value, mem *Value) bool {
+ if v.Op != OpLoad {
+ return false
+ }
+ if v.MemoryArg() != mem {
+ return false
+ }
+ if mem.Op != OpStaticCall {
+ return false
+ }
+ if !isSameCall(mem.Aux, "runtime.newobject") {
+ return false
+ }
+ if v.Args[0].Op != OpOffPtr {
+ return false
+ }
+ if v.Args[0].Args[0].Op != OpSP {
+ return false
+ }
+ c := v.Block.Func.Config
+ if v.Args[0].AuxInt != c.ctxt.FixedFrameSize()+c.RegSize { // offset of return value
+ return false
+ }
+ return true
+}
+
+// IsSanitizerSafeAddr reports whether v is known to be an address
+// that doesn't need instrumentation.
+func IsSanitizerSafeAddr(v *Value) bool {
+ for v.Op == OpOffPtr || v.Op == OpAddPtr || v.Op == OpPtrIndex || v.Op == OpCopy {
+ v = v.Args[0]
+ }
+ switch v.Op {
+ case OpSP, OpLocalAddr, OpSelectNAddr:
+ // Stack addresses are always safe.
+ return true
+ case OpITab, OpStringPtr, OpGetClosurePtr:
+ // Itabs, string data, and closure fields are
+ // read-only once initialized.
+ return true
+ case OpAddr:
+ return v.Aux.(*obj.LSym).Type == objabi.SRODATA
+ }
+ return false
+}
+
+// isVolatile reports whether v is a pointer to argument region on stack which
+// will be clobbered by a function call.
+func isVolatile(v *Value) bool {
+ for v.Op == OpOffPtr || v.Op == OpAddPtr || v.Op == OpPtrIndex || v.Op == OpCopy || v.Op == OpSelectNAddr {
+ v = v.Args[0]
+ }
+ return v.Op == OpSP
+}
diff --git a/src/cmd/compile/internal/ssa/writebarrier_test.go b/src/cmd/compile/internal/ssa/writebarrier_test.go
new file mode 100644
index 0000000..0b11afc
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/writebarrier_test.go
@@ -0,0 +1,56 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "cmd/compile/internal/types"
+ "testing"
+)
+
+func TestWriteBarrierStoreOrder(t *testing.T) {
+ // Make sure writebarrier phase works even StoreWB ops are not in dependency order
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
+ Valu("v", OpConstNil, ptrType, 0, nil),
+ Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
+ Valu("wb2", OpStore, types.TypeMem, 0, ptrType, "addr1", "v", "wb1"),
+ Valu("wb1", OpStore, types.TypeMem, 0, ptrType, "addr1", "v", "start"), // wb1 and wb2 are out of order
+ Goto("exit")),
+ Bloc("exit",
+ Exit("wb2")))
+
+ CheckFunc(fun.f)
+ writebarrier(fun.f)
+ CheckFunc(fun.f)
+}
+
+func TestWriteBarrierPhi(t *testing.T) {
+ // Make sure writebarrier phase works for single-block loop, where
+ // a Phi op takes the store in the same block as argument.
+ // See issue #19067.
+ c := testConfig(t)
+ ptrType := c.config.Types.BytePtr
+ fun := c.Fun("entry",
+ Bloc("entry",
+ Valu("start", OpInitMem, types.TypeMem, 0, nil),
+ Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
+ Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
+ Goto("loop")),
+ Bloc("loop",
+ Valu("phi", OpPhi, types.TypeMem, 0, nil, "start", "wb"),
+ Valu("v", OpConstNil, ptrType, 0, nil),
+ Valu("addr", OpAddr, ptrType, 0, nil, "sb"),
+ Valu("wb", OpStore, types.TypeMem, 0, ptrType, "addr", "v", "phi"), // has write barrier
+ Goto("loop")))
+
+ CheckFunc(fun.f)
+ writebarrier(fun.f)
+ CheckFunc(fun.f)
+}
diff --git a/src/cmd/compile/internal/ssa/xposmap.go b/src/cmd/compile/internal/ssa/xposmap.go
new file mode 100644
index 0000000..93582e1
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/xposmap.go
@@ -0,0 +1,116 @@
+// Copyright 2019 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 (
+ "cmd/internal/src"
+ "fmt"
+)
+
+type lineRange struct {
+ first, last uint32
+}
+
+// An xposmap is a map from fileindex and line of src.XPos to int32,
+// implemented sparsely to save space (column and statement status are ignored).
+// The sparse skeleton is constructed once, and then reused by ssa phases
+// that (re)move values with statements attached.
+type xposmap struct {
+ // A map from file index to maps from line range to integers (block numbers)
+ maps map[int32]*biasedSparseMap
+ // The next two fields provide a single-item cache for common case of repeated lines from same file.
+ lastIndex int32 // -1 means no entry in cache
+ lastMap *biasedSparseMap // map found at maps[lastIndex]
+}
+
+// newXposmap constructs an xposmap valid for inputs which have a file index in the keys of x,
+// and line numbers in the range x[file index].
+// The resulting xposmap will panic if a caller attempts to set or add an XPos not in that range.
+func newXposmap(x map[int]lineRange) *xposmap {
+ maps := make(map[int32]*biasedSparseMap)
+ for i, p := range x {
+ maps[int32(i)] = newBiasedSparseMap(int(p.first), int(p.last))
+ }
+ return &xposmap{maps: maps, lastIndex: -1} // zero for the rest is okay
+}
+
+// clear removes data from the map but leaves the sparse skeleton.
+func (m *xposmap) clear() {
+ for _, l := range m.maps {
+ if l != nil {
+ l.clear()
+ }
+ }
+ m.lastIndex = -1
+ m.lastMap = nil
+}
+
+// mapFor returns the line range map for a given file index.
+func (m *xposmap) mapFor(index int32) *biasedSparseMap {
+ if index == m.lastIndex {
+ return m.lastMap
+ }
+ mf := m.maps[index]
+ m.lastIndex = index
+ m.lastMap = mf
+ return mf
+}
+
+// set inserts p->v into the map.
+// If p does not fall within the set of fileindex->lineRange used to construct m, this will panic.
+func (m *xposmap) set(p src.XPos, v int32) {
+ s := m.mapFor(p.FileIndex())
+ if s == nil {
+ panic(fmt.Sprintf("xposmap.set(%d), file index not found in map\n", p.FileIndex()))
+ }
+ s.set(p.Line(), v)
+}
+
+// get returns the int32 associated with the file index and line of p.
+func (m *xposmap) get(p src.XPos) int32 {
+ s := m.mapFor(p.FileIndex())
+ if s == nil {
+ return -1
+ }
+ return s.get(p.Line())
+}
+
+// add adds p to m, treating m as a set instead of as a map.
+// If p does not fall within the set of fileindex->lineRange used to construct m, this will panic.
+// Use clear() in between set/map interpretations of m.
+func (m *xposmap) add(p src.XPos) {
+ m.set(p, 0)
+}
+
+// contains returns whether the file index and line of p are in m,
+// treating m as a set instead of as a map.
+func (m *xposmap) contains(p src.XPos) bool {
+ s := m.mapFor(p.FileIndex())
+ if s == nil {
+ return false
+ }
+ return s.contains(p.Line())
+}
+
+// remove removes the file index and line for p from m,
+// whether m is currently treated as a map or set.
+func (m *xposmap) remove(p src.XPos) {
+ s := m.mapFor(p.FileIndex())
+ if s == nil {
+ return
+ }
+ s.remove(p.Line())
+}
+
+// foreachEntry applies f to each (fileindex, line, value) triple in m.
+func (m *xposmap) foreachEntry(f func(j int32, l uint, v int32)) {
+ for j, mm := range m.maps {
+ s := mm.size()
+ for i := 0; i < s; i++ {
+ l, v := mm.getEntry(i)
+ f(j, l, v)
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/zcse.go b/src/cmd/compile/internal/ssa/zcse.go
new file mode 100644
index 0000000..ec38b7d
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/zcse.go
@@ -0,0 +1,79 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import "cmd/compile/internal/types"
+
+// zcse does an initial pass of common-subexpression elimination on the
+// function for values with zero arguments to allow the more expensive cse
+// to begin with a reduced number of values. Values are just relinked,
+// nothing is deleted. A subsequent deadcode pass is required to actually
+// remove duplicate expressions.
+func zcse(f *Func) {
+ vals := make(map[vkey]*Value)
+
+ for _, b := range f.Blocks {
+ for i := 0; i < len(b.Values); i++ {
+ v := b.Values[i]
+ if opcodeTable[v.Op].argLen == 0 {
+ key := vkey{v.Op, keyFor(v), v.Aux, v.Type}
+ if vals[key] == nil {
+ vals[key] = v
+ if b != f.Entry {
+ // Move v to the entry block so it will dominate every block
+ // where we might use it. This prevents the need for any dominator
+ // calculations in this pass.
+ v.Block = f.Entry
+ f.Entry.Values = append(f.Entry.Values, v)
+ last := len(b.Values) - 1
+ b.Values[i] = b.Values[last]
+ b.Values[last] = nil
+ b.Values = b.Values[:last]
+
+ i-- // process b.Values[i] again
+ }
+ }
+ }
+ }
+ }
+
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ for i, a := range v.Args {
+ if opcodeTable[a.Op].argLen == 0 {
+ key := vkey{a.Op, keyFor(a), a.Aux, a.Type}
+ if rv, ok := vals[key]; ok {
+ v.SetArg(i, rv)
+ }
+ }
+ }
+ }
+ }
+}
+
+// vkey is a type used to uniquely identify a zero arg value.
+type vkey struct {
+ op Op
+ ai int64 // aux int
+ ax interface{} // aux
+ t *types.Type // type
+}
+
+// keyFor returns the AuxInt portion of a key structure uniquely identifying a
+// zero arg value for the supported ops.
+func keyFor(v *Value) int64 {
+ switch v.Op {
+ case OpConst64, OpConst64F, OpConst32F:
+ return v.AuxInt
+ case OpConst32:
+ return int64(int32(v.AuxInt))
+ case OpConst16:
+ return int64(int16(v.AuxInt))
+ case OpConst8, OpConstBool:
+ return int64(int8(v.AuxInt))
+ default:
+ return v.AuxInt
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/zeroextension_test.go b/src/cmd/compile/internal/ssa/zeroextension_test.go
new file mode 100644
index 0000000..2e31621
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/zeroextension_test.go
@@ -0,0 +1,34 @@
+// Copyright 2018 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 "testing"
+
+type extTest struct {
+ f func(uint64, uint64) uint64
+ arg1 uint64
+ arg2 uint64
+ res uint64
+ name string
+}
+
+var extTests = [...]extTest{
+ {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 / op2)) }, arg1: 0x1, arg2: 0xfffffffeffffffff, res: 0xffffffff, name: "div"},
+ {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 * op2)) }, arg1: 0x1, arg2: 0x100000001, res: 0x1, name: "mul"},
+ {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 + op2)) }, arg1: 0x1, arg2: 0xeeeeeeeeffffffff, res: 0x0, name: "add"},
+ {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 - op2)) }, arg1: 0x1, arg2: 0xeeeeeeeeffffffff, res: 0x2, name: "sub"},
+ {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 | op2)) }, arg1: 0x100000000000001, arg2: 0xfffffffffffffff, res: 0xffffffff, name: "or"},
+ {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 ^ op2)) }, arg1: 0x100000000000001, arg2: 0xfffffffffffffff, res: 0xfffffffe, name: "xor"},
+ {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 & op2)) }, arg1: 0x100000000000001, arg2: 0x100000000000001, res: 0x1, name: "and"},
+}
+
+func TestZeroExtension(t *testing.T) {
+ for _, x := range extTests {
+ r := x.f(x.arg1, x.arg2)
+ if x.res != r {
+ t.Errorf("%s: got %d want %d", x.name, r, x.res)
+ }
+ }
+}